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 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2674 if (tb->generic_params)
2675 parent = create_generic_typespec (assembly, tb);
2677 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb));
2679 name = mono_string_to_utf8 (rmb.name);
2680 sig = method_builder_encode_signature (assembly, &rmb);
2682 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2685 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2691 is_field_on_inst (MonoClassField *field)
2693 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2697 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2700 get_field_on_inst_generic_type (MonoClassField *field)
2702 MonoClass *class, *gtd;
2703 MonoDynamicGenericClass *dgclass;
2706 g_assert (is_field_on_inst (field));
2708 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2710 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2711 field_index = field - dgclass->fields;
2712 return dgclass->field_generic_types [field_index];
2715 class = field->parent;
2716 gtd = class->generic_class->container_class;
2718 if (field >= class->fields && field - class->fields < class->field.count) {
2719 field_index = field - class->fields;
2720 return gtd->fields [field_index].type;
2723 g_assert_not_reached ();
2727 #ifndef DISABLE_REFLECTION_EMIT
2729 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoObject *f, MonoClassField *field)
2735 g_assert (field->parent);
2737 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2741 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2742 int index = field - field->parent->fields;
2743 type = field->parent->generic_class->container_class->fields [index].type;
2745 if (is_field_on_inst (field))
2746 type = get_field_on_inst_generic_type (field);
2748 type = mono_field_get_type (field);
2750 token = mono_image_get_memberref_token (assembly, &field->parent->byval_arg,
2751 mono_field_get_name (field),
2752 fieldref_encode_signature (assembly, field->parent->image, type));
2753 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2758 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2762 MonoGenericClass *gclass;
2763 MonoDynamicGenericClass *dgclass;
2767 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2770 if (is_sre_field_builder (mono_object_class (f->fb))) {
2771 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2772 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2773 klass = mono_class_from_mono_type (type);
2774 gclass = type->data.generic_class;
2775 g_assert (gclass->is_dynamic);
2776 dgclass = (MonoDynamicGenericClass *) gclass;
2778 name = mono_string_to_utf8 (fb->name);
2779 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2780 field_encode_signature (assembly, fb));
2782 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2784 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2786 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2787 klass = mono_class_from_mono_type (type);
2789 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2790 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2792 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2793 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2796 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2801 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2805 MonoGenericClass *gclass;
2808 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2810 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2814 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2815 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2816 MonoDynamicGenericClass *dgclass;
2817 ReflectionMethodBuilder rmb;
2820 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2821 klass = mono_class_from_mono_type (type);
2823 gclass = type->data.generic_class;
2824 g_assert (gclass->is_dynamic);
2825 dgclass = (MonoDynamicGenericClass *) gclass;
2827 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2829 name = mono_string_to_utf8 (rmb.name);
2831 sig = method_builder_encode_signature (assembly, &rmb);
2833 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2835 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2836 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2838 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2839 klass = mono_class_from_mono_type (type);
2841 sig = method_encode_signature (assembly, mono_method_signature (mm));
2842 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2844 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2845 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2849 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2854 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2857 MonoGenericContext tmp_context;
2858 MonoType **type_argv;
2859 MonoGenericInst *ginst;
2860 MonoMethod *method, *inflated;
2863 init_type_builder_generics ((MonoObject*)m->inst);
2865 method = inflate_method (m->inst, (MonoObject*)m->mb);
2867 klass = method->klass;
2869 if (m->method_args == NULL)
2872 if (method->is_inflated)
2873 method = ((MonoMethodInflated *) method)->declaring;
2875 count = mono_array_length (m->method_args);
2877 type_argv = g_new0 (MonoType *, count);
2878 for (i = 0; i < count; i++) {
2879 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2880 type_argv [i] = mono_reflection_type_get_handle (garg);
2882 ginst = mono_metadata_get_generic_inst (count, type_argv);
2885 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2886 tmp_context.method_inst = ginst;
2888 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2893 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2895 guint32 sig, token = 0;
2899 if (m->method_args) {
2900 MonoMethod *inflated;
2902 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2903 if (create_methodspec)
2904 token = mono_image_get_methodspec_token (assembly, inflated);
2906 token = mono_image_get_inflated_method_token (assembly, inflated);
2910 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2914 if (is_sre_method_builder (mono_object_class (m->mb))) {
2915 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2916 MonoGenericClass *gclass;
2917 ReflectionMethodBuilder rmb;
2920 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2921 klass = mono_class_from_mono_type (type);
2922 gclass = type->data.generic_class;
2923 g_assert (gclass->is_dynamic);
2925 reflection_methodbuilder_from_method_builder (&rmb, mb);
2927 name = mono_string_to_utf8 (rmb.name);
2929 sig = method_builder_encode_signature (assembly, &rmb);
2931 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2933 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2934 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2936 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2937 klass = mono_class_from_mono_type (type);
2939 sig = method_encode_signature (assembly, mono_method_signature (mm));
2940 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2942 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2943 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2946 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2951 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2955 guint32 nparams = context->method_inst->type_argc;
2958 if (!assembly->save)
2961 sigbuffer_init (&buf, 32);
2963 * FIXME: vararg, explicit_this, differenc call_conv values...
2965 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2966 sigbuffer_add_value (&buf, nparams);
2968 for (i = 0; i < nparams; i++)
2969 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2971 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2972 sigbuffer_free (&buf);
2977 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2979 MonoDynamicTable *table;
2981 guint32 token, mtoken = 0, sig;
2982 MonoMethodInflated *imethod;
2983 MonoMethod *declaring;
2985 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2987 g_assert (method->is_inflated);
2988 imethod = (MonoMethodInflated *) method;
2989 declaring = imethod->declaring;
2991 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2992 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2994 if (!mono_method_signature (declaring)->generic_param_count)
2997 switch (mono_metadata_token_table (mtoken)) {
2998 case MONO_TABLE_MEMBERREF:
2999 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
3001 case MONO_TABLE_METHOD:
3002 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
3005 g_assert_not_reached ();
3008 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
3010 if (assembly->save) {
3011 alloc_table (table, table->rows + 1);
3012 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
3013 values [MONO_METHODSPEC_METHOD] = mtoken;
3014 values [MONO_METHODSPEC_SIGNATURE] = sig;
3017 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3024 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3026 MonoMethodInflated *imethod;
3029 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3033 g_assert (method->is_inflated);
3034 imethod = (MonoMethodInflated *) method;
3036 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3037 token = method_encode_methodspec (assembly, method);
3039 guint32 sig = method_encode_signature (
3040 assembly, mono_method_signature (imethod->declaring));
3041 token = mono_image_get_memberref_token (
3042 assembly, &method->klass->byval_arg, method->name, sig);
3045 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3050 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3052 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3055 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3056 token = mono_image_get_memberref_token (
3057 assembly, &m->klass->byval_arg, m->name, sig);
3063 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3065 MonoDynamicTable *table;
3074 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3075 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3076 * Because of this, we must not insert it into the `typeref' hash table.
3078 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3079 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3083 sigbuffer_init (&buf, 32);
3085 g_assert (tb->generic_params);
3086 klass = mono_class_from_mono_type (type);
3088 if (tb->generic_container)
3089 mono_reflection_create_generic_class (tb);
3091 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3092 g_assert (klass->generic_container);
3093 sigbuffer_add_value (&buf, klass->byval_arg.type);
3094 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3096 count = mono_array_length (tb->generic_params);
3097 sigbuffer_add_value (&buf, count);
3098 for (i = 0; i < count; i++) {
3099 MonoReflectionGenericParam *gparam;
3101 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3103 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3106 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3108 if (assembly->save) {
3109 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3110 alloc_table (table, table->rows + 1);
3111 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3112 values [MONO_TYPESPEC_SIGNATURE] = token;
3114 sigbuffer_free (&buf);
3116 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3117 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3123 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3126 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3128 int i, count, len, pos;
3133 count += mono_array_length (modreq);
3135 count += mono_array_length (modopt);
3138 return mono_metadata_type_dup (NULL, type);
3140 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3142 memcpy (t, type, MONO_SIZEOF_TYPE);
3144 t->num_mods = count;
3147 for (i = 0; i < mono_array_length (modreq); ++i) {
3148 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3149 t->modifiers [pos].required = 1;
3150 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3155 for (i = 0; i < mono_array_length (modopt); ++i) {
3156 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3157 t->modifiers [pos].required = 0;
3158 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3167 init_type_builder_generics (MonoObject *type)
3169 MonoReflectionTypeBuilder *tb;
3171 if (!is_sre_type_builder(mono_object_class (type)))
3173 tb = (MonoReflectionTypeBuilder *)type;
3175 if (tb && tb->generic_container)
3176 mono_reflection_create_generic_class (tb);
3180 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3182 MonoDynamicTable *table;
3184 MonoType *custom = NULL, *type;
3186 guint32 token, pclass, parent, sig;
3189 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3193 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3194 name = mono_string_to_utf8 (fb->name);
3196 /*FIXME this is one more layer of ugliness due how types are created.*/
3197 init_type_builder_generics (fb->type);
3199 /* fb->type does not include the custom modifiers */
3200 /* FIXME: We should do this in one place when a fieldbuilder is created */
3201 type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
3202 if (fb->modreq || fb->modopt)
3203 type = custom = add_custom_modifiers (assembly, type, fb->modreq, fb->modopt);
3205 sig = fieldref_encode_signature (assembly, NULL, type);
3208 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3209 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3211 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3212 parent >>= MONO_TYPEDEFORREF_BITS;
3214 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3216 if (assembly->save) {
3217 alloc_table (table, table->rows + 1);
3218 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3219 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3220 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3221 values [MONO_MEMBERREF_SIGNATURE] = sig;
3224 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3226 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3232 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3239 if (!assembly->save)
3242 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3243 g_assert (helper->type == 2);
3245 if (helper->arguments)
3246 nargs = mono_array_length (helper->arguments);
3250 size = 10 + (nargs * 10);
3252 sigbuffer_init (&buf, 32);
3254 /* Encode calling convention */
3255 /* Change Any to Standard */
3256 if ((helper->call_conv & 0x03) == 0x03)
3257 helper->call_conv = 0x01;
3258 /* explicit_this implies has_this */
3259 if (helper->call_conv & 0x40)
3260 helper->call_conv &= 0x20;
3262 if (helper->call_conv == 0) { /* Unmanaged */
3263 idx = helper->unmanaged_call_conv - 1;
3266 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3267 if (helper->call_conv & 0x02) /* varargs */
3271 sigbuffer_add_byte (&buf, idx);
3272 sigbuffer_add_value (&buf, nargs);
3273 encode_reflection_type (assembly, helper->return_type, &buf);
3274 for (i = 0; i < nargs; ++i) {
3275 MonoArray *modreqs = NULL;
3276 MonoArray *modopts = NULL;
3277 MonoReflectionType *pt;
3279 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3280 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3281 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3282 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3284 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3285 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3286 encode_reflection_type (assembly, pt, &buf);
3288 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3289 sigbuffer_free (&buf);
3295 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3298 MonoDynamicTable *table;
3301 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3302 idx = table->next_idx ++;
3304 alloc_table (table, table->rows);
3305 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3307 values [MONO_STAND_ALONE_SIGNATURE] =
3308 mono_reflection_encode_sighelper (assembly, helper);
3314 reflection_cc_to_file (int call_conv) {
3315 switch (call_conv & 0x3) {
3317 case 1: return MONO_CALL_DEFAULT;
3318 case 2: return MONO_CALL_VARARG;
3320 g_assert_not_reached ();
3324 #endif /* !DISABLE_REFLECTION_EMIT */
3328 MonoMethodSignature *sig;
3333 #ifndef DISABLE_REFLECTION_EMIT
3335 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3340 MonoMethodSignature *sig;
3344 name = mono_string_to_utf8 (m->name);
3345 nparams = mono_array_length (m->parameters);
3346 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3348 sig->sentinelpos = -1;
3349 sig->call_convention = reflection_cc_to_file (m->call_conv);
3350 sig->param_count = nparams;
3351 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3352 mtype = mono_reflection_type_get_handle (m->parent);
3353 for (i = 0; i < nparams; ++i)
3354 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3356 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3358 if (strcmp (name, am->name) == 0 &&
3359 mono_metadata_type_equal (am->parent, mtype) &&
3360 mono_metadata_signature_equal (am->sig, sig)) {
3363 m->table_idx = am->token & 0xffffff;
3367 am = g_new0 (ArrayMethod, 1);
3371 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3372 method_encode_signature (assembly, sig));
3373 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3374 m->table_idx = am->token & 0xffffff;
3379 * Insert into the metadata tables all the info about the TypeBuilder tb.
3380 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3383 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3385 MonoDynamicTable *table;
3387 int i, is_object = 0, is_system = 0;
3390 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3391 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3392 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3393 n = mono_string_to_utf8 (tb->name);
3394 if (strcmp (n, "Object") == 0)
3396 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3398 n = mono_string_to_utf8 (tb->nspace);
3399 if (strcmp (n, "System") == 0)
3401 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3403 if (tb->parent && !(is_system && is_object) &&
3404 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3405 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3407 values [MONO_TYPEDEF_EXTENDS] = 0;
3409 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3410 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3413 * if we have explicitlayout or sequentiallayouts, output data in the
3414 * ClassLayout table.
3416 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3417 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3418 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3420 alloc_table (table, table->rows);
3421 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3422 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3423 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3424 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3427 /* handle interfaces */
3428 if (tb->interfaces) {
3429 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3431 table->rows += mono_array_length (tb->interfaces);
3432 alloc_table (table, table->rows);
3433 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3434 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3435 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3436 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3437 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3438 values += MONO_INTERFACEIMPL_SIZE;
3444 table = &assembly->tables [MONO_TABLE_FIELD];
3445 table->rows += tb->num_fields;
3446 alloc_table (table, table->rows);
3447 for (i = 0; i < tb->num_fields; ++i)
3448 mono_image_get_field_info (
3449 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3452 /* handle constructors */
3454 table = &assembly->tables [MONO_TABLE_METHOD];
3455 table->rows += mono_array_length (tb->ctors);
3456 alloc_table (table, table->rows);
3457 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3458 mono_image_get_ctor_info (domain,
3459 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3462 /* handle methods */
3464 table = &assembly->tables [MONO_TABLE_METHOD];
3465 table->rows += tb->num_methods;
3466 alloc_table (table, table->rows);
3467 for (i = 0; i < tb->num_methods; ++i)
3468 mono_image_get_method_info (
3469 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3472 /* Do the same with properties etc.. */
3473 if (tb->events && mono_array_length (tb->events)) {
3474 table = &assembly->tables [MONO_TABLE_EVENT];
3475 table->rows += mono_array_length (tb->events);
3476 alloc_table (table, table->rows);
3477 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3479 alloc_table (table, table->rows);
3480 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3481 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3482 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3483 for (i = 0; i < mono_array_length (tb->events); ++i)
3484 mono_image_get_event_info (
3485 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3487 if (tb->properties && mono_array_length (tb->properties)) {
3488 table = &assembly->tables [MONO_TABLE_PROPERTY];
3489 table->rows += mono_array_length (tb->properties);
3490 alloc_table (table, table->rows);
3491 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3493 alloc_table (table, table->rows);
3494 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3495 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3496 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3497 for (i = 0; i < mono_array_length (tb->properties); ++i)
3498 mono_image_get_property_info (
3499 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3502 /* handle generic parameters */
3503 if (tb->generic_params) {
3504 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3505 table->rows += mono_array_length (tb->generic_params);
3506 alloc_table (table, table->rows);
3507 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3508 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3510 mono_image_get_generic_param_info (
3511 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3515 mono_image_add_decl_security (assembly,
3516 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3519 MonoDynamicTable *ntable;
3521 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3522 ntable->rows += mono_array_length (tb->subtypes);
3523 alloc_table (ntable, ntable->rows);
3524 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3526 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3527 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3529 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3530 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3531 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3532 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3533 mono_string_to_utf8 (tb->name), tb->table_idx,
3534 ntable->next_idx, ntable->rows);*/
3535 values += MONO_NESTED_CLASS_SIZE;
3543 collect_types (MonoPtrArray *types, MonoReflectionTypeBuilder *type)
3547 mono_ptr_array_append (*types, type);
3549 if (!type->subtypes)
3552 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3553 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3554 collect_types (types, subtype);
3559 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3561 if ((*type1)->table_idx < (*type2)->table_idx)
3564 if ((*type1)->table_idx > (*type2)->table_idx)
3571 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3576 for (i = 0; i < mono_array_length (pinfo); ++i) {
3577 MonoReflectionParamBuilder *pb;
3578 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3581 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3586 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3589 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3591 for (i = 0; i < tb->num_fields; ++i) {
3592 MonoReflectionFieldBuilder* fb;
3593 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3594 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3598 for (i = 0; i < mono_array_length (tb->events); ++i) {
3599 MonoReflectionEventBuilder* eb;
3600 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3601 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3604 if (tb->properties) {
3605 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3606 MonoReflectionPropertyBuilder* pb;
3607 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3608 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3612 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3613 MonoReflectionCtorBuilder* cb;
3614 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3615 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3616 params_add_cattrs (assembly, cb->pinfo);
3621 for (i = 0; i < tb->num_methods; ++i) {
3622 MonoReflectionMethodBuilder* mb;
3623 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3624 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3625 params_add_cattrs (assembly, mb->pinfo);
3630 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3631 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3636 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3640 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3642 if (moduleb->global_methods) {
3643 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3644 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3645 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3646 params_add_cattrs (assembly, mb->pinfo);
3650 if (moduleb->global_fields) {
3651 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3652 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3653 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3657 if (moduleb->types) {
3658 for (i = 0; i < moduleb->num_types; ++i)
3659 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3664 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3666 MonoDynamicTable *table;
3670 char *b = blob_size;
3673 table = &assembly->tables [MONO_TABLE_FILE];
3675 alloc_table (table, table->rows);
3676 values = table->values + table->next_idx * MONO_FILE_SIZE;
3677 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3678 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3679 if (module->image->dynamic) {
3680 /* This depends on the fact that the main module is emitted last */
3681 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3682 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3685 path = g_strdup (module->image->name);
3687 mono_sha1_get_digest_from_file (path, hash);
3690 mono_metadata_encode_value (20, b, &b);
3691 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3692 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3697 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3699 MonoDynamicTable *table;
3702 table = &assembly->tables [MONO_TABLE_MODULE];
3703 mb->table_idx = table->next_idx ++;
3704 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3705 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3708 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3709 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3710 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3711 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3715 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3716 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3718 MonoDynamicTable *table;
3722 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3723 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3726 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3728 alloc_table (table, table->rows);
3729 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3731 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3732 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3733 if (klass->nested_in)
3734 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3736 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3737 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3738 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3740 res = table->next_idx;
3744 /* Emit nested types */
3745 if (klass->ext && klass->ext->nested_classes) {
3748 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3749 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3756 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3757 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3762 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3764 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3766 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3767 parent_index, assembly);
3771 * We need to do this ourselves since klass->nested_classes is not set up.
3774 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3775 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3780 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3781 guint32 module_index, MonoDynamicImage *assembly)
3783 MonoImage *image = module->image;
3787 t = &image->tables [MONO_TABLE_TYPEDEF];
3789 for (i = 0; i < t->rows; ++i) {
3790 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3792 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3793 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3798 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3800 MonoDynamicTable *table;
3802 guint32 scope, scope_idx, impl, current_idx;
3803 gboolean forwarder = TRUE;
3804 gpointer iter = NULL;
3807 if (klass->nested_in) {
3808 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3811 scope = resolution_scope_from_image (assembly, klass->image);
3812 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3813 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3814 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3817 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3820 alloc_table (table, table->rows);
3821 current_idx = table->next_idx;
3822 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3824 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3825 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3826 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3827 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3828 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3832 while ((nested = mono_class_get_nested_types (klass, &iter)))
3833 add_exported_type (assemblyb, assembly, nested, current_idx);
3837 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3842 if (!assemblyb->type_forwarders)
3845 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3846 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3851 type = mono_reflection_type_get_handle (t);
3854 klass = mono_class_from_mono_type (type);
3856 add_exported_type (assemblyb, assembly, klass, 0);
3860 #define align_pointer(base,p)\
3862 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3864 (p) += 4 - (__diff & 3);\
3868 compare_constants (const void *a, const void *b)
3870 const guint32 *a_values = a;
3871 const guint32 *b_values = b;
3872 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3876 compare_semantics (const void *a, const void *b)
3878 const guint32 *a_values = a;
3879 const guint32 *b_values = b;
3880 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3883 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3887 compare_custom_attrs (const void *a, const void *b)
3889 const guint32 *a_values = a;
3890 const guint32 *b_values = b;
3892 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3896 compare_field_marshal (const void *a, const void *b)
3898 const guint32 *a_values = a;
3899 const guint32 *b_values = b;
3901 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3905 compare_nested (const void *a, const void *b)
3907 const guint32 *a_values = a;
3908 const guint32 *b_values = b;
3910 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3914 compare_genericparam (const void *a, const void *b)
3916 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3917 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3919 if ((*b_entry)->owner == (*a_entry)->owner)
3921 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3922 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3924 return (*a_entry)->owner - (*b_entry)->owner;
3928 compare_declsecurity_attrs (const void *a, const void *b)
3930 const guint32 *a_values = a;
3931 const guint32 *b_values = b;
3933 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3937 compare_interface_impl (const void *a, const void *b)
3939 const guint32 *a_values = a;
3940 const guint32 *b_values = b;
3942 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3946 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3950 pad_heap (MonoDynamicStream *sh)
3952 if (sh->index & 3) {
3953 int sz = 4 - (sh->index & 3);
3954 memset (sh->data + sh->index, 0, sz);
3961 MonoDynamicStream *stream;
3965 * build_compressed_metadata() fills in the blob of data that represents the
3966 * raw metadata as it will be saved in the PE file. The five streams are output
3967 * and the metadata tables are comnpressed from the guint32 array representation,
3968 * to the compressed on-disk format.
3971 build_compressed_metadata (MonoDynamicImage *assembly)
3973 MonoDynamicTable *table;
3975 guint64 valid_mask = 0;
3976 guint64 sorted_mask;
3977 guint32 heapt_size = 0;
3978 guint32 meta_size = 256; /* allow for header and other stuff */
3979 guint32 table_offset;
3980 guint32 ntables = 0;
3986 struct StreamDesc stream_desc [5];
3988 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3989 for (i = 0; i < assembly->gen_params->len; i++){
3990 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3991 write_generic_param_entry (assembly, entry);
3994 stream_desc [0].name = "#~";
3995 stream_desc [0].stream = &assembly->tstream;
3996 stream_desc [1].name = "#Strings";
3997 stream_desc [1].stream = &assembly->sheap;
3998 stream_desc [2].name = "#US";
3999 stream_desc [2].stream = &assembly->us;
4000 stream_desc [3].name = "#Blob";
4001 stream_desc [3].stream = &assembly->blob;
4002 stream_desc [4].name = "#GUID";
4003 stream_desc [4].stream = &assembly->guid;
4005 /* tables that are sorted */
4006 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
4007 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
4008 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
4009 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
4010 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
4011 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
4012 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
4014 /* Compute table sizes */
4015 /* the MonoImage has already been created in mono_image_basic_init() */
4016 meta = &assembly->image;
4018 /* sizes should be multiple of 4 */
4019 pad_heap (&assembly->blob);
4020 pad_heap (&assembly->guid);
4021 pad_heap (&assembly->sheap);
4022 pad_heap (&assembly->us);
4024 /* Setup the info used by compute_sizes () */
4025 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
4026 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
4027 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
4029 meta_size += assembly->blob.index;
4030 meta_size += assembly->guid.index;
4031 meta_size += assembly->sheap.index;
4032 meta_size += assembly->us.index;
4034 for (i=0; i < MONO_TABLE_NUM; ++i)
4035 meta->tables [i].rows = assembly->tables [i].rows;
4037 for (i = 0; i < MONO_TABLE_NUM; i++){
4038 if (meta->tables [i].rows == 0)
4040 valid_mask |= (guint64)1 << i;
4042 meta->tables [i].row_size = mono_metadata_compute_size (
4043 meta, i, &meta->tables [i].size_bitfield);
4044 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4046 heapt_size += 24; /* #~ header size */
4047 heapt_size += ntables * 4;
4048 /* make multiple of 4 */
4051 meta_size += heapt_size;
4052 meta->raw_metadata = g_malloc0 (meta_size);
4053 p = (unsigned char*)meta->raw_metadata;
4054 /* the metadata signature */
4055 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4056 /* version numbers and 4 bytes reserved */
4057 int16val = (guint16*)p;
4058 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4059 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4061 /* version string */
4062 int32val = (guint32*)p;
4063 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4065 memcpy (p, meta->version, strlen (meta->version));
4066 p += GUINT32_FROM_LE (*int32val);
4067 align_pointer (meta->raw_metadata, p);
4068 int16val = (guint16*)p;
4069 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4070 *int16val = GUINT16_TO_LE (5); /* number of streams */
4074 * write the stream info.
4076 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4077 table_offset += 3; table_offset &= ~3;
4079 assembly->tstream.index = heapt_size;
4080 for (i = 0; i < 5; ++i) {
4081 int32val = (guint32*)p;
4082 stream_desc [i].stream->offset = table_offset;
4083 *int32val++ = GUINT32_TO_LE (table_offset);
4084 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4085 table_offset += GUINT32_FROM_LE (*int32val);
4086 table_offset += 3; table_offset &= ~3;
4088 strcpy ((char*)p, stream_desc [i].name);
4089 p += strlen (stream_desc [i].name) + 1;
4090 align_pointer (meta->raw_metadata, p);
4093 * now copy the data, the table stream header and contents goes first.
4095 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4096 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4097 int32val = (guint32*)p;
4098 *int32val = GUINT32_TO_LE (0); /* reserved */
4101 *p++ = 2; /* version */
4104 if (meta->idx_string_wide)
4106 if (meta->idx_guid_wide)
4108 if (meta->idx_blob_wide)
4111 *p++ = 1; /* reserved */
4112 int64val = (guint64*)p;
4113 *int64val++ = GUINT64_TO_LE (valid_mask);
4114 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4116 int32val = (guint32*)p;
4117 for (i = 0; i < MONO_TABLE_NUM; i++){
4118 if (meta->tables [i].rows == 0)
4120 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4122 p = (unsigned char*)int32val;
4124 /* sort the tables that still need sorting */
4125 table = &assembly->tables [MONO_TABLE_CONSTANT];
4127 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4128 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4130 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4131 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4133 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4134 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4136 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4137 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4139 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4140 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4141 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4143 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4144 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4146 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4148 /* compress the tables */
4149 for (i = 0; i < MONO_TABLE_NUM; i++){
4152 guint32 bitfield = meta->tables [i].size_bitfield;
4153 if (!meta->tables [i].rows)
4155 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4156 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4157 meta->tables [i].base = (char*)p;
4158 for (row = 1; row <= meta->tables [i].rows; ++row) {
4159 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4160 for (col = 0; col < assembly->tables [i].columns; ++col) {
4161 switch (mono_metadata_table_size (bitfield, col)) {
4163 *p++ = values [col];
4166 *p++ = values [col] & 0xff;
4167 *p++ = (values [col] >> 8) & 0xff;
4170 *p++ = values [col] & 0xff;
4171 *p++ = (values [col] >> 8) & 0xff;
4172 *p++ = (values [col] >> 16) & 0xff;
4173 *p++ = (values [col] >> 24) & 0xff;
4176 g_assert_not_reached ();
4180 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4183 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4184 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4185 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4186 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4187 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4189 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4193 * Some tables in metadata need to be sorted according to some criteria, but
4194 * when methods and fields are first created with reflection, they may be assigned a token
4195 * that doesn't correspond to the final token they will get assigned after the sorting.
4196 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4197 * with the reflection objects that represent them. Once all the tables are set up, the
4198 * reflection objects will contains the correct table index. fixup_method() will fixup the
4199 * tokens for the method with ILGenerator @ilgen.
4202 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4204 guint32 code_idx = GPOINTER_TO_UINT (value);
4205 MonoReflectionILTokenInfo *iltoken;
4206 MonoReflectionFieldBuilder *field;
4207 MonoReflectionCtorBuilder *ctor;
4208 MonoReflectionMethodBuilder *method;
4209 MonoReflectionTypeBuilder *tb;
4210 MonoReflectionArrayMethod *am;
4212 unsigned char *target;
4214 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4215 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4216 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4217 switch (target [3]) {
4218 case MONO_TABLE_FIELD:
4219 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4220 field = (MonoReflectionFieldBuilder *)iltoken->member;
4221 idx = field->table_idx;
4222 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4223 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4224 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4226 g_assert_not_reached ();
4229 case MONO_TABLE_METHOD:
4230 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4231 method = (MonoReflectionMethodBuilder *)iltoken->member;
4232 idx = method->table_idx;
4233 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4234 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4235 idx = ctor->table_idx;
4236 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4237 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4238 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4239 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4241 g_assert_not_reached ();
4244 case MONO_TABLE_TYPEDEF:
4245 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4246 g_assert_not_reached ();
4247 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4248 idx = tb->table_idx;
4250 case MONO_TABLE_MEMBERREF:
4251 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4252 am = (MonoReflectionArrayMethod*)iltoken->member;
4253 idx = am->table_idx;
4254 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4255 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4256 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4257 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4258 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4259 g_assert (m->klass->generic_class || m->klass->generic_container);
4261 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4263 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4264 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4265 g_assert (is_field_on_inst (f));
4267 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4268 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4270 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4272 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4274 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4277 g_assert_not_reached ();
4280 case MONO_TABLE_METHODSPEC:
4281 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4282 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4283 g_assert (mono_method_signature (m)->generic_param_count);
4285 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4287 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4290 g_assert_not_reached ();
4294 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4296 target [0] = idx & 0xff;
4297 target [1] = (idx >> 8) & 0xff;
4298 target [2] = (idx >> 16) & 0xff;
4305 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4306 * value is not known when the table is emitted.
4309 fixup_cattrs (MonoDynamicImage *assembly)
4311 MonoDynamicTable *table;
4313 guint32 type, i, idx, token;
4316 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4318 for (i = 0; i < table->rows; ++i) {
4319 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4321 type = values [MONO_CUSTOM_ATTR_TYPE];
4322 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4323 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4324 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4325 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4328 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod") || !strcmp (ctor->vtable->klass->name, "ConstructorBuilder")) {
4329 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4330 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4331 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4338 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4340 MonoDynamicTable *table;
4343 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4345 alloc_table (table, table->rows);
4346 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4347 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4348 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4349 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4350 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4355 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4357 MonoDynamicTable *table;
4361 char *b = blob_size;
4363 guint32 idx, offset;
4365 if (rsrc->filename) {
4366 name = mono_string_to_utf8 (rsrc->filename);
4367 sname = g_path_get_basename (name);
4369 table = &assembly->tables [MONO_TABLE_FILE];
4371 alloc_table (table, table->rows);
4372 values = table->values + table->next_idx * MONO_FILE_SIZE;
4373 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4374 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4377 mono_sha1_get_digest_from_file (name, hash);
4378 mono_metadata_encode_value (20, b, &b);
4379 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4380 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4382 idx = table->next_idx++;
4384 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4390 data = mono_array_addr (rsrc->data, char, 0);
4391 len = mono_array_length (rsrc->data);
4397 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4398 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4399 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4400 mono_image_add_stream_data (&assembly->resources, data, len);
4404 * The entry should be emitted into the MANIFESTRESOURCE table of
4405 * the main module, but that needs to reference the FILE table
4406 * which isn't emitted yet.
4413 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4417 set_version_from_string (MonoString *version, guint32 *values)
4419 gchar *ver, *p, *str;
4422 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4423 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4424 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4425 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4428 ver = str = mono_string_to_utf8 (version);
4429 for (i = 0; i < 4; ++i) {
4430 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4436 /* handle Revision and Build */
4446 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4450 char *b = blob_size;
4455 len = mono_array_length (pkey);
4456 mono_metadata_encode_value (len, b, &b);
4457 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4458 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4460 assembly->public_key = g_malloc (len);
4461 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4462 assembly->public_key_len = len;
4464 /* Special case: check for ECMA key (16 bytes) */
4465 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4466 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4467 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4468 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4469 /* minimum key size (in 2.0) is 384 bits */
4470 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4472 /* FIXME - verifier */
4473 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4474 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4476 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4482 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4484 MonoDynamicTable *table;
4485 MonoDynamicImage *assembly;
4486 MonoReflectionAssemblyBuilder *assemblyb;
4490 guint32 module_index;
4492 assemblyb = moduleb->assemblyb;
4493 assembly = moduleb->dynamic_image;
4494 domain = mono_object_domain (assemblyb);
4496 /* Emit ASSEMBLY table */
4497 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4498 alloc_table (table, 1);
4499 values = table->values + MONO_ASSEMBLY_SIZE;
4500 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4501 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4502 if (assemblyb->culture) {
4503 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4505 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4507 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4508 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4509 set_version_from_string (assemblyb->version, values);
4511 /* Emit FILE + EXPORTED_TYPE table */
4513 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4515 MonoReflectionModuleBuilder *file_module =
4516 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4517 if (file_module != moduleb) {
4518 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4520 if (file_module->types) {
4521 for (j = 0; j < file_module->num_types; ++j) {
4522 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4523 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4528 if (assemblyb->loaded_modules) {
4529 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4530 MonoReflectionModule *file_module =
4531 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4532 mono_image_fill_file_table (domain, file_module, assembly);
4534 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4537 if (assemblyb->type_forwarders)
4538 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4540 /* Emit MANIFESTRESOURCE table */
4542 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4544 MonoReflectionModuleBuilder *file_module =
4545 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4546 /* The table for the main module is emitted later */
4547 if (file_module != moduleb) {
4549 if (file_module->resources) {
4550 int len = mono_array_length (file_module->resources);
4551 for (j = 0; j < len; ++j) {
4552 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4553 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4560 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4563 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4564 * for the modulebuilder @moduleb.
4565 * At the end of the process, method and field tokens are fixed up and the
4566 * on-disk compressed metadata representation is created.
4569 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4571 MonoDynamicTable *table;
4572 MonoDynamicImage *assembly;
4573 MonoReflectionAssemblyBuilder *assemblyb;
4579 assemblyb = moduleb->assemblyb;
4580 assembly = moduleb->dynamic_image;
4581 domain = mono_object_domain (assemblyb);
4583 if (assembly->text_rva)
4586 assembly->text_rva = START_TEXT_RVA;
4588 if (moduleb->is_main) {
4589 mono_image_emit_manifest (moduleb);
4592 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4593 table->rows = 1; /* .<Module> */
4595 alloc_table (table, table->rows);
4597 * Set the first entry.
4599 values = table->values + table->columns;
4600 values [MONO_TYPEDEF_FLAGS] = 0;
4601 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4602 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4603 values [MONO_TYPEDEF_EXTENDS] = 0;
4604 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4605 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4608 * handle global methods
4609 * FIXME: test what to do when global methods are defined in multiple modules.
4611 if (moduleb->global_methods) {
4612 table = &assembly->tables [MONO_TABLE_METHOD];
4613 table->rows += mono_array_length (moduleb->global_methods);
4614 alloc_table (table, table->rows);
4615 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4616 mono_image_get_method_info (
4617 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4619 if (moduleb->global_fields) {
4620 table = &assembly->tables [MONO_TABLE_FIELD];
4621 table->rows += mono_array_length (moduleb->global_fields);
4622 alloc_table (table, table->rows);
4623 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4624 mono_image_get_field_info (
4625 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4628 table = &assembly->tables [MONO_TABLE_MODULE];
4629 alloc_table (table, 1);
4630 mono_image_fill_module_table (domain, moduleb, assembly);
4632 /* Collect all types into a list sorted by their table_idx */
4633 mono_ptr_array_init (types, moduleb->num_types);
4636 for (i = 0; i < moduleb->num_types; ++i) {
4637 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4638 collect_types (&types, type);
4641 mono_ptr_array_sort (types, (gpointer)compare_types_by_table_idx);
4642 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4643 table->rows += mono_ptr_array_size (types);
4644 alloc_table (table, table->rows);
4647 * Emit type names + namespaces at one place inside the string heap,
4648 * so load_class_names () needs to touch fewer pages.
4650 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4651 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4652 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4654 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4655 MonoReflectionTypeBuilder *tb = mono_ptr_array_get (types, i);
4656 string_heap_insert_mstring (&assembly->sheap, tb->name);
4659 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4660 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4661 mono_image_get_type_info (domain, type, assembly);
4665 * table->rows is already set above and in mono_image_fill_module_table.
4667 /* add all the custom attributes at the end, once all the indexes are stable */
4668 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4670 /* CAS assembly permissions */
4671 if (assemblyb->permissions_minimum)
4672 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4673 if (assemblyb->permissions_optional)
4674 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4675 if (assemblyb->permissions_refused)
4676 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4678 module_add_cattrs (assembly, moduleb);
4681 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4683 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4684 * the final tokens and don't need another fixup pass. */
4686 if (moduleb->global_methods) {
4687 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4688 MonoReflectionMethodBuilder *mb = mono_array_get (
4689 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4690 mono_image_add_methodimpl (assembly, mb);
4694 for (i = 0; i < mono_ptr_array_size (types); ++i) {
4695 MonoReflectionTypeBuilder *type = mono_ptr_array_get (types, i);
4696 if (type->methods) {
4697 for (j = 0; j < type->num_methods; ++j) {
4698 MonoReflectionMethodBuilder *mb = mono_array_get (
4699 type->methods, MonoReflectionMethodBuilder*, j);
4701 mono_image_add_methodimpl (assembly, mb);
4706 mono_ptr_array_destroy (types);
4708 fixup_cattrs (assembly);
4711 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4714 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4716 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4719 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4723 guint32 import_lookup_table;
4727 guint32 import_address_table_rva;
4735 #ifndef DISABLE_REFLECTION_EMIT
4738 * mono_image_insert_string:
4739 * @module: module builder object
4742 * Insert @str into the user string stream of @module.
4745 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4747 MonoDynamicImage *assembly;
4752 MONO_ARCH_SAVE_REGS;
4754 if (!module->dynamic_image)
4755 mono_image_module_basic_init (module);
4757 assembly = module->dynamic_image;
4759 if (assembly->save) {
4760 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4761 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4762 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4764 char *swapped = g_malloc (2 * mono_string_length (str));
4765 const char *p = (const char*)mono_string_chars (str);
4767 swap_with_size (swapped, p, 2, mono_string_length (str));
4768 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4772 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4774 mono_image_add_stream_data (&assembly->us, "", 1);
4776 idx = assembly->us.index ++;
4779 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4781 return MONO_TOKEN_STRING | idx;
4785 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4789 MonoMethodSignature *sig;
4791 klass = obj->vtable->klass;
4792 if (strcmp (klass->name, "MonoMethod") == 0) {
4793 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4794 MonoMethodSignature *old;
4795 guint32 sig_token, parent;
4798 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4800 nargs = mono_array_length (opt_param_types);
4801 old = mono_method_signature (method);
4802 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4804 sig->hasthis = old->hasthis;
4805 sig->explicit_this = old->explicit_this;
4806 sig->call_convention = old->call_convention;
4807 sig->generic_param_count = old->generic_param_count;
4808 sig->param_count = old->param_count + nargs;
4809 sig->sentinelpos = old->param_count;
4810 sig->ret = old->ret;
4812 for (i = 0; i < old->param_count; i++)
4813 sig->params [i] = old->params [i];
4815 for (i = 0; i < nargs; i++) {
4816 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4817 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4820 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4821 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4822 parent >>= MONO_TYPEDEFORREF_BITS;
4824 parent <<= MONO_MEMBERREF_PARENT_BITS;
4825 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4827 sig_token = method_encode_signature (assembly, sig);
4828 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4829 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4830 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4831 ReflectionMethodBuilder rmb;
4832 guint32 parent, sig_token;
4833 int nopt_args, nparams, ngparams, i;
4836 reflection_methodbuilder_from_method_builder (&rmb, mb);
4837 rmb.opt_types = opt_param_types;
4838 nopt_args = mono_array_length (opt_param_types);
4840 nparams = rmb.parameters ? mono_array_length (rmb.parameters): 0;
4841 ngparams = rmb.generic_params ? mono_array_length (rmb.generic_params): 0;
4842 sig = mono_metadata_signature_alloc (&assembly->image, nparams + nopt_args);
4844 sig->hasthis = !(rmb.attrs & METHOD_ATTRIBUTE_STATIC);
4845 sig->explicit_this = (rmb.call_conv & 0x40) == 0x40;
4846 sig->call_convention = rmb.call_conv;
4847 sig->generic_param_count = ngparams;
4848 sig->param_count = nparams + nopt_args;
4849 sig->sentinelpos = nparams;
4850 sig->ret = mono_reflection_type_get_handle (rmb.rtype);
4852 for (i = 0; i < nparams; i++) {
4853 MonoReflectionType *rt = mono_array_get (rmb.parameters, MonoReflectionType *, i);
4854 sig->params [i] = mono_reflection_type_get_handle (rt);
4857 for (i = 0; i < nopt_args; i++) {
4858 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4859 sig->params [nparams + i] = mono_reflection_type_get_handle (rt);
4862 sig_token = method_builder_encode_signature (assembly, &rmb);
4864 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4865 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4867 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4868 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4870 name = mono_string_to_utf8 (rmb.name);
4871 token = mono_image_get_varargs_method_token (
4872 assembly, parent, name, sig_token);
4875 g_error ("requested method token for %s\n", klass->name);
4878 g_hash_table_insert (assembly->vararg_aux_hash, GUINT_TO_POINTER (token), sig);
4879 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4884 * mono_image_create_token:
4885 * @assembly: a dynamic assembly
4887 * @register_token: Whenever to register the token in the assembly->tokens hash.
4889 * Get a token to insert in the IL code stream for the given MemberInfo.
4890 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4891 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4895 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4896 gboolean create_open_instance, gboolean register_token)
4901 klass = obj->vtable->klass;
4903 /* Check for user defined reflection objects */
4904 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4905 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4906 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4908 if (strcmp (klass->name, "MethodBuilder") == 0) {
4909 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4910 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4912 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4913 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4915 token = mono_image_get_methodbuilder_token (assembly, mb, create_open_instance);
4916 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4917 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4918 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4919 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4921 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4922 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4924 token = mono_image_get_ctorbuilder_token (assembly, mb);
4925 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4926 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4927 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4928 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4929 if (tb->generic_params) {
4930 token = mono_image_get_generic_field_token (assembly, fb);
4932 if ((tb->module->dynamic_image == assembly)) {
4933 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4935 token = mono_image_get_fieldref_token (assembly, (MonoObject*)fb, fb->handle);
4938 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4939 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4940 if (create_open_instance && tb->generic_params) {
4942 init_type_builder_generics (obj);
4943 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4944 token = mono_image_typedef_or_ref_full (assembly, type, TRUE);
4945 token = mono_metadata_token_from_dor (token);
4946 } else if (tb->module->dynamic_image == assembly) {
4947 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4950 type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4951 token = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, type));
4953 } else if (strcmp (klass->name, "MonoType") == 0) {
4954 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4955 MonoClass *mc = mono_class_from_mono_type (type);
4956 token = mono_metadata_token_from_dor (
4957 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL || create_open_instance));
4958 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4959 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4960 token = mono_metadata_token_from_dor (
4961 mono_image_typedef_or_ref (assembly, type));
4962 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4963 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4964 token = mono_metadata_token_from_dor (
4965 mono_image_typedef_or_ref (assembly, type));
4966 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4967 strcmp (klass->name, "MonoMethod") == 0 ||
4968 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4969 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4970 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4971 if (m->method->is_inflated) {
4972 if (create_open_instance)
4973 token = mono_image_get_methodspec_token (assembly, m->method);
4975 token = mono_image_get_inflated_method_token (assembly, m->method);
4976 } else if ((m->method->klass->image == &assembly->image) &&
4977 !m->method->klass->generic_class) {
4978 static guint32 method_table_idx = 0xffffff;
4979 if (m->method->klass->wastypebuilder) {
4980 /* we use the same token as the one that was assigned
4981 * to the Methodbuilder.
4982 * FIXME: do the equivalent for Fields.
4984 token = m->method->token;
4987 * Each token should have a unique index, but the indexes are
4988 * assigned by managed code, so we don't know about them. An
4989 * easy solution is to count backwards...
4991 method_table_idx --;
4992 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4995 token = mono_image_get_methodref_token (assembly, m->method, create_open_instance);
4997 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4998 } else if (strcmp (klass->name, "MonoField") == 0) {
4999 MonoReflectionField *f = (MonoReflectionField *)obj;
5000 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
5001 static guint32 field_table_idx = 0xffffff;
5003 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
5005 token = mono_image_get_fieldref_token (assembly, (MonoObject*)f, f->field);
5007 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
5008 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
5009 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
5010 token = mono_image_get_array_token (assembly, m);
5011 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
5012 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
5013 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
5014 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
5015 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
5016 token = mono_metadata_token_from_dor (
5017 mono_image_typedef_or_ref (assembly, type));
5018 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
5019 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
5020 token = mono_image_get_field_on_inst_token (assembly, f);
5021 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
5022 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
5023 token = mono_image_get_ctor_on_inst_token (assembly, c, create_open_instance);
5024 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
5025 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
5026 token = mono_image_get_method_on_inst_token (assembly, m, create_open_instance);
5027 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
5028 MonoReflectionType *type = (MonoReflectionType *)obj;
5029 token = mono_metadata_token_from_dor (
5030 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
5032 g_error ("requested token for %s\n", klass->name);
5036 mono_image_register_token (assembly, token, obj);
5042 * mono_image_register_token:
5044 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
5045 * the Module.ResolveXXXToken () methods to work.
5048 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
5050 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
5052 /* There could be multiple MethodInfo objects with the same token */
5053 //g_assert (prev == obj);
5055 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
5059 static MonoDynamicImage*
5060 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
5062 static const guchar entrycode [16] = {0xff, 0x25, 0};
5063 MonoDynamicImage *image;
5066 const char *version;
5068 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
5069 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
5071 version = mono_get_runtime_info ()->runtime_version;
5074 /* The MonoGHashTable's need GC tracking */
5075 image = GC_MALLOC (sizeof (MonoDynamicImage));
5077 image = g_new0 (MonoDynamicImage, 1);
5080 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5082 /*g_print ("created image %p\n", image);*/
5083 /* keep in sync with image.c */
5084 image->image.name = assembly_name;
5085 image->image.assembly_name = image->image.name; /* they may be different */
5086 image->image.module_name = module_name;
5087 image->image.version = g_strdup (version);
5088 image->image.md_version_major = 1;
5089 image->image.md_version_minor = 1;
5090 image->image.dynamic = TRUE;
5092 image->image.references = g_new0 (MonoAssembly*, 1);
5093 image->image.references [0] = NULL;
5095 mono_image_init (&image->image);
5097 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5098 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5099 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5100 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5101 image->vararg_aux_hash = g_hash_table_new (NULL, NULL);
5102 image->handleref = g_hash_table_new (NULL, NULL);
5103 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5104 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5105 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5106 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5107 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5108 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5109 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5110 image->gen_params = g_ptr_array_new ();
5112 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5113 string_heap_init (&image->sheap);
5114 mono_image_add_stream_data (&image->us, "", 1);
5115 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5116 /* import tables... */
5117 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5118 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5119 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5120 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5121 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5122 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5123 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5124 stream_data_align (&image->code);
5126 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5128 for (i=0; i < MONO_TABLE_NUM; ++i) {
5129 image->tables [i].next_idx = 1;
5130 image->tables [i].columns = table_sizes [i];
5133 image->image.assembly = (MonoAssembly*)assembly;
5134 image->run = assembly->run;
5135 image->save = assembly->save;
5136 image->pe_kind = 0x1; /* ILOnly */
5137 image->machine = 0x14c; /* I386 */
5139 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5146 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5152 mono_dynamic_image_free (MonoDynamicImage *image)
5154 MonoDynamicImage *di = image;
5159 mono_g_hash_table_destroy (di->methodspec);
5161 g_hash_table_destroy (di->typespec);
5163 g_hash_table_destroy (di->typeref);
5165 g_hash_table_destroy (di->handleref);
5166 if (di->handleref_managed)
5167 mono_g_hash_table_destroy (di->handleref_managed);
5169 mono_g_hash_table_destroy (di->tokens);
5170 if (di->generic_def_objects)
5171 mono_g_hash_table_destroy (di->generic_def_objects);
5172 if (di->blob_cache) {
5173 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5174 g_hash_table_destroy (di->blob_cache);
5176 if (di->standalonesig_cache)
5177 g_hash_table_destroy (di->standalonesig_cache);
5178 for (list = di->array_methods; list; list = list->next) {
5179 ArrayMethod *am = (ArrayMethod *)list->data;
5184 g_list_free (di->array_methods);
5185 if (di->gen_params) {
5186 for (i = 0; i < di->gen_params->len; i++) {
5187 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5188 mono_gc_deregister_root ((char*) &entry->gparam);
5191 g_ptr_array_free (di->gen_params, TRUE);
5193 if (di->token_fixups)
5194 mono_g_hash_table_destroy (di->token_fixups);
5195 if (di->method_to_table_idx)
5196 g_hash_table_destroy (di->method_to_table_idx);
5197 if (di->field_to_table_idx)
5198 g_hash_table_destroy (di->field_to_table_idx);
5199 if (di->method_aux_hash)
5200 g_hash_table_destroy (di->method_aux_hash);
5201 if (di->vararg_aux_hash)
5202 g_hash_table_destroy (di->vararg_aux_hash);
5203 g_free (di->strong_name);
5204 g_free (di->win32_res);
5206 g_free (di->public_key);
5208 /*g_print ("string heap destroy for image %p\n", di);*/
5209 mono_dynamic_stream_reset (&di->sheap);
5210 mono_dynamic_stream_reset (&di->code);
5211 mono_dynamic_stream_reset (&di->resources);
5212 mono_dynamic_stream_reset (&di->us);
5213 mono_dynamic_stream_reset (&di->blob);
5214 mono_dynamic_stream_reset (&di->tstream);
5215 mono_dynamic_stream_reset (&di->guid);
5216 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5217 g_free (di->tables [i].values);
5221 #ifndef DISABLE_REFLECTION_EMIT
5224 * mono_image_basic_init:
5225 * @assembly: an assembly builder object
5227 * Create the MonoImage that represents the assembly builder and setup some
5228 * of the helper hash table and the basic metadata streams.
5231 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5233 MonoDynamicAssembly *assembly;
5234 MonoDynamicImage *image;
5235 MonoDomain *domain = mono_object_domain (assemblyb);
5237 MONO_ARCH_SAVE_REGS;
5239 if (assemblyb->dynamic_assembly)
5243 /* assembly->assembly.image might be GC allocated */
5244 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5246 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5249 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5251 assembly->assembly.ref_count = 1;
5252 assembly->assembly.dynamic = TRUE;
5253 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5254 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5255 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5256 if (assemblyb->culture)
5257 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5259 assembly->assembly.aname.culture = g_strdup ("");
5261 if (assemblyb->version) {
5262 char *vstr = mono_string_to_utf8 (assemblyb->version);
5263 char **version = g_strsplit (vstr, ".", 4);
5264 char **parts = version;
5265 assembly->assembly.aname.major = atoi (*parts++);
5266 assembly->assembly.aname.minor = atoi (*parts++);
5267 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5268 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5270 g_strfreev (version);
5273 assembly->assembly.aname.major = 0;
5274 assembly->assembly.aname.minor = 0;
5275 assembly->assembly.aname.build = 0;
5276 assembly->assembly.aname.revision = 0;
5279 assembly->run = assemblyb->access != 2;
5280 assembly->save = assemblyb->access != 1;
5281 assembly->domain = domain;
5283 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5284 image->initial_image = TRUE;
5285 assembly->assembly.aname.name = image->image.name;
5286 assembly->assembly.image = &image->image;
5287 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5288 /* -1 to correct for the trailing NULL byte */
5289 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5290 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5292 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5295 mono_domain_assemblies_lock (domain);
5296 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5297 mono_domain_assemblies_unlock (domain);
5299 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5301 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5303 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5306 #endif /* !DISABLE_REFLECTION_EMIT */
5308 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5311 calc_section_size (MonoDynamicImage *assembly)
5315 /* alignment constraints */
5316 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5317 g_assert ((assembly->code.index % 4) == 0);
5318 assembly->meta_size += 3;
5319 assembly->meta_size &= ~3;
5320 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5321 g_assert ((assembly->resources.index % 4) == 0);
5323 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5324 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5327 if (assembly->win32_res) {
5328 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5330 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5331 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5335 assembly->sections [MONO_SECTION_RELOC].size = 12;
5336 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5346 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5350 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5352 ResTreeNode *t1 = (ResTreeNode*)a;
5353 ResTreeNode *t2 = (ResTreeNode*)b;
5355 return t1->id - t2->id;
5359 * resource_tree_create:
5361 * Organize the resources into a resource tree.
5363 static ResTreeNode *
5364 resource_tree_create (MonoArray *win32_resources)
5366 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5370 tree = g_new0 (ResTreeNode, 1);
5372 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5373 MonoReflectionWin32Resource *win32_res =
5374 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5378 /* FIXME: BUG: this stores managed references in unmanaged memory */
5379 lang_node = g_new0 (ResTreeNode, 1);
5380 lang_node->id = win32_res->lang_id;
5381 lang_node->win32_res = win32_res;
5383 /* Create type node if neccesary */
5385 for (l = tree->children; l; l = l->next)
5386 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5387 type_node = (ResTreeNode*)l->data;
5392 type_node = g_new0 (ResTreeNode, 1);
5393 type_node->id = win32_res->res_type;
5396 * The resource types have to be sorted otherwise
5397 * Windows Explorer can't display the version information.
5399 tree->children = g_slist_insert_sorted (tree->children,
5400 type_node, resource_tree_compare_by_id);
5403 /* Create res node if neccesary */
5405 for (l = type_node->children; l; l = l->next)
5406 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5407 res_node = (ResTreeNode*)l->data;
5412 res_node = g_new0 (ResTreeNode, 1);
5413 res_node->id = win32_res->res_id;
5414 type_node->children = g_slist_append (type_node->children, res_node);
5417 res_node->children = g_slist_append (res_node->children, lang_node);
5424 * resource_tree_encode:
5426 * Encode the resource tree into the format used in the PE file.
5429 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5432 MonoPEResourceDir dir;
5433 MonoPEResourceDirEntry dir_entry;
5434 MonoPEResourceDataEntry data_entry;
5436 guint32 res_id_entries;
5439 * For the format of the resource directory, see the article
5440 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5444 memset (&dir, 0, sizeof (dir));
5445 memset (&dir_entry, 0, sizeof (dir_entry));
5446 memset (&data_entry, 0, sizeof (data_entry));
5448 g_assert (sizeof (dir) == 16);
5449 g_assert (sizeof (dir_entry) == 8);
5450 g_assert (sizeof (data_entry) == 16);
5452 node->offset = p - begin;
5454 /* IMAGE_RESOURCE_DIRECTORY */
5455 res_id_entries = g_slist_length (node->children);
5456 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5458 memcpy (p, &dir, sizeof (dir));
5461 /* Reserve space for entries */
5463 p += sizeof (dir_entry) * res_id_entries;
5465 /* Write children */
5466 for (l = node->children; l; l = l->next) {
5467 ResTreeNode *child = (ResTreeNode*)l->data;
5469 if (child->win32_res) {
5472 child->offset = p - begin;
5474 /* IMAGE_RESOURCE_DATA_ENTRY */
5475 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5476 size = mono_array_length (child->win32_res->res_data);
5477 data_entry.rde_size = GUINT32_TO_LE (size);
5479 memcpy (p, &data_entry, sizeof (data_entry));
5480 p += sizeof (data_entry);
5482 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5485 resource_tree_encode (child, begin, p, &p);
5489 /* IMAGE_RESOURCE_ENTRY */
5490 for (l = node->children; l; l = l->next) {
5491 ResTreeNode *child = (ResTreeNode*)l->data;
5493 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5494 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5496 memcpy (entries, &dir_entry, sizeof (dir_entry));
5497 entries += sizeof (dir_entry);
5504 resource_tree_free (ResTreeNode * node)
5507 for (list = node->children; list; list = list->next)
5508 resource_tree_free ((ResTreeNode*)list->data);
5509 g_slist_free(node->children);
5514 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5519 MonoReflectionWin32Resource *win32_res;
5522 if (!assemblyb->win32_resources)
5526 * Resources are stored in a three level tree inside the PE file.
5527 * - level one contains a node for each type of resource
5528 * - level two contains a node for each resource
5529 * - level three contains a node for each instance of a resource for a
5530 * specific language.
5533 tree = resource_tree_create (assemblyb->win32_resources);
5535 /* Estimate the size of the encoded tree */
5537 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5538 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5539 size += mono_array_length (win32_res->res_data);
5541 /* Directory structure */
5542 size += mono_array_length (assemblyb->win32_resources) * 256;
5543 p = buf = g_malloc (size);
5545 resource_tree_encode (tree, p, p, &p);
5547 g_assert (p - buf <= size);
5549 assembly->win32_res = g_malloc (p - buf);
5550 assembly->win32_res_size = p - buf;
5551 memcpy (assembly->win32_res, buf, p - buf);
5554 resource_tree_free (tree);
5558 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5560 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5563 p += sizeof (MonoPEResourceDir);
5564 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5565 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5566 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5567 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5568 fixup_resource_directory (res_section, child, rva);
5570 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5571 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5574 p += sizeof (MonoPEResourceDirEntry);
5579 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5582 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5583 g_error ("WriteFile returned %d\n", GetLastError ());
5587 * mono_image_create_pefile:
5588 * @mb: a module builder object
5590 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5591 * assembly->pefile where it can be easily retrieved later in chunks.
5594 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5596 MonoMSDOSHeader *msdos;
5597 MonoDotNetHeader *header;
5598 MonoSectionTable *section;
5599 MonoCLIHeader *cli_header;
5600 guint32 size, image_size, virtual_base, text_offset;
5601 guint32 header_start, section_start, file_offset, virtual_offset;
5602 MonoDynamicImage *assembly;
5603 MonoReflectionAssemblyBuilder *assemblyb;
5604 MonoDynamicStream pefile_stream = {0};
5605 MonoDynamicStream *pefile = &pefile_stream;
5607 guint32 *rva, value;
5609 static const unsigned char msheader[] = {
5610 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5611 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5612 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5613 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5614 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5615 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5616 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5617 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5620 assemblyb = mb->assemblyb;
5622 mono_image_basic_init (assemblyb);
5623 assembly = mb->dynamic_image;
5625 assembly->pe_kind = assemblyb->pe_kind;
5626 assembly->machine = assemblyb->machine;
5627 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5628 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5630 mono_image_build_metadata (mb);
5632 if (mb->is_main && assemblyb->resources) {
5633 int len = mono_array_length (assemblyb->resources);
5634 for (i = 0; i < len; ++i)
5635 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5638 if (mb->resources) {
5639 int len = mono_array_length (mb->resources);
5640 for (i = 0; i < len; ++i)
5641 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5644 build_compressed_metadata (assembly);
5647 assembly_add_win32_resources (assembly, assemblyb);
5649 nsections = calc_section_size (assembly);
5651 /* The DOS header and stub */
5652 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5653 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5655 /* the dotnet header */
5656 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5658 /* the section tables */
5659 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5661 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5662 virtual_offset = VIRT_ALIGN;
5665 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5666 if (!assembly->sections [i].size)
5669 file_offset += FILE_ALIGN - 1;
5670 file_offset &= ~(FILE_ALIGN - 1);
5671 virtual_offset += VIRT_ALIGN - 1;
5672 virtual_offset &= ~(VIRT_ALIGN - 1);
5674 assembly->sections [i].offset = file_offset;
5675 assembly->sections [i].rva = virtual_offset;
5677 file_offset += assembly->sections [i].size;
5678 virtual_offset += assembly->sections [i].size;
5679 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5682 file_offset += FILE_ALIGN - 1;
5683 file_offset &= ~(FILE_ALIGN - 1);
5685 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5687 /* back-patch info */
5688 msdos = (MonoMSDOSHeader*)pefile->data;
5689 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5691 header = (MonoDotNetHeader*)(pefile->data + header_start);
5692 header->pesig [0] = 'P';
5693 header->pesig [1] = 'E';
5695 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5696 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5697 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5698 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5699 if (assemblyb->pekind == 1) {
5701 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5704 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5707 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5709 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5710 header->pe.pe_major = 6;
5711 header->pe.pe_minor = 0;
5712 size = assembly->sections [MONO_SECTION_TEXT].size;
5713 size += FILE_ALIGN - 1;
5714 size &= ~(FILE_ALIGN - 1);
5715 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5716 size = assembly->sections [MONO_SECTION_RSRC].size;
5717 size += FILE_ALIGN - 1;
5718 size &= ~(FILE_ALIGN - 1);
5719 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5720 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5721 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5722 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5723 /* pe_rva_entry_point always at the beginning of the text section */
5724 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5726 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5727 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5728 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5729 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5730 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5731 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5732 size = section_start;
5733 size += FILE_ALIGN - 1;
5734 size &= ~(FILE_ALIGN - 1);
5735 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5737 size += VIRT_ALIGN - 1;
5738 size &= ~(VIRT_ALIGN - 1);
5739 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5742 // Translate the PEFileKind value to the value expected by the Windows loader
5748 // PEFileKinds.Dll == 1
5749 // PEFileKinds.ConsoleApplication == 2
5750 // PEFileKinds.WindowApplication == 3
5753 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5754 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5756 if (assemblyb->pekind == 3)
5761 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5763 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5764 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5765 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5766 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5767 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5768 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5770 /* fill data directory entries */
5772 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5773 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5775 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5776 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5778 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5779 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5780 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5781 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5782 /* patch entrypoint name */
5783 if (assemblyb->pekind == 1)
5784 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5786 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5787 /* patch imported function RVA name */
5788 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5789 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5791 /* the import table */
5792 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5793 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5794 /* patch imported dll RVA name and other entries in the dir */
5795 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5796 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5797 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5798 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5799 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5800 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5802 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5803 value = (assembly->text_rva + assembly->imp_names_offset);
5804 *p++ = (value) & 0xff;
5805 *p++ = (value >> 8) & (0xff);
5806 *p++ = (value >> 16) & (0xff);
5807 *p++ = (value >> 24) & (0xff);
5809 /* the CLI header info */
5810 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5811 cli_header->ch_size = GUINT32_FROM_LE (72);
5812 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5813 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5814 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5815 if (assemblyb->entry_point) {
5816 guint32 table_idx = 0;
5817 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5818 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5819 table_idx = methodb->table_idx;
5821 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5823 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5825 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5827 /* The embedded managed resources */
5828 text_offset = assembly->text_rva + assembly->code.index;
5829 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5830 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5831 text_offset += assembly->resources.index;
5832 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5833 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5834 text_offset += assembly->meta_size;
5835 if (assembly->strong_name_size) {
5836 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5837 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5838 text_offset += assembly->strong_name_size;
5841 /* write the section tables and section content */
5842 section = (MonoSectionTable*)(pefile->data + section_start);
5843 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5844 static const char section_names [][7] = {
5845 ".text", ".rsrc", ".reloc"
5847 if (!assembly->sections [i].size)
5849 strcpy (section->st_name, section_names [i]);
5850 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5851 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5852 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5853 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5854 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5855 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5856 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5860 checked_write_file (file, pefile->data, pefile->index);
5862 mono_dynamic_stream_reset (pefile);
5864 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5865 if (!assembly->sections [i].size)
5868 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5869 g_error ("SetFilePointer returned %d\n", GetLastError ());
5872 case MONO_SECTION_TEXT:
5873 /* patch entry point */
5874 p = (guchar*)(assembly->code.data + 2);
5875 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5876 *p++ = (value) & 0xff;
5877 *p++ = (value >> 8) & 0xff;
5878 *p++ = (value >> 16) & 0xff;
5879 *p++ = (value >> 24) & 0xff;
5881 checked_write_file (file, assembly->code.data, assembly->code.index);
5882 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5883 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5884 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5887 g_free (assembly->image.raw_metadata);
5889 case MONO_SECTION_RELOC: {
5893 guint16 type_and_offset;
5897 g_assert (sizeof (reloc) == 12);
5899 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5900 reloc.block_size = GUINT32_FROM_LE (12);
5903 * the entrypoint is always at the start of the text section
5904 * 3 is IMAGE_REL_BASED_HIGHLOW
5905 * 2 is patch_size_rva - text_rva
5907 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5910 checked_write_file (file, &reloc, sizeof (reloc));
5914 case MONO_SECTION_RSRC:
5915 if (assembly->win32_res) {
5917 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5918 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5919 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5923 g_assert_not_reached ();
5927 /* check that the file is properly padded */
5928 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5929 g_error ("SetFilePointer returned %d\n", GetLastError ());
5930 if (! SetEndOfFile (file))
5931 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5933 mono_dynamic_stream_reset (&assembly->code);
5934 mono_dynamic_stream_reset (&assembly->us);
5935 mono_dynamic_stream_reset (&assembly->blob);
5936 mono_dynamic_stream_reset (&assembly->guid);
5937 mono_dynamic_stream_reset (&assembly->sheap);
5939 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5940 g_hash_table_destroy (assembly->blob_cache);
5941 assembly->blob_cache = NULL;
5944 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5947 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5949 g_assert_not_reached ();
5952 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5954 #ifndef DISABLE_REFLECTION_EMIT
5956 MonoReflectionModule *
5957 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5961 MonoImageOpenStatus status;
5962 MonoDynamicAssembly *assembly;
5963 guint32 module_count;
5964 MonoImage **new_modules;
5965 gboolean *new_modules_loaded;
5967 name = mono_string_to_utf8 (fileName);
5969 image = mono_image_open (name, &status);
5972 if (status == MONO_IMAGE_ERROR_ERRNO)
5973 exc = mono_get_exception_file_not_found (fileName);
5975 exc = mono_get_exception_bad_image_format (name);
5977 mono_raise_exception (exc);
5982 assembly = ab->dynamic_assembly;
5983 image->assembly = (MonoAssembly*)assembly;
5985 module_count = image->assembly->image->module_count;
5986 new_modules = g_new0 (MonoImage *, module_count + 1);
5987 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5989 if (image->assembly->image->modules)
5990 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5991 if (image->assembly->image->modules_loaded)
5992 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5993 new_modules [module_count] = image;
5994 new_modules_loaded [module_count] = TRUE;
5995 mono_image_addref (image);
5997 g_free (image->assembly->image->modules);
5998 image->assembly->image->modules = new_modules;
5999 image->assembly->image->modules_loaded = new_modules_loaded;
6000 image->assembly->image->module_count ++;
6002 mono_assembly_load_references (image, &status);
6004 mono_image_close (image);
6005 mono_raise_exception (mono_get_exception_file_not_found (fileName));
6008 return mono_module_get_object (mono_domain_get (), image);
6011 #endif /* DISABLE_REFLECTION_EMIT */
6014 * We need to return always the same object for MethodInfo, FieldInfo etc..
6015 * but we need to consider the reflected type.
6016 * type uses a different hash, since it uses custom hash/equal functions.
6021 MonoClass *refclass;
6025 reflected_equal (gconstpointer a, gconstpointer b) {
6026 const ReflectedEntry *ea = a;
6027 const ReflectedEntry *eb = b;
6029 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
6033 reflected_hash (gconstpointer a) {
6034 const ReflectedEntry *ea = a;
6035 return mono_aligned_addr_hash (ea->item);
6038 #define CHECK_OBJECT(t,p,k) \
6044 mono_domain_lock (domain); \
6045 if (!domain->refobject_hash) \
6046 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6047 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
6048 mono_domain_unlock (domain); \
6051 mono_domain_unlock (domain); \
6054 #ifdef HAVE_BOEHM_GC
6055 /* ReflectedEntry doesn't need to be GC tracked */
6056 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
6057 #define FREE_REFENTRY(entry) g_free ((entry))
6058 #define REFENTRY_REQUIRES_CLEANUP
6060 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
6062 #define FREE_REFENTRY(entry)
6065 #define CACHE_OBJECT(t,p,o,k) \
6068 ReflectedEntry pe; \
6070 pe.refclass = (k); \
6071 mono_domain_lock (domain); \
6072 if (!domain->refobject_hash) \
6073 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
6074 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
6076 ReflectedEntry *e = ALLOC_REFENTRY; \
6078 e->refclass = (k); \
6079 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6082 mono_domain_unlock (domain); \
6087 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6089 mono_domain_lock (domain);
6090 if (domain->refobject_hash) {
6092 gpointer orig_pe, orig_value;
6095 pe.refclass = klass;
6096 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6097 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6098 FREE_REFENTRY (orig_pe);
6101 mono_domain_unlock (domain);
6104 #ifdef REFENTRY_REQUIRES_CLEANUP
6106 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6108 FREE_REFENTRY (key);
6113 mono_reflection_cleanup_domain (MonoDomain *domain)
6115 if (domain->refobject_hash) {
6116 /*let's avoid scanning the whole hashtable if not needed*/
6117 #ifdef REFENTRY_REQUIRES_CLEANUP
6118 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6120 mono_g_hash_table_destroy (domain->refobject_hash);
6121 domain->refobject_hash = NULL;
6125 #ifndef DISABLE_REFLECTION_EMIT
6127 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6129 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6133 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6135 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6139 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6141 MonoDynamicImage *image = moduleb->dynamic_image;
6142 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6146 MonoImage **new_modules;
6148 char *name, *fqname;
6150 * FIXME: we already created an image in mono_image_basic_init (), but
6151 * we don't know which module it belongs to, since that is only
6152 * determined at assembly save time.
6154 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6155 name = mono_string_to_utf8 (ab->name);
6156 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6157 if (!mono_error_ok (&error)) {
6159 mono_error_raise_exception (&error);
6161 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6163 moduleb->module.image = &image->image;
6164 moduleb->dynamic_image = image;
6165 register_module (mono_object_domain (moduleb), moduleb, image);
6167 /* register the module with the assembly */
6168 ass = ab->dynamic_assembly->assembly.image;
6169 module_count = ass->module_count;
6170 new_modules = g_new0 (MonoImage *, module_count + 1);
6173 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6174 new_modules [module_count] = &image->image;
6175 mono_image_addref (&image->image);
6177 g_free (ass->modules);
6178 ass->modules = new_modules;
6179 ass->module_count ++;
6184 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6186 MonoDynamicImage *image = moduleb->dynamic_image;
6188 g_assert (type->type);
6189 image->wrappers_type = mono_class_from_mono_type (type->type);
6195 * mono_assembly_get_object:
6196 * @domain: an app domain
6197 * @assembly: an assembly
6199 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6201 MonoReflectionAssembly*
6202 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6204 static MonoClass *assembly_type;
6205 MonoReflectionAssembly *res;
6207 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6208 if (!assembly_type) {
6209 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6211 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6213 assembly_type = class;
6215 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6216 res->assembly = assembly;
6218 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6223 MonoReflectionModule*
6224 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6226 static MonoClass *module_type;
6227 MonoReflectionModule *res;
6230 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6232 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6234 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6236 module_type = class;
6238 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6241 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6243 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6244 basename = g_path_get_basename (image->name);
6245 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6246 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6250 if (image->assembly->image == image) {
6251 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6255 if (image->assembly->image->modules) {
6256 for (i = 0; i < image->assembly->image->module_count; i++) {
6257 if (image->assembly->image->modules [i] == image)
6258 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6260 g_assert (res->token);
6264 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6267 MonoReflectionModule*
6268 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6270 static MonoClass *module_type;
6271 MonoReflectionModule *res;
6272 MonoTableInfo *table;
6273 guint32 cols [MONO_FILE_SIZE];
6275 guint32 i, name_idx;
6279 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6281 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6283 module_type = class;
6285 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6287 table = &image->tables [MONO_TABLE_FILE];
6288 g_assert (table_index < table->rows);
6289 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6292 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6293 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6295 /* Check whenever the row has a corresponding row in the moduleref table */
6296 table = &image->tables [MONO_TABLE_MODULEREF];
6297 for (i = 0; i < table->rows; ++i) {
6298 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6299 val = mono_metadata_string_heap (image, name_idx);
6300 if (strcmp (val, name) == 0)
6301 res->image = image->modules [i];
6304 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6305 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6306 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6307 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6308 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6314 verify_safe_for_managed_space (MonoType *type)
6316 switch (type->type) {
6318 case MONO_TYPE_ARRAY:
6319 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6321 return verify_safe_for_managed_space (type->data.type);
6322 case MONO_TYPE_SZARRAY:
6323 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6324 case MONO_TYPE_GENERICINST: {
6325 MonoGenericInst *inst = type->data.generic_class->inst;
6329 for (i = 0; i < inst->type_argc; ++i)
6330 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6336 case MONO_TYPE_MVAR:
6343 mono_type_normalize (MonoType *type)
6346 MonoGenericClass *gclass;
6347 MonoGenericInst *ginst;
6349 MonoGenericContainer *gcontainer;
6350 MonoType **argv = NULL;
6351 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6353 if (type->type != MONO_TYPE_GENERICINST)
6356 gclass = type->data.generic_class;
6357 ginst = gclass->context.class_inst;
6358 if (!ginst->is_open)
6361 gtd = gclass->container_class;
6362 gcontainer = gtd->generic_container;
6363 argv = g_newa (MonoType*, ginst->type_argc);
6365 for (i = 0; i < ginst->type_argc; ++i) {
6366 MonoType *t = ginst->type_argv [i], *norm;
6367 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6368 is_denorm_gtd = FALSE;
6369 norm = mono_type_normalize (t);
6372 requires_rebind = TRUE;
6376 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6378 if (requires_rebind) {
6379 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6380 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6386 * mono_type_get_object:
6387 * @domain: an app domain
6390 * Return an System.MonoType object representing the type @type.
6393 mono_type_get_object (MonoDomain *domain, MonoType *type)
6395 MonoType *norm_type;
6396 MonoReflectionType *res;
6397 MonoClass *klass = mono_class_from_mono_type (type);
6399 /*we must avoid using @type as it might have come
6400 * from a mono_metadata_type_dup and the caller
6401 * expects that is can be freed.
6402 * Using the right type from
6404 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6406 /* void is very common */
6407 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6408 return (MonoReflectionType*)domain->typeof_void;
6411 * If the vtable of the given class was already created, we can use
6412 * the MonoType from there and avoid all locking and hash table lookups.
6414 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6415 * that the resulting object is different.
6417 if (type == &klass->byval_arg && !klass->image->dynamic) {
6418 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6419 if (vtable && vtable->type)
6420 return vtable->type;
6423 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6424 mono_domain_lock (domain);
6425 if (!domain->type_hash)
6426 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
6427 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
6428 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6429 mono_domain_unlock (domain);
6430 mono_loader_unlock ();
6434 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6435 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6436 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6437 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6438 * artifact of how generics are encoded and should be transparent to managed code so we
6439 * need to weed out this diference when retrieving managed System.Type objects.
6441 norm_type = mono_type_normalize (type);
6442 if (norm_type != type) {
6443 res = mono_type_get_object (domain, norm_type);
6444 mono_g_hash_table_insert (domain->type_hash, type, res);
6445 mono_domain_unlock (domain);
6446 mono_loader_unlock ();
6450 /* This MonoGenericClass hack is no longer necessary. Let's leave it here until we finish with the 2-stage type-builder setup.*/
6451 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder)
6454 if (!verify_safe_for_managed_space (type)) {
6455 mono_domain_unlock (domain);
6456 mono_loader_unlock ();
6457 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6460 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6461 gboolean is_type_done = TRUE;
6462 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6463 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6464 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6466 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6467 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6469 if (gparam->owner && gparam->owner->is_method) {
6470 MonoMethod *method = gparam->owner->owner.method;
6471 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6472 is_type_done = FALSE;
6473 } else if (gparam->owner && !gparam->owner->is_method) {
6474 MonoClass *klass = gparam->owner->owner.klass;
6475 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6476 is_type_done = FALSE;
6480 /* g_assert_not_reached (); */
6481 /* should this be considered an error condition? */
6482 if (is_type_done && !type->byref) {
6483 mono_domain_unlock (domain);
6484 mono_loader_unlock ();
6485 return mono_class_get_ref_info (klass);
6488 /* This is stored in vtables/JITted code so it has to be pinned */
6489 res = (MonoReflectionType *)mono_object_new_pinned (domain, mono_defaults.monotype_class);
6491 mono_g_hash_table_insert (domain->type_hash, type, res);
6493 if (type->type == MONO_TYPE_VOID)
6494 domain->typeof_void = (MonoObject*)res;
6496 mono_domain_unlock (domain);
6497 mono_loader_unlock ();
6502 * mono_method_get_object:
6503 * @domain: an app domain
6505 * @refclass: the reflected type (can be NULL)
6507 * Return an System.Reflection.MonoMethod object representing the method @method.
6509 MonoReflectionMethod*
6510 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6513 * We use the same C representation for methods and constructors, but the type
6514 * name in C# is different.
6516 static MonoClass *System_Reflection_MonoMethod = NULL;
6517 static MonoClass *System_Reflection_MonoCMethod = NULL;
6518 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6519 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6521 MonoReflectionMethod *ret;
6523 if (method->is_inflated) {
6524 MonoReflectionGenericMethod *gret;
6526 refclass = method->klass;
6527 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6528 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6529 if (!System_Reflection_MonoGenericCMethod)
6530 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6531 klass = System_Reflection_MonoGenericCMethod;
6533 if (!System_Reflection_MonoGenericMethod)
6534 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6535 klass = System_Reflection_MonoGenericMethod;
6537 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6538 gret->method.method = method;
6539 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6540 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6541 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6545 refclass = method->klass;
6547 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6548 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6549 if (!System_Reflection_MonoCMethod)
6550 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6551 klass = System_Reflection_MonoCMethod;
6554 if (!System_Reflection_MonoMethod)
6555 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6556 klass = System_Reflection_MonoMethod;
6558 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6559 ret->method = method;
6560 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6561 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6565 * mono_method_clear_object:
6567 * Clear the cached reflection objects for the dynamic method METHOD.
6570 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6573 g_assert (method->dynamic);
6575 klass = method->klass;
6577 clear_cached_object (domain, method, klass);
6578 klass = klass->parent;
6580 /* Added by mono_param_get_objects () */
6581 clear_cached_object (domain, &(method->signature), NULL);
6582 klass = method->klass;
6584 clear_cached_object (domain, &(method->signature), klass);
6585 klass = klass->parent;
6590 * mono_field_get_object:
6591 * @domain: an app domain
6595 * Return an System.Reflection.MonoField object representing the field @field
6598 MonoReflectionField*
6599 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6601 MonoReflectionField *res;
6602 static MonoClass *monofield_klass;
6604 CHECK_OBJECT (MonoReflectionField *, field, klass);
6605 if (!monofield_klass)
6606 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6607 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6610 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6612 if (is_field_on_inst (field)) {
6613 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6614 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6617 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6618 res->attrs = mono_field_get_flags (field);
6620 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6624 * mono_property_get_object:
6625 * @domain: an app domain
6627 * @property: a property
6629 * Return an System.Reflection.MonoProperty object representing the property @property
6632 MonoReflectionProperty*
6633 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6635 MonoReflectionProperty *res;
6636 static MonoClass *monoproperty_klass;
6638 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6639 if (!monoproperty_klass)
6640 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6641 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6643 res->property = property;
6644 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6648 * mono_event_get_object:
6649 * @domain: an app domain
6653 * Return an System.Reflection.MonoEvent object representing the event @event
6656 MonoReflectionEvent*
6657 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6659 MonoReflectionEvent *res;
6660 MonoReflectionMonoEvent *mono_event;
6661 static MonoClass *monoevent_klass;
6663 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6664 if (!monoevent_klass)
6665 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6666 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6667 mono_event->klass = klass;
6668 mono_event->event = event;
6669 res = (MonoReflectionEvent*)mono_event;
6670 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6674 * mono_get_reflection_missing_object:
6675 * @domain: Domain where the object lives
6677 * Returns the System.Reflection.Missing.Value singleton object
6678 * (of type System.Reflection.Missing).
6680 * Used as the value for ParameterInfo.DefaultValue when Optional
6684 mono_get_reflection_missing_object (MonoDomain *domain)
6687 static MonoClassField *missing_value_field = NULL;
6689 if (!missing_value_field) {
6690 MonoClass *missing_klass;
6691 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6692 mono_class_init (missing_klass);
6693 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6694 g_assert (missing_value_field);
6696 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6702 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6705 *dbnull = mono_get_dbnull_object (domain);
6710 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6712 if (!*reflection_missing)
6713 *reflection_missing = mono_get_reflection_missing_object (domain);
6714 return *reflection_missing;
6718 * mono_param_get_objects:
6719 * @domain: an app domain
6722 * Return an System.Reflection.ParameterInfo array object representing the parameters
6723 * in the method @method.
6726 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6728 static MonoClass *System_Reflection_ParameterInfo;
6729 static MonoClass *System_Reflection_ParameterInfo_array;
6731 MonoArray *res = NULL;
6732 MonoReflectionMethod *member = NULL;
6733 MonoReflectionParameter *param = NULL;
6734 char **names, **blobs = NULL;
6735 guint32 *types = NULL;
6736 MonoType *type = NULL;
6737 MonoObject *dbnull = NULL;
6738 MonoObject *missing = NULL;
6739 MonoMarshalSpec **mspecs;
6740 MonoMethodSignature *sig;
6741 MonoVTable *pinfo_vtable;
6744 if (!System_Reflection_ParameterInfo_array) {
6747 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6748 mono_memory_barrier ();
6749 System_Reflection_ParameterInfo = klass;
6751 klass = mono_array_class_get (klass, 1);
6752 mono_memory_barrier ();
6753 System_Reflection_ParameterInfo_array = klass;
6756 sig = mono_method_signature_checked (method, &error);
6757 if (!mono_error_ok (&error))
6758 mono_error_raise_exception (&error);
6760 if (!sig->param_count)
6761 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6763 /* Note: the cache is based on the address of the signature into the method
6764 * since we already cache MethodInfos with the method as keys.
6766 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6768 member = mono_method_get_object (domain, method, refclass);
6769 names = g_new (char *, sig->param_count);
6770 mono_method_get_param_names (method, (const char **) names);
6772 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6773 mono_method_get_marshal_info (method, mspecs);
6775 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6776 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6777 for (i = 0; i < sig->param_count; ++i) {
6778 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6779 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6780 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6781 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6782 param->PositionImpl = i;
6783 param->AttrsImpl = sig->params [i]->attrs;
6785 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6786 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6787 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6789 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6793 blobs = g_new0 (char *, sig->param_count);
6794 types = g_new0 (guint32, sig->param_count);
6795 get_default_param_value_blobs (method, blobs, types);
6798 /* Build MonoType for the type from the Constant Table */
6800 type = g_new0 (MonoType, 1);
6801 type->type = types [i];
6802 type->data.klass = NULL;
6803 if (types [i] == MONO_TYPE_CLASS)
6804 type->data.klass = mono_defaults.object_class;
6805 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6806 /* For enums, types [i] contains the base type */
6808 type->type = MONO_TYPE_VALUETYPE;
6809 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6811 type->data.klass = mono_class_from_mono_type (type);
6813 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6815 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6816 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6817 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6818 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6820 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6826 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6828 mono_array_setref (res, i, param);
6835 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6837 mono_metadata_free_marshal_spec (mspecs [i]);
6840 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6844 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6846 return mono_param_get_objects_internal (domain, method, NULL);
6850 * mono_method_body_get_object:
6851 * @domain: an app domain
6854 * Return an System.Reflection.MethodBody object representing the method @method.
6856 MonoReflectionMethodBody*
6857 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6859 static MonoClass *System_Reflection_MethodBody = NULL;
6860 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6861 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6862 MonoReflectionMethodBody *ret;
6863 MonoMethodHeader *header;
6865 guint32 method_rva, local_var_sig_token;
6867 unsigned char format, flags;
6870 /* for compatibility with .net */
6871 if (method->dynamic)
6872 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
6874 if (!System_Reflection_MethodBody)
6875 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6876 if (!System_Reflection_LocalVariableInfo)
6877 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6878 if (!System_Reflection_ExceptionHandlingClause)
6879 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6881 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6883 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6884 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6885 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6886 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6889 image = method->klass->image;
6890 header = mono_method_get_header (method);
6892 if (!image->dynamic) {
6893 /* Obtain local vars signature token */
6894 method_rva = mono_metadata_decode_row_col (&image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6895 ptr = mono_image_rva_map (image, method_rva);
6896 flags = *(const unsigned char *) ptr;
6897 format = flags & METHOD_HEADER_FORMAT_MASK;
6899 case METHOD_HEADER_TINY_FORMAT:
6900 local_var_sig_token = 0;
6902 case METHOD_HEADER_FAT_FORMAT:
6906 local_var_sig_token = read32 (ptr);
6909 g_assert_not_reached ();
6912 local_var_sig_token = 0; //FIXME
6914 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6916 ret->init_locals = header->init_locals;
6917 ret->max_stack = header->max_stack;
6918 ret->local_var_sig_token = local_var_sig_token;
6919 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6920 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6923 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6924 for (i = 0; i < header->num_locals; ++i) {
6925 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6926 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6927 info->is_pinned = header->locals [i]->pinned;
6928 info->local_index = i;
6929 mono_array_setref (ret->locals, i, info);
6933 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6934 for (i = 0; i < header->num_clauses; ++i) {
6935 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6936 MonoExceptionClause *clause = &header->clauses [i];
6938 info->flags = clause->flags;
6939 info->try_offset = clause->try_offset;
6940 info->try_length = clause->try_len;
6941 info->handler_offset = clause->handler_offset;
6942 info->handler_length = clause->handler_len;
6943 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6944 info->filter_offset = clause->data.filter_offset;
6945 else if (clause->data.catch_class)
6946 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6948 mono_array_setref (ret->clauses, i, info);
6951 mono_metadata_free_mh (header);
6952 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
6957 * mono_get_dbnull_object:
6958 * @domain: Domain where the object lives
6960 * Returns the System.DBNull.Value singleton object
6962 * Used as the value for ParameterInfo.DefaultValue
6965 mono_get_dbnull_object (MonoDomain *domain)
6968 static MonoClassField *dbnull_value_field = NULL;
6970 if (!dbnull_value_field) {
6971 MonoClass *dbnull_klass;
6972 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
6973 mono_class_init (dbnull_klass);
6974 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
6975 g_assert (dbnull_value_field);
6977 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
6983 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
6985 guint32 param_index, i, lastp, crow = 0;
6986 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
6989 MonoClass *klass = method->klass;
6990 MonoImage *image = klass->image;
6991 MonoMethodSignature *methodsig = mono_method_signature (method);
6993 MonoTableInfo *constt;
6994 MonoTableInfo *methodt;
6995 MonoTableInfo *paramt;
6997 if (!methodsig->param_count)
7000 mono_class_init (klass);
7002 if (klass->image->dynamic) {
7003 MonoReflectionMethodAux *aux;
7004 if (method->is_inflated)
7005 method = ((MonoMethodInflated*)method)->declaring;
7006 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7007 if (aux && aux->param_defaults) {
7008 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7009 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7014 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7015 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7016 constt = &image->tables [MONO_TABLE_CONSTANT];
7018 idx = mono_method_get_index (method) - 1;
7019 g_assert (idx != -1);
7021 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7022 if (idx + 1 < methodt->rows)
7023 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7025 lastp = paramt->rows + 1;
7027 for (i = param_index; i < lastp; ++i) {
7030 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7031 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7033 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7036 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7041 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7042 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7043 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7050 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7055 MonoType *basetype = type;
7060 klass = mono_class_from_mono_type (type);
7061 if (klass->valuetype) {
7062 object = mono_object_new (domain, klass);
7063 retval = ((gchar *) object + sizeof (MonoObject));
7064 if (klass->enumtype)
7065 basetype = mono_class_enum_basetype (klass);
7070 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7077 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7080 gboolean quoted = FALSE;
7082 memset (assembly, 0, sizeof (MonoAssemblyName));
7083 assembly->culture = "";
7084 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7091 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@' || g_ascii_isspace (*p)))
7102 /* Remove trailing whitespace */
7104 while (*s && g_ascii_isspace (*s))
7107 while (g_ascii_isspace (*p))
7110 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7112 assembly->major = strtoul (p, &s, 10);
7113 if (s == p || *s != '.')
7116 assembly->minor = strtoul (p, &s, 10);
7117 if (s == p || *s != '.')
7120 assembly->build = strtoul (p, &s, 10);
7121 if (s == p || *s != '.')
7124 assembly->revision = strtoul (p, &s, 10);
7128 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7130 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7131 assembly->culture = "";
7134 assembly->culture = p;
7135 while (*p && *p != ',') {
7139 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7141 if (strncmp (p, "null", 4) == 0) {
7146 while (*p && *p != ',') {
7149 len = (p - start + 1);
7150 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7151 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7152 g_strlcpy ((char*)assembly->public_key_token, start, len);
7155 while (*p && *p != ',')
7159 while (g_ascii_isspace (*p) || *p == ',') {
7173 * mono_reflection_parse_type:
7176 * Parse a type name as accepted by the GetType () method and output the info
7177 * extracted in the info structure.
7178 * the name param will be mangled, so, make a copy before passing it to this function.
7179 * The fields in info will be valid until the memory pointed to by name is valid.
7181 * See also mono_type_get_name () below.
7183 * Returns: 0 on parse error.
7186 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7187 MonoTypeNameParse *info)
7189 char *start, *p, *w, *temp, *last_point, *startn;
7190 int in_modifiers = 0;
7191 int isbyref = 0, rank, arity = 0, i;
7193 start = p = w = name;
7195 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7196 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7197 info->name = info->name_space = NULL;
7198 info->nested = NULL;
7199 info->modifiers = NULL;
7200 info->type_arguments = NULL;
7202 /* last_point separates the namespace from the name */
7205 while (*p == ' ') p++, start++, w++, name++;
7210 *p = 0; /* NULL terminate the name */
7212 info->nested = g_list_append (info->nested, startn);
7213 /* we have parsed the nesting namespace + name */
7217 info->name_space = start;
7219 info->name = last_point + 1;
7221 info->name_space = (char *)"";
7240 i = strtol (p, &temp, 10);
7257 info->name_space = start;
7259 info->name = last_point + 1;
7261 info->name_space = (char *)"";
7268 if (isbyref) /* only one level allowed by the spec */
7271 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7275 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7281 info->type_arguments = g_ptr_array_new ();
7282 for (i = 0; i < arity; i++) {
7283 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7284 gboolean fqname = FALSE;
7286 g_ptr_array_add (info->type_arguments, subinfo);
7293 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7296 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7297 if (fqname && (*p != ']')) {
7305 while (*p && (*p != ']'))
7313 if (g_ascii_isspace (*aname)) {
7320 !assembly_name_to_aname (&subinfo->assembly, aname))
7322 } else if (fqname && (*p == ']')) {
7326 if (i + 1 < arity) {
7346 else if (*p == '*') /* '*' means unknown lower bound */
7347 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7354 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7365 if (g_ascii_isspace (*p)) {
7372 return 0; /* missing assembly name */
7373 if (!assembly_name_to_aname (&info->assembly, p))
7379 if (info->assembly.name)
7382 // *w = 0; /* terminate class name */
7384 if (!info->name || !*info->name)
7388 /* add other consistency checks */
7393 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7395 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7399 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7401 gboolean type_resolve = FALSE;
7403 MonoImage *rootimage = image;
7405 if (info->assembly.name) {
7406 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7407 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7409 * This could happen in the AOT compiler case when the search hook is not
7412 assembly = image->assembly;
7414 /* then we must load the assembly ourselve - see #60439 */
7415 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7419 image = assembly->image;
7420 } else if (!image) {
7421 image = mono_defaults.corlib;
7424 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7425 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7426 image = mono_defaults.corlib;
7427 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7434 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7439 gboolean bounded = FALSE;
7442 image = mono_defaults.corlib;
7445 klass = mono_class_from_name_case (image, info->name_space, info->name);
7447 klass = mono_class_from_name (image, info->name_space, info->name);
7450 for (mod = info->nested; mod; mod = mod->next) {
7451 gpointer iter = NULL;
7455 mono_class_init (parent);
7457 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7459 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7462 if (strcmp (klass->name, mod->data) == 0)
7472 if (info->type_arguments) {
7473 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7474 MonoReflectionType *the_type;
7478 for (i = 0; i < info->type_arguments->len; i++) {
7479 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7481 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7482 if (!type_args [i]) {
7488 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7490 instance = mono_reflection_bind_generic_parameters (
7491 the_type, info->type_arguments->len, type_args);
7497 klass = mono_class_from_mono_type (instance);
7500 for (mod = info->modifiers; mod; mod = mod->next) {
7501 modval = GPOINTER_TO_UINT (mod->data);
7502 if (!modval) { /* byref: must be last modifier */
7503 return &klass->this_arg;
7504 } else if (modval == -1) {
7505 klass = mono_ptr_class_get (&klass->byval_arg);
7506 } else if (modval == -2) {
7508 } else { /* array rank */
7509 klass = mono_bounded_array_class_get (klass, modval, bounded);
7513 return &klass->byval_arg;
7517 * mono_reflection_get_type:
7518 * @image: a metadata context
7519 * @info: type description structure
7520 * @ignorecase: flag for case-insensitive string compares
7521 * @type_resolve: whenever type resolve was already tried
7523 * Build a MonoType from the type description in @info.
7528 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7529 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7533 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7535 MonoReflectionAssemblyBuilder *abuilder;
7539 g_assert (assembly->dynamic);
7540 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7542 /* Enumerate all modules */
7545 if (abuilder->modules) {
7546 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7547 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7548 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7554 if (!type && abuilder->loaded_modules) {
7555 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7556 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7557 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7567 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7570 MonoReflectionAssembly *assembly;
7574 if (image && image->dynamic)
7575 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7577 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7580 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7587 *type_resolve = TRUE;
7590 /* Reconstruct the type name */
7591 fullName = g_string_new ("");
7592 if (info->name_space && (info->name_space [0] != '\0'))
7593 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7595 g_string_printf (fullName, "%s", info->name);
7596 for (mod = info->nested; mod; mod = mod->next)
7597 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7599 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7601 if (assembly->assembly->dynamic)
7602 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7604 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7607 g_string_free (fullName, TRUE);
7612 mono_reflection_free_type_info (MonoTypeNameParse *info)
7614 g_list_free (info->modifiers);
7615 g_list_free (info->nested);
7617 if (info->type_arguments) {
7620 for (i = 0; i < info->type_arguments->len; i++) {
7621 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7623 mono_reflection_free_type_info (subinfo);
7624 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7628 g_ptr_array_free (info->type_arguments, TRUE);
7633 * mono_reflection_type_from_name:
7635 * @image: a metadata context (can be NULL).
7637 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7638 * it defaults to get the type from @image or, if @image is NULL or loading
7639 * from it fails, uses corlib.
7643 mono_reflection_type_from_name (char *name, MonoImage *image)
7645 MonoType *type = NULL;
7646 MonoTypeNameParse info;
7649 /* Make a copy since parse_type modifies its argument */
7650 tmp = g_strdup (name);
7652 /*g_print ("requested type %s\n", str);*/
7653 if (mono_reflection_parse_type (tmp, &info)) {
7654 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7658 mono_reflection_free_type_info (&info);
7663 * mono_reflection_get_token:
7665 * Return the metadata token of OBJ which should be an object
7666 * representing a metadata element.
7669 mono_reflection_get_token (MonoObject *obj)
7674 klass = obj->vtable->klass;
7676 if (strcmp (klass->name, "MethodBuilder") == 0) {
7677 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7679 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7680 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7681 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7683 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7684 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7685 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7687 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
7688 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7689 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7690 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7691 } else if (strcmp (klass->name, "MonoType") == 0) {
7692 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
7693 MonoClass *mc = mono_class_from_mono_type (type);
7694 if (!mono_class_init (mc))
7695 mono_raise_exception (mono_class_get_exception_for_failure (mc));
7697 token = mc->type_token;
7698 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7699 strcmp (klass->name, "MonoMethod") == 0 ||
7700 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7701 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7702 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7703 if (m->method->is_inflated) {
7704 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7705 return inflated->declaring->token;
7707 token = m->method->token;
7709 } else if (strcmp (klass->name, "MonoField") == 0) {
7710 MonoReflectionField *f = (MonoReflectionField*)obj;
7712 if (is_field_on_inst (f->field)) {
7713 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7714 int field_index = f->field - dgclass->fields;
7717 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7718 obj = dgclass->field_objects [field_index];
7719 return mono_reflection_get_token (obj);
7721 token = mono_class_get_field_token (f->field);
7722 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7723 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7725 token = mono_class_get_property_token (p->property);
7726 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7727 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7729 token = mono_class_get_event_token (p->event);
7730 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7731 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7732 MonoClass *member_class = mono_object_class (p->MemberImpl);
7733 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7735 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7736 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7737 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7740 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7741 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7743 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7744 MonoException *ex = mono_get_exception_not_implemented (msg);
7746 mono_raise_exception (ex);
7753 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7755 int slen, type = t->type;
7756 MonoClass *tklass = t->data.klass;
7762 case MONO_TYPE_BOOLEAN: {
7763 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7768 case MONO_TYPE_CHAR:
7770 case MONO_TYPE_I2: {
7771 guint16 *val = g_malloc (sizeof (guint16));
7776 #if SIZEOF_VOID_P == 4
7782 case MONO_TYPE_I4: {
7783 guint32 *val = g_malloc (sizeof (guint32));
7788 #if SIZEOF_VOID_P == 8
7789 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7793 case MONO_TYPE_I8: {
7794 guint64 *val = g_malloc (sizeof (guint64));
7799 case MONO_TYPE_R8: {
7800 double *val = g_malloc (sizeof (double));
7805 case MONO_TYPE_VALUETYPE:
7806 if (t->data.klass->enumtype) {
7807 type = mono_class_enum_basetype (t->data.klass)->type;
7810 MonoClass *k = t->data.klass;
7812 if (mono_is_corlib_image (k->image) && strcmp (k->name_space, "System") == 0 && strcmp (k->name, "DateTime") == 0){
7813 guint64 *val = g_malloc (sizeof (guint64));
7819 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7822 case MONO_TYPE_STRING:
7823 if (*p == (char)0xFF) {
7827 slen = mono_metadata_decode_value (p, &p);
7829 return mono_string_new_len (mono_domain_get (), p, slen);
7830 case MONO_TYPE_CLASS: {
7833 if (*p == (char)0xFF) {
7838 slen = mono_metadata_decode_value (p, &p);
7839 n = g_memdup (p, slen + 1);
7841 t = mono_reflection_type_from_name (n, image);
7843 g_warning ("Cannot load type '%s'", n);
7847 return mono_type_get_object (mono_domain_get (), t);
7851 case MONO_TYPE_OBJECT: {
7854 MonoClass *subc = NULL;
7859 } else if (subt == 0x0E) {
7860 type = MONO_TYPE_STRING;
7862 } else if (subt == 0x1D) {
7863 MonoType simple_type = {{0}};
7867 type = MONO_TYPE_SZARRAY;
7868 if (etype == 0x50) {
7869 tklass = mono_defaults.systemtype_class;
7872 /* See Partition II, Appendix B3 */
7873 etype = MONO_TYPE_OBJECT;
7874 simple_type.type = etype;
7875 tklass = mono_class_from_mono_type (&simple_type);
7878 } else if (subt == 0x55) {
7881 slen = mono_metadata_decode_value (p, &p);
7882 n = g_memdup (p, slen + 1);
7884 t = mono_reflection_type_from_name (n, image);
7886 g_error ("Cannot load type '%s'", n);
7889 subc = mono_class_from_mono_type (t);
7890 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7891 MonoType simple_type = {{0}};
7892 simple_type.type = subt;
7893 subc = mono_class_from_mono_type (&simple_type);
7895 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7897 val = load_cattr_value (image, &subc->byval_arg, p, end);
7898 obj = mono_object_new (mono_domain_get (), subc);
7899 g_assert (!subc->has_references);
7900 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7904 case MONO_TYPE_SZARRAY: {
7906 guint32 i, alen, basetype;
7909 if (alen == 0xffffffff) {
7913 arr = mono_array_new (mono_domain_get(), tklass, alen);
7914 basetype = tklass->byval_arg.type;
7915 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7916 basetype = mono_class_enum_basetype (tklass)->type;
7921 case MONO_TYPE_BOOLEAN:
7922 for (i = 0; i < alen; i++) {
7923 MonoBoolean val = *p++;
7924 mono_array_set (arr, MonoBoolean, i, val);
7927 case MONO_TYPE_CHAR:
7930 for (i = 0; i < alen; i++) {
7931 guint16 val = read16 (p);
7932 mono_array_set (arr, guint16, i, val);
7939 for (i = 0; i < alen; i++) {
7940 guint32 val = read32 (p);
7941 mono_array_set (arr, guint32, i, val);
7946 for (i = 0; i < alen; i++) {
7949 mono_array_set (arr, double, i, val);
7955 for (i = 0; i < alen; i++) {
7956 guint64 val = read64 (p);
7957 mono_array_set (arr, guint64, i, val);
7961 case MONO_TYPE_CLASS:
7962 case MONO_TYPE_OBJECT:
7963 case MONO_TYPE_STRING:
7964 for (i = 0; i < alen; i++) {
7965 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7966 mono_array_setref (arr, i, item);
7970 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7976 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7982 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7984 static MonoClass *klass;
7985 static MonoMethod *ctor;
7987 void *params [2], *unboxed;
7990 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7992 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7994 params [0] = mono_type_get_object (mono_domain_get (), t);
7996 retval = mono_object_new (mono_domain_get (), klass);
7997 unboxed = mono_object_unbox (retval);
7998 mono_runtime_invoke (ctor, unboxed, params, NULL);
8004 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8006 static MonoClass *klass;
8007 static MonoMethod *ctor;
8009 void *unboxed, *params [2];
8012 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8014 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8017 params [1] = typedarg;
8018 retval = mono_object_new (mono_domain_get (), klass);
8019 unboxed = mono_object_unbox (retval);
8020 mono_runtime_invoke (ctor, unboxed, params, NULL);
8026 type_is_reference (MonoType *type)
8028 switch (type->type) {
8029 case MONO_TYPE_BOOLEAN:
8030 case MONO_TYPE_CHAR:
8043 case MONO_TYPE_VALUETYPE:
8051 free_param_data (MonoMethodSignature *sig, void **params) {
8053 for (i = 0; i < sig->param_count; ++i) {
8054 if (!type_is_reference (sig->params [i]))
8055 g_free (params [i]);
8060 * Find the field index in the metadata FieldDef table.
8063 find_field_index (MonoClass *klass, MonoClassField *field) {
8066 for (i = 0; i < klass->field.count; ++i) {
8067 if (field == &klass->fields [i])
8068 return klass->field.first + 1 + i;
8074 * Find the property index in the metadata Property table.
8077 find_property_index (MonoClass *klass, MonoProperty *property) {
8080 for (i = 0; i < klass->ext->property.count; ++i) {
8081 if (property == &klass->ext->properties [i])
8082 return klass->ext->property.first + 1 + i;
8088 * Find the event index in the metadata Event table.
8091 find_event_index (MonoClass *klass, MonoEvent *event) {
8094 for (i = 0; i < klass->ext->event.count; ++i) {
8095 if (event == &klass->ext->events [i])
8096 return klass->ext->event.first + 1 + i;
8102 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8104 const char *p = (const char*)data;
8106 guint32 i, j, num_named;
8108 void *params_buf [32];
8110 MonoMethodSignature *sig;
8112 mono_error_init (error);
8114 mono_class_init (method->klass);
8116 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8117 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8122 attr = mono_object_new (mono_domain_get (), method->klass);
8123 mono_runtime_invoke (method, attr, NULL, NULL);
8127 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8130 /*g_print ("got attr %s\n", method->klass->name);*/
8132 sig = mono_method_signature (method);
8133 if (sig->param_count < 32)
8134 params = params_buf;
8136 /* Allocate using GC so it gets GC tracking */
8137 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8141 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8142 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8146 attr = mono_object_new (mono_domain_get (), method->klass);
8147 mono_runtime_invoke (method, attr, params, NULL);
8148 free_param_data (method->signature, params);
8149 num_named = read16 (named);
8151 for (j = 0; j < num_named; j++) {
8153 char *name, named_type, data_type;
8154 named_type = *named++;
8155 data_type = *named++; /* type of data */
8156 if (data_type == MONO_TYPE_SZARRAY)
8157 data_type = *named++;
8158 if (data_type == MONO_TYPE_ENUM) {
8161 type_len = mono_metadata_decode_blob_size (named, &named);
8162 type_name = g_malloc (type_len + 1);
8163 memcpy (type_name, named, type_len);
8164 type_name [type_len] = 0;
8166 /* FIXME: lookup the type and check type consistency */
8169 name_len = mono_metadata_decode_blob_size (named, &named);
8170 name = g_malloc (name_len + 1);
8171 memcpy (name, named, name_len);
8172 name [name_len] = 0;
8174 if (named_type == 0x53) {
8175 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8176 void *val = load_cattr_value (image, field->type, named, &named);
8177 mono_field_set_value (attr, field, val);
8178 if (!type_is_reference (field->type))
8180 } else if (named_type == 0x54) {
8183 MonoType *prop_type;
8185 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8186 /* can we have more that 1 arg in a custom attr named property? */
8187 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8188 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8189 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8190 mono_property_set_value (prop, attr, pparams, NULL);
8191 if (!type_is_reference (prop_type))
8192 g_free (pparams [0]);
8197 if (params != params_buf)
8198 mono_gc_free_fixed (params);
8204 * mono_reflection_create_custom_attr_data_args:
8206 * Create an array of typed and named arguments from the cattr blob given by DATA.
8207 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8208 * NAMED_ARG_INFO will contain information about the named arguments.
8211 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)
8213 MonoArray *typedargs, *namedargs;
8214 MonoClass *attrklass;
8216 const char *p = (const char*)data;
8218 guint32 i, j, num_named;
8219 CattrNamedArg *arginfo = NULL;
8221 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8224 mono_class_init (method->klass);
8228 *named_arg_info = NULL;
8230 domain = mono_domain_get ();
8232 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8235 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8239 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8243 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8244 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8245 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8246 mono_array_setref (typedargs, i, obj);
8248 if (!type_is_reference (mono_method_signature (method)->params [i]))
8253 num_named = read16 (named);
8254 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8256 attrklass = method->klass;
8258 arginfo = g_new0 (CattrNamedArg, num_named);
8259 *named_arg_info = arginfo;
8261 for (j = 0; j < num_named; j++) {
8263 char *name, named_type, data_type;
8264 named_type = *named++;
8265 data_type = *named++; /* type of data */
8266 if (data_type == MONO_TYPE_SZARRAY)
8267 data_type = *named++;
8268 if (data_type == MONO_TYPE_ENUM) {
8271 type_len = mono_metadata_decode_blob_size (named, &named);
8272 type_name = g_malloc (type_len + 1);
8273 memcpy (type_name, named, type_len);
8274 type_name [type_len] = 0;
8276 /* FIXME: lookup the type and check type consistency */
8279 name_len = mono_metadata_decode_blob_size (named, &named);
8280 name = g_malloc (name_len + 1);
8281 memcpy (name, named, name_len);
8282 name [name_len] = 0;
8284 if (named_type == 0x53) {
8286 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8289 arginfo [j].type = field->type;
8290 arginfo [j].field = field;
8292 val = load_cattr_value (image, field->type, named, &named);
8293 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8294 mono_array_setref (namedargs, j, obj);
8295 if (!type_is_reference (field->type))
8297 } else if (named_type == 0x54) {
8299 MonoType *prop_type;
8300 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8303 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8304 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8306 arginfo [j].type = prop_type;
8307 arginfo [j].prop = prop;
8309 val = load_cattr_value (image, prop_type, named, &named);
8310 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8311 mono_array_setref (namedargs, j, obj);
8312 if (!type_is_reference (prop_type))
8318 *typed_args = typedargs;
8319 *named_args = namedargs;
8323 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8326 MonoArray *typedargs, *namedargs;
8329 CattrNamedArg *arginfo;
8338 image = assembly->assembly->image;
8339 method = ref_method->method;
8340 domain = mono_object_domain (ref_method);
8342 if (!mono_class_init (method->klass))
8343 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8345 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8346 if (mono_loader_get_last_error ())
8347 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8349 if (!typedargs || !namedargs)
8352 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8353 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8354 MonoObject *typedarg;
8356 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8357 mono_array_setref (typedargs, i, typedarg);
8360 for (i = 0; i < mono_array_length (namedargs); ++i) {
8361 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8362 MonoObject *typedarg, *namedarg, *minfo;
8364 if (arginfo [i].prop)
8365 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8367 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8369 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8370 namedarg = create_cattr_named_arg (minfo, typedarg);
8372 mono_array_setref (namedargs, i, namedarg);
8375 *ctor_args = typedargs;
8376 *named_args = namedargs;
8380 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8382 static MonoMethod *ctor;
8387 g_assert (image->assembly);
8390 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8392 domain = mono_domain_get ();
8393 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8394 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8395 params [1] = mono_assembly_get_object (domain, image->assembly);
8396 params [2] = (gpointer)&cattr->data;
8397 params [3] = &cattr->data_size;
8398 mono_runtime_invoke (ctor, attr, params, NULL);
8403 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8409 mono_error_init (error);
8412 for (i = 0; i < cinfo->num_attrs; ++i) {
8413 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8417 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8419 for (i = 0; i < cinfo->num_attrs; ++i) {
8420 if (!cinfo->attrs [i].ctor)
8421 /* The cattr type is not finished yet */
8422 /* We should include the type name but cinfo doesn't contain it */
8423 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8424 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8425 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8426 if (!mono_error_ok (error))
8428 mono_array_setref (result, n, attr);
8436 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8440 return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8444 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8450 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8451 for (i = 0; i < cinfo->num_attrs; ++i) {
8452 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8453 mono_array_setref (result, i, attr);
8459 * mono_custom_attrs_from_index:
8461 * Returns: NULL if no attributes are found or if a loading error occurs.
8464 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8466 guint32 mtoken, i, len;
8467 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8469 MonoCustomAttrInfo *ainfo;
8470 GList *tmp, *list = NULL;
8473 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8475 i = mono_metadata_custom_attrs_from_index (image, idx);
8479 while (i < ca->rows) {
8480 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8482 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8485 len = g_list_length (list);
8488 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8489 ainfo->num_attrs = len;
8490 ainfo->image = image;
8491 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8492 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8493 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8494 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8495 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8496 mtoken |= MONO_TOKEN_METHOD_DEF;
8498 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8499 mtoken |= MONO_TOKEN_MEMBER_REF;
8502 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8505 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8506 if (!ainfo->attrs [i].ctor) {
8507 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8513 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8514 /*FIXME raising an exception here doesn't make any sense*/
8515 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8520 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8521 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8522 ainfo->attrs [i].data = (guchar*)data;
8530 mono_custom_attrs_from_method (MonoMethod *method)
8535 * An instantiated method has the same cattrs as the generic method definition.
8537 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8538 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8540 if (method->is_inflated)
8541 method = ((MonoMethodInflated *) method)->declaring;
8543 if (method->dynamic || method->klass->image->dynamic)
8544 return lookup_custom_attr (method->klass->image, method);
8547 /* Synthetic methods */
8550 idx = mono_method_get_index (method);
8551 idx <<= MONO_CUSTOM_ATTR_BITS;
8552 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8553 return mono_custom_attrs_from_index (method->klass->image, idx);
8557 mono_custom_attrs_from_class (MonoClass *klass)
8561 if (klass->generic_class)
8562 klass = klass->generic_class->container_class;
8564 if (klass->image->dynamic)
8565 return lookup_custom_attr (klass->image, klass);
8567 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8568 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8569 idx <<= MONO_CUSTOM_ATTR_BITS;
8570 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8572 idx = mono_metadata_token_index (klass->type_token);
8573 idx <<= MONO_CUSTOM_ATTR_BITS;
8574 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8576 return mono_custom_attrs_from_index (klass->image, idx);
8580 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8584 if (assembly->image->dynamic)
8585 return lookup_custom_attr (assembly->image, assembly);
8586 idx = 1; /* there is only one assembly */
8587 idx <<= MONO_CUSTOM_ATTR_BITS;
8588 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8589 return mono_custom_attrs_from_index (assembly->image, idx);
8592 static MonoCustomAttrInfo*
8593 mono_custom_attrs_from_module (MonoImage *image)
8598 return lookup_custom_attr (image, image);
8599 idx = 1; /* there is only one module */
8600 idx <<= MONO_CUSTOM_ATTR_BITS;
8601 idx |= MONO_CUSTOM_ATTR_MODULE;
8602 return mono_custom_attrs_from_index (image, idx);
8606 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8610 if (klass->image->dynamic) {
8611 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8612 return lookup_custom_attr (klass->image, property);
8614 idx = find_property_index (klass, property);
8615 idx <<= MONO_CUSTOM_ATTR_BITS;
8616 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8617 return mono_custom_attrs_from_index (klass->image, idx);
8621 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8625 if (klass->image->dynamic) {
8626 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8627 return lookup_custom_attr (klass->image, event);
8629 idx = find_event_index (klass, event);
8630 idx <<= MONO_CUSTOM_ATTR_BITS;
8631 idx |= MONO_CUSTOM_ATTR_EVENT;
8632 return mono_custom_attrs_from_index (klass->image, idx);
8636 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8639 if (klass->image->dynamic) {
8640 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8641 return lookup_custom_attr (klass->image, field);
8643 idx = find_field_index (klass, field);
8644 idx <<= MONO_CUSTOM_ATTR_BITS;
8645 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8646 return mono_custom_attrs_from_index (klass->image, idx);
8650 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8653 guint32 i, idx, method_index;
8654 guint32 param_list, param_last, param_pos, found;
8656 MonoReflectionMethodAux *aux;
8659 * An instantiated method has the same cattrs as the generic method definition.
8661 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8662 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8664 if (method->is_inflated)
8665 method = ((MonoMethodInflated *) method)->declaring;
8667 if (method->klass->image->dynamic) {
8668 MonoCustomAttrInfo *res, *ainfo;
8671 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8672 if (!aux || !aux->param_cattr)
8675 /* Need to copy since it will be freed later */
8676 ainfo = aux->param_cattr [param];
8679 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8680 res = g_malloc0 (size);
8681 memcpy (res, ainfo, size);
8685 image = method->klass->image;
8686 method_index = mono_method_get_index (method);
8689 ca = &image->tables [MONO_TABLE_METHOD];
8691 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8692 if (method_index == ca->rows) {
8693 ca = &image->tables [MONO_TABLE_PARAM];
8694 param_last = ca->rows + 1;
8696 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8697 ca = &image->tables [MONO_TABLE_PARAM];
8700 for (i = param_list; i < param_last; ++i) {
8701 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8702 if (param_pos == param) {
8710 idx <<= MONO_CUSTOM_ATTR_BITS;
8711 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8712 return mono_custom_attrs_from_index (image, idx);
8716 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8720 for (i = 0; i < ainfo->num_attrs; ++i) {
8721 klass = ainfo->attrs [i].ctor->klass;
8722 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8729 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8736 for (i = 0; i < ainfo->num_attrs; ++i) {
8737 klass = ainfo->attrs [i].ctor->klass;
8738 if (mono_class_has_parent (klass, attr_klass)) {
8743 if (attr_index == -1)
8746 attrs = mono_custom_attrs_construct (ainfo);
8748 return mono_array_get (attrs, MonoObject*, attr_index);
8754 * mono_reflection_get_custom_attrs_info:
8755 * @obj: a reflection object handle
8757 * Return the custom attribute info for attributes defined for the
8758 * reflection handle @obj. The objects.
8760 * FIXME this function leaks like a sieve for SRE objects.
8763 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8766 MonoCustomAttrInfo *cinfo = NULL;
8768 klass = obj->vtable->klass;
8769 if (klass == mono_defaults.monotype_class) {
8770 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8771 klass = mono_class_from_mono_type (type);
8772 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8773 cinfo = mono_custom_attrs_from_class (klass);
8774 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8775 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8776 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8777 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8778 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8779 cinfo = mono_custom_attrs_from_module (module->image);
8780 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8781 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8782 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8783 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8784 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8785 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8786 } else if (strcmp ("MonoField", klass->name) == 0) {
8787 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8788 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8789 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8790 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8791 cinfo = mono_custom_attrs_from_method (rmethod->method);
8792 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8793 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8794 cinfo = mono_custom_attrs_from_method (rmethod->method);
8795 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8796 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8797 MonoClass *member_class = mono_object_class (param->MemberImpl);
8798 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8799 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8800 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8801 } else if (is_sr_mono_property (member_class)) {
8802 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8804 if (!(method = prop->property->get))
8805 method = prop->property->set;
8808 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8810 #ifndef DISABLE_REFLECTION_EMIT
8811 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8812 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8813 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8814 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8815 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8816 MonoMethod *method = NULL;
8817 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8818 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8819 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8820 method = ((MonoReflectionMethod *)c->cb)->method;
8822 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));
8824 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8828 char *type_name = mono_type_get_full_name (member_class);
8829 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8830 MonoException *ex = mono_get_exception_not_supported (msg);
8833 mono_raise_exception (ex);
8835 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8836 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8837 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8838 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8839 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8840 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8841 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8842 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8843 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8844 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8845 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8846 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8847 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8848 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8849 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8850 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8851 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8852 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8853 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8854 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8855 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8856 } else { /* handle other types here... */
8857 g_error ("get custom attrs not yet supported for %s", klass->name);
8864 * mono_reflection_get_custom_attrs_by_type:
8865 * @obj: a reflection object handle
8867 * Return an array with all the custom attributes defined of the
8868 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8869 * of that type are returned. The objects are fully build. Return NULL if a loading error
8873 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8876 MonoCustomAttrInfo *cinfo;
8878 mono_error_init (error);
8880 cinfo = mono_reflection_get_custom_attrs_info (obj);
8882 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8884 mono_custom_attrs_free (cinfo);
8886 if (mono_loader_get_last_error ())
8888 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8895 * mono_reflection_get_custom_attrs:
8896 * @obj: a reflection object handle
8898 * Return an array with all the custom attributes defined of the
8899 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8903 mono_reflection_get_custom_attrs (MonoObject *obj)
8907 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8911 * mono_reflection_get_custom_attrs_data:
8912 * @obj: a reflection obj handle
8914 * Returns an array of System.Reflection.CustomAttributeData,
8915 * which include information about attributes reflected on
8916 * types loaded using the Reflection Only methods
8919 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8922 MonoCustomAttrInfo *cinfo;
8924 cinfo = mono_reflection_get_custom_attrs_info (obj);
8926 result = mono_custom_attrs_data_construct (cinfo);
8928 mono_custom_attrs_free (cinfo);
8930 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8935 static MonoReflectionType*
8936 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8938 static MonoMethod *method_get_underlying_system_type = NULL;
8939 MonoMethod *usertype_method;
8941 if (!method_get_underlying_system_type)
8942 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8943 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8944 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8949 is_corlib_type (MonoClass *class)
8951 return class->image == mono_defaults.corlib;
8954 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8955 static MonoClass *cached_class; \
8957 return cached_class == _class; \
8958 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8959 cached_class = _class; \
8966 #ifndef DISABLE_REFLECTION_EMIT
8968 is_sre_array (MonoClass *class)
8970 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8974 is_sre_byref (MonoClass *class)
8976 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8980 is_sre_pointer (MonoClass *class)
8982 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8986 is_sre_generic_instance (MonoClass *class)
8988 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8992 is_sre_type_builder (MonoClass *class)
8994 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8998 is_sre_method_builder (MonoClass *class)
9000 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9004 is_sre_ctor_builder (MonoClass *class)
9006 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9010 is_sre_field_builder (MonoClass *class)
9012 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9016 is_sre_method_on_tb_inst (MonoClass *class)
9018 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9022 is_sre_ctor_on_tb_inst (MonoClass *class)
9024 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9028 mono_reflection_type_get_handle (MonoReflectionType* ref)
9036 if (is_usertype (ref)) {
9037 ref = mono_reflection_type_get_underlying_system_type (ref);
9038 if (ref == NULL || is_usertype (ref))
9044 class = mono_object_class (ref);
9046 if (is_sre_array (class)) {
9048 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9049 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9051 if (sre_array->rank == 0) //single dimentional array
9052 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9054 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9055 sre_array->type.type = res;
9057 } else if (is_sre_byref (class)) {
9059 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9060 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9062 res = &mono_class_from_mono_type (base)->this_arg;
9063 sre_byref->type.type = res;
9065 } else if (is_sre_pointer (class)) {
9067 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9068 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9070 res = &mono_ptr_class_get (base)->byval_arg;
9071 sre_pointer->type.type = res;
9073 } else if (is_sre_generic_instance (class)) {
9074 MonoType *res, **types;
9075 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9078 count = mono_array_length (gclass->type_arguments);
9079 types = g_new0 (MonoType*, count);
9080 for (i = 0; i < count; ++i) {
9081 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9082 types [i] = mono_reflection_type_get_handle (t);
9089 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9092 gclass->type.type = res;
9096 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9103 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9105 mono_reflection_type_get_handle (type);
9109 mono_reflection_register_with_runtime (MonoReflectionType *type)
9111 MonoType *res = mono_reflection_type_get_handle (type);
9112 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9116 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9118 class = mono_class_from_mono_type (res);
9120 mono_loader_lock (); /*same locking as mono_type_get_object*/
9121 mono_domain_lock (domain);
9123 if (!class->image->dynamic) {
9124 mono_class_setup_supertypes (class);
9126 if (!domain->type_hash)
9127 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9128 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9129 mono_g_hash_table_insert (domain->type_hash, res, type);
9131 mono_domain_unlock (domain);
9132 mono_loader_unlock ();
9136 * LOCKING: Assumes the loader lock is held.
9138 static MonoMethodSignature*
9139 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9140 MonoMethodSignature *sig;
9143 count = parameters? mono_array_length (parameters): 0;
9145 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9146 sig->param_count = count;
9147 sig->sentinelpos = -1; /* FIXME */
9148 for (i = 0; i < count; ++i)
9149 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9154 * LOCKING: Assumes the loader lock is held.
9156 static MonoMethodSignature*
9157 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9158 MonoMethodSignature *sig;
9160 sig = parameters_to_signature (image, ctor->parameters);
9161 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9162 sig->ret = &mono_defaults.void_class->byval_arg;
9167 * LOCKING: Assumes the loader lock is held.
9169 static MonoMethodSignature*
9170 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9171 MonoMethodSignature *sig;
9173 sig = parameters_to_signature (image, method->parameters);
9174 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9175 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9176 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9180 static MonoMethodSignature*
9181 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9182 MonoMethodSignature *sig;
9184 sig = parameters_to_signature (NULL, method->parameters);
9185 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9186 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9187 sig->generic_param_count = 0;
9192 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9194 MonoClass *klass = mono_object_class (prop);
9195 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9196 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9197 *name = mono_string_to_utf8 (pb->name);
9198 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9200 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9201 *name = g_strdup (p->property->name);
9202 if (p->property->get)
9203 *type = mono_method_signature (p->property->get)->ret;
9205 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9210 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9212 MonoClass *klass = mono_object_class (field);
9213 if (strcmp (klass->name, "FieldBuilder") == 0) {
9214 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9215 *name = mono_string_to_utf8 (fb->name);
9216 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9218 MonoReflectionField *f = (MonoReflectionField *)field;
9219 *name = g_strdup (mono_field_get_name (f->field));
9220 *type = f->field->type;
9224 #else /* DISABLE_REFLECTION_EMIT */
9227 mono_reflection_register_with_runtime (MonoReflectionType *type)
9233 is_sre_type_builder (MonoClass *class)
9239 is_sre_generic_instance (MonoClass *class)
9245 init_type_builder_generics (MonoObject *type)
9249 #endif /* !DISABLE_REFLECTION_EMIT */
9253 is_sr_mono_field (MonoClass *class)
9255 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9259 is_sr_mono_property (MonoClass *class)
9261 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9265 is_sr_mono_method (MonoClass *class)
9267 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9271 is_sr_mono_cmethod (MonoClass *class)
9273 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9277 is_sr_mono_generic_method (MonoClass *class)
9279 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9283 is_sr_mono_generic_cmethod (MonoClass *class)
9285 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9289 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9291 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9295 is_usertype (MonoReflectionType *ref)
9297 MonoClass *class = mono_object_class (ref);
9298 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9301 static MonoReflectionType*
9302 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9304 if (!type || type->type)
9307 if (is_usertype (type)) {
9308 type = mono_reflection_type_get_underlying_system_type (type);
9309 if (is_usertype (type))
9310 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9316 * Encode a value in a custom attribute stream of bytes.
9317 * The value to encode is either supplied as an object in argument val
9318 * (valuetypes are boxed), or as a pointer to the data in the
9320 * @type represents the type of the value
9321 * @buffer is the start of the buffer
9322 * @p the current position in the buffer
9323 * @buflen contains the size of the buffer and is used to return the new buffer size
9324 * if this needs to be realloced.
9325 * @retbuffer and @retp return the start and the position of the buffer
9328 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9330 MonoTypeEnum simple_type;
9332 if ((p-buffer) + 10 >= *buflen) {
9335 newbuf = g_realloc (buffer, *buflen);
9336 p = newbuf + (p-buffer);
9340 argval = ((char*)arg + sizeof (MonoObject));
9341 simple_type = type->type;
9343 switch (simple_type) {
9344 case MONO_TYPE_BOOLEAN:
9349 case MONO_TYPE_CHAR:
9352 swap_with_size (p, argval, 2, 1);
9358 swap_with_size (p, argval, 4, 1);
9362 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9372 swap_with_size (p, argval, 8, 1);
9378 swap_with_size (p, argval, 8, 1);
9381 case MONO_TYPE_VALUETYPE:
9382 if (type->data.klass->enumtype) {
9383 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9386 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9389 case MONO_TYPE_STRING: {
9396 str = mono_string_to_utf8 ((MonoString*)arg);
9397 slen = strlen (str);
9398 if ((p-buffer) + 10 + slen >= *buflen) {
9402 newbuf = g_realloc (buffer, *buflen);
9403 p = newbuf + (p-buffer);
9406 mono_metadata_encode_value (slen, p, &p);
9407 memcpy (p, str, slen);
9412 case MONO_TYPE_CLASS: {
9420 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9421 slen = strlen (str);
9422 if ((p-buffer) + 10 + slen >= *buflen) {
9426 newbuf = g_realloc (buffer, *buflen);
9427 p = newbuf + (p-buffer);
9430 mono_metadata_encode_value (slen, p, &p);
9431 memcpy (p, str, slen);
9436 case MONO_TYPE_SZARRAY: {
9438 MonoClass *eclass, *arg_eclass;
9441 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9444 len = mono_array_length ((MonoArray*)arg);
9446 *p++ = (len >> 8) & 0xff;
9447 *p++ = (len >> 16) & 0xff;
9448 *p++ = (len >> 24) & 0xff;
9450 *retbuffer = buffer;
9451 eclass = type->data.klass;
9452 arg_eclass = mono_object_class (arg)->element_class;
9455 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9456 eclass = mono_defaults.object_class;
9458 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9459 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9460 int elsize = mono_class_array_element_size (arg_eclass);
9461 for (i = 0; i < len; ++i) {
9462 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9465 } else if (eclass->valuetype && arg_eclass->valuetype) {
9466 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9467 int elsize = mono_class_array_element_size (eclass);
9468 for (i = 0; i < len; ++i) {
9469 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9473 for (i = 0; i < len; ++i) {
9474 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9479 case MONO_TYPE_OBJECT: {
9485 * The parameter type is 'object' but the type of the actual
9486 * argument is not. So we have to add type information to the blob
9487 * too. This is completely undocumented in the spec.
9491 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9496 klass = mono_object_class (arg);
9498 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9501 } else if (klass->enumtype) {
9503 } else if (klass == mono_defaults.string_class) {
9504 simple_type = MONO_TYPE_STRING;
9507 } else if (klass->rank == 1) {
9509 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9510 /* See Partition II, Appendix B3 */
9513 *p++ = klass->element_class->byval_arg.type;
9514 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9516 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9517 *p++ = simple_type = klass->byval_arg.type;
9520 g_error ("unhandled type in custom attr");
9522 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9523 slen = strlen (str);
9524 if ((p-buffer) + 10 + slen >= *buflen) {
9528 newbuf = g_realloc (buffer, *buflen);
9529 p = newbuf + (p-buffer);
9532 mono_metadata_encode_value (slen, p, &p);
9533 memcpy (p, str, slen);
9536 simple_type = mono_class_enum_basetype (klass)->type;
9540 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9543 *retbuffer = buffer;
9547 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9549 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9550 char *str = type_get_qualified_name (type, NULL);
9551 int slen = strlen (str);
9555 * This seems to be optional...
9558 mono_metadata_encode_value (slen, p, &p);
9559 memcpy (p, str, slen);
9562 } else if (type->type == MONO_TYPE_OBJECT) {
9564 } else if (type->type == MONO_TYPE_CLASS) {
9565 /* it should be a type: encode_cattr_value () has the check */
9568 mono_metadata_encode_value (type->type, p, &p);
9569 if (type->type == MONO_TYPE_SZARRAY)
9570 /* See the examples in Partition VI, Annex B */
9571 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9577 #ifndef DISABLE_REFLECTION_EMIT
9579 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9582 /* Preallocate a large enough buffer */
9583 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9584 char *str = type_get_qualified_name (type, NULL);
9587 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9588 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9594 len += strlen (name);
9596 if ((p-buffer) + 20 + len >= *buflen) {
9600 newbuf = g_realloc (buffer, *buflen);
9601 p = newbuf + (p-buffer);
9605 encode_field_or_prop_type (type, p, &p);
9607 len = strlen (name);
9608 mono_metadata_encode_value (len, p, &p);
9609 memcpy (p, name, len);
9611 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9613 *retbuffer = buffer;
9617 * mono_reflection_get_custom_attrs_blob:
9618 * @ctor: custom attribute constructor
9619 * @ctorArgs: arguments o the constructor
9625 * Creates the blob of data that needs to be saved in the metadata and that represents
9626 * the custom attributed described by @ctor, @ctorArgs etc.
9627 * Returns: a Byte array representing the blob of data.
9630 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9633 MonoMethodSignature *sig;
9638 MONO_ARCH_SAVE_REGS;
9640 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9641 /* sig is freed later so allocate it in the heap */
9642 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9644 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9647 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9649 p = buffer = g_malloc (buflen);
9650 /* write the prolog */
9653 for (i = 0; i < sig->param_count; ++i) {
9654 arg = mono_array_get (ctorArgs, MonoObject*, i);
9655 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9659 i += mono_array_length (properties);
9661 i += mono_array_length (fields);
9663 *p++ = (i >> 8) & 0xff;
9666 for (i = 0; i < mono_array_length (properties); ++i) {
9670 prop = mono_array_get (properties, gpointer, i);
9671 get_prop_name_and_type (prop, &pname, &ptype);
9672 *p++ = 0x54; /* PROPERTY signature */
9673 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9680 for (i = 0; i < mono_array_length (fields); ++i) {
9684 field = mono_array_get (fields, gpointer, i);
9685 get_field_name_and_type (field, &fname, &ftype);
9686 *p++ = 0x53; /* FIELD signature */
9687 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9692 g_assert (p - buffer <= buflen);
9693 buflen = p - buffer;
9694 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9695 p = mono_array_addr (result, char, 0);
9696 memcpy (p, buffer, buflen);
9698 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9704 * mono_reflection_setup_internal_class:
9705 * @tb: a TypeBuilder object
9707 * Creates a MonoClass that represents the TypeBuilder.
9708 * This is a trick that lets us simplify a lot of reflection code
9709 * (and will allow us to support Build and Run assemblies easier).
9712 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9715 MonoClass *klass, *parent;
9717 MONO_ARCH_SAVE_REGS;
9719 RESOLVE_TYPE (tb->parent);
9721 mono_loader_lock ();
9724 /* check so we can compile corlib correctly */
9725 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9726 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9727 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9729 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9735 /* the type has already being created: it means we just have to change the parent */
9736 if (tb->type.type) {
9737 klass = mono_class_from_mono_type (tb->type.type);
9738 klass->parent = NULL;
9739 /* fool mono_class_setup_parent */
9740 klass->supertypes = NULL;
9741 mono_class_setup_parent (klass, parent);
9742 mono_class_setup_mono_type (klass);
9743 mono_loader_unlock ();
9747 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9749 klass->image = &tb->module->dynamic_image->image;
9751 klass->inited = 1; /* we lie to the runtime */
9752 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9753 if (!mono_error_ok (&error))
9755 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9756 if (!mono_error_ok (&error))
9758 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9759 klass->flags = tb->attrs;
9761 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9763 klass->element_class = klass;
9765 if (mono_class_get_ref_info (klass) == NULL) {
9767 mono_class_set_ref_info (klass, tb);
9769 /* Put into cache so mono_class_get () will find it.
9770 Skip nested types as those should not be available on the global scope. */
9771 if (!tb->nesting_type) {
9772 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9774 klass->image->reflection_info_unregister_classes =
9775 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9778 g_assert (mono_class_get_ref_info (klass) == tb);
9781 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9782 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9784 if (parent != NULL) {
9785 mono_class_setup_parent (klass, parent);
9786 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9787 const char *old_n = klass->name;
9788 /* trick to get relative numbering right when compiling corlib */
9789 klass->name = "BuildingObject";
9790 mono_class_setup_parent (klass, mono_defaults.object_class);
9791 klass->name = old_n;
9794 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9795 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9796 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9797 klass->instance_size = sizeof (MonoObject);
9798 klass->size_inited = 1;
9799 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9802 mono_class_setup_mono_type (klass);
9804 mono_class_setup_supertypes (klass);
9807 * FIXME: handle interfaces.
9810 tb->type.type = &klass->byval_arg;
9812 if (tb->nesting_type) {
9813 g_assert (tb->nesting_type->type);
9814 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9817 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9819 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9821 mono_loader_unlock ();
9825 mono_loader_unlock ();
9826 mono_error_raise_exception (&error);
9830 * mono_reflection_setup_generic_class:
9831 * @tb: a TypeBuilder object
9833 * Setup the generic class before adding the first generic parameter.
9836 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9841 * mono_reflection_create_generic_class:
9842 * @tb: a TypeBuilder object
9844 * Creates the generic class after all generic parameters have been added.
9847 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9852 MONO_ARCH_SAVE_REGS;
9854 klass = mono_class_from_mono_type (tb->type.type);
9856 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9858 if (klass->generic_container || (count == 0))
9861 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9863 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9865 klass->generic_container->owner.klass = klass;
9866 klass->generic_container->type_argc = count;
9867 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9869 klass->is_generic = 1;
9871 for (i = 0; i < count; i++) {
9872 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9873 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9874 klass->generic_container->type_params [i] = *param;
9875 /*Make sure we are a diferent type instance */
9876 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9877 klass->generic_container->type_params [i].info.pklass = NULL;
9878 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9880 g_assert (klass->generic_container->type_params [i].param.owner);
9883 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9887 * mono_reflection_create_internal_class:
9888 * @tb: a TypeBuilder object
9890 * Actually create the MonoClass that is associated with the TypeBuilder.
9893 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9897 MONO_ARCH_SAVE_REGS;
9899 klass = mono_class_from_mono_type (tb->type.type);
9901 mono_loader_lock ();
9902 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9903 MonoReflectionFieldBuilder *fb;
9905 MonoType *enum_basetype;
9907 g_assert (tb->fields != NULL);
9908 g_assert (mono_array_length (tb->fields) >= 1);
9910 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9912 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9913 mono_loader_unlock ();
9917 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9918 klass->element_class = mono_class_from_mono_type (enum_basetype);
9919 if (!klass->element_class)
9920 klass->element_class = mono_class_from_mono_type (enum_basetype);
9923 * get the element_class from the current corlib.
9925 ec = default_class_from_mono_type (enum_basetype);
9926 klass->instance_size = ec->instance_size;
9927 klass->size_inited = 1;
9929 * this is almost safe to do with enums and it's needed to be able
9930 * to create objects of the enum type (for use in SetConstant).
9932 /* FIXME: Does this mean enums can't have method overrides ? */
9933 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9935 mono_loader_unlock ();
9938 static MonoMarshalSpec*
9939 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9940 MonoReflectionMarshal *minfo)
9942 MonoMarshalSpec *res;
9944 res = image_g_new0 (image, MonoMarshalSpec, 1);
9945 res->native = minfo->type;
9947 switch (minfo->type) {
9948 case MONO_NATIVE_LPARRAY:
9949 res->data.array_data.elem_type = minfo->eltype;
9950 if (minfo->has_size) {
9951 res->data.array_data.param_num = minfo->param_num;
9952 res->data.array_data.num_elem = minfo->count;
9953 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9956 res->data.array_data.param_num = -1;
9957 res->data.array_data.num_elem = -1;
9958 res->data.array_data.elem_mult = -1;
9962 case MONO_NATIVE_BYVALTSTR:
9963 case MONO_NATIVE_BYVALARRAY:
9964 res->data.array_data.num_elem = minfo->count;
9967 case MONO_NATIVE_CUSTOM:
9968 if (minfo->marshaltyperef)
9969 res->data.custom_data.custom_name =
9970 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9972 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9981 #endif /* !DISABLE_REFLECTION_EMIT */
9983 MonoReflectionMarshal*
9984 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9985 MonoMarshalSpec *spec)
9987 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9988 MonoReflectionMarshal *minfo;
9991 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9992 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9993 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9994 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9997 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9998 minfo->type = spec->native;
10000 switch (minfo->type) {
10001 case MONO_NATIVE_LPARRAY:
10002 minfo->eltype = spec->data.array_data.elem_type;
10003 minfo->count = spec->data.array_data.num_elem;
10004 minfo->param_num = spec->data.array_data.param_num;
10007 case MONO_NATIVE_BYVALTSTR:
10008 case MONO_NATIVE_BYVALARRAY:
10009 minfo->count = spec->data.array_data.num_elem;
10012 case MONO_NATIVE_CUSTOM:
10013 if (spec->data.custom_data.custom_name) {
10014 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10016 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10018 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10020 if (spec->data.custom_data.cookie)
10021 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10031 #ifndef DISABLE_REFLECTION_EMIT
10033 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10034 ReflectionMethodBuilder *rmb,
10035 MonoMethodSignature *sig)
10039 MonoMethodWrapper *wrapperm;
10040 MonoMarshalSpec **specs;
10041 MonoReflectionMethodAux *method_aux;
10046 mono_error_init (&error);
10048 * Methods created using a MethodBuilder should have their memory allocated
10049 * inside the image mempool, while dynamic methods should have their memory
10052 dynamic = rmb->refs != NULL;
10053 image = dynamic ? NULL : klass->image;
10056 g_assert (!klass->generic_class);
10058 mono_loader_lock ();
10060 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10061 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10062 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10064 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10066 wrapperm = (MonoMethodWrapper*)m;
10068 m->dynamic = dynamic;
10070 m->flags = rmb->attrs;
10071 m->iflags = rmb->iattrs;
10072 m->name = mono_string_to_utf8_image_ignore (image, rmb->name);
10074 m->signature = sig;
10075 m->sre_method = TRUE;
10076 m->skip_visibility = rmb->skip_visibility;
10077 if (rmb->table_idx)
10078 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10080 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10081 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10082 m->string_ctor = 1;
10084 m->signature->pinvoke = 1;
10085 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10086 m->signature->pinvoke = 1;
10088 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10090 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10091 g_assert (mono_error_ok (&error));
10092 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10093 g_assert (mono_error_ok (&error));
10095 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10097 if (klass->image->dynamic)
10098 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10100 mono_loader_unlock ();
10103 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10104 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10105 MonoMethodHeader *header;
10107 gint32 max_stack, i;
10108 gint32 num_locals = 0;
10109 gint32 num_clauses = 0;
10113 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10114 code_size = rmb->ilgen->code_len;
10115 max_stack = rmb->ilgen->max_stack;
10116 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10117 if (rmb->ilgen->ex_handlers)
10118 num_clauses = method_count_clauses (rmb->ilgen);
10121 code = mono_array_addr (rmb->code, guint8, 0);
10122 code_size = mono_array_length (rmb->code);
10123 /* we probably need to run a verifier on the code... */
10133 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10134 header->code_size = code_size;
10135 header->code = image_g_malloc (image, code_size);
10136 memcpy ((char*)header->code, code, code_size);
10137 header->max_stack = max_stack;
10138 header->init_locals = rmb->init_locals;
10139 header->num_locals = num_locals;
10141 for (i = 0; i < num_locals; ++i) {
10142 MonoReflectionLocalBuilder *lb =
10143 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10145 header->locals [i] = image_g_new0 (image, MonoType, 1);
10146 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10149 header->num_clauses = num_clauses;
10151 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10152 rmb->ilgen, num_clauses);
10155 wrapperm->header = header;
10158 if (rmb->generic_params) {
10159 int count = mono_array_length (rmb->generic_params);
10160 MonoGenericContainer *container = rmb->generic_container;
10162 g_assert (container);
10164 container->type_argc = count;
10165 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10166 container->owner.method = m;
10168 m->is_generic = TRUE;
10169 mono_method_set_generic_container (m, container);
10171 for (i = 0; i < count; i++) {
10172 MonoReflectionGenericParam *gp =
10173 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10174 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10175 container->type_params [i] = *param;
10179 * The method signature might have pointers to generic parameters that belong to other methods.
10180 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10181 * generic parameters.
10183 for (i = 0; i < m->signature->param_count; ++i) {
10184 MonoType *t = m->signature->params [i];
10185 if (t->type == MONO_TYPE_MVAR) {
10186 MonoGenericParam *gparam = t->data.generic_param;
10187 if (gparam->num < count) {
10188 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10189 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10195 if (klass->generic_container) {
10196 container->parent = klass->generic_container;
10197 container->context.class_inst = klass->generic_container->context.class_inst;
10199 container->context.method_inst = mono_get_shared_generic_inst (container);
10203 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10207 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10209 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10210 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10211 for (i = 0; i < rmb->nrefs; ++i)
10212 data [i + 1] = rmb->refs [i];
10217 /* Parameter info */
10220 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10221 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10222 for (i = 0; i <= m->signature->param_count; ++i) {
10223 MonoReflectionParamBuilder *pb;
10224 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10225 if ((i > 0) && (pb->attrs)) {
10226 /* Make a copy since it might point to a shared type structure */
10227 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10228 m->signature->params [i - 1]->attrs = pb->attrs;
10231 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10232 MonoDynamicImage *assembly;
10233 guint32 idx, def_type, len;
10237 if (!method_aux->param_defaults) {
10238 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10239 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10241 assembly = (MonoDynamicImage*)klass->image;
10242 idx = encode_constant (assembly, pb->def_value, &def_type);
10243 /* Copy the data from the blob since it might get realloc-ed */
10244 p = assembly->blob.data + idx;
10245 len = mono_metadata_decode_blob_size (p, &p2);
10247 method_aux->param_defaults [i] = image_g_malloc (image, len);
10248 method_aux->param_default_types [i] = def_type;
10249 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10253 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10254 g_assert (mono_error_ok (&error));
10257 if (!method_aux->param_cattr)
10258 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10259 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10265 /* Parameter marshalling */
10268 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10269 MonoReflectionParamBuilder *pb;
10270 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10271 if (pb->marshal_info) {
10273 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10274 specs [pb->position] =
10275 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10279 if (specs != NULL) {
10281 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10282 method_aux->param_marshall = specs;
10285 if (klass->image->dynamic && method_aux)
10286 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10288 mono_loader_unlock ();
10294 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10296 ReflectionMethodBuilder rmb;
10297 MonoMethodSignature *sig;
10299 mono_loader_lock ();
10300 sig = ctor_builder_to_signature (klass->image, mb);
10301 mono_loader_unlock ();
10303 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10305 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10306 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10308 /* If we are in a generic class, we might be called multiple times from inflate_method */
10309 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10310 /* ilgen is no longer needed */
10314 return mb->mhandle;
10318 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10320 ReflectionMethodBuilder rmb;
10321 MonoMethodSignature *sig;
10323 mono_loader_lock ();
10324 sig = method_builder_to_signature (klass->image, mb);
10325 mono_loader_unlock ();
10327 reflection_methodbuilder_from_method_builder (&rmb, mb);
10329 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10330 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10332 /* If we are in a generic class, we might be called multiple times from inflate_method */
10333 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10334 /* ilgen is no longer needed */
10337 return mb->mhandle;
10340 static MonoClassField*
10341 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10343 MonoClassField *field;
10347 field = g_new0 (MonoClassField, 1);
10349 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10350 g_assert (mono_error_ok (&error));
10351 if (fb->attrs || fb->modreq || fb->modopt) {
10352 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10353 field->type->attrs = fb->attrs;
10355 g_assert (klass->image->dynamic);
10356 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10357 g_free (field->type);
10358 field->type = mono_metadata_type_dup (klass->image, custom);
10361 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10363 if (fb->offset != -1)
10364 field->offset = fb->offset;
10365 field->parent = klass;
10366 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10368 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10375 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10378 MonoReflectionTypeBuilder *tb = NULL;
10379 gboolean is_dynamic = FALSE;
10380 MonoDomain *domain;
10381 MonoClass *geninst;
10383 mono_loader_lock ();
10385 domain = mono_object_domain (type);
10387 if (is_sre_type_builder (mono_object_class (type))) {
10388 tb = (MonoReflectionTypeBuilder *) type;
10391 } else if (is_sre_generic_instance (mono_object_class (type))) {
10392 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10393 MonoReflectionType *gtd = rgi->generic_type;
10395 if (is_sre_type_builder (mono_object_class (gtd))) {
10396 tb = (MonoReflectionTypeBuilder *)gtd;
10401 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10402 if (tb && tb->generic_container)
10403 mono_reflection_create_generic_class (tb);
10405 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10406 if (!klass->generic_container) {
10407 mono_loader_unlock ();
10411 if (klass->wastypebuilder) {
10412 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10417 mono_loader_unlock ();
10419 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10421 return &geninst->byval_arg;
10425 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10427 MonoGenericClass *gclass;
10428 MonoGenericInst *inst;
10430 g_assert (klass->generic_container);
10432 inst = mono_metadata_get_generic_inst (type_argc, types);
10433 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10435 return mono_generic_class_get_class (gclass);
10438 MonoReflectionMethod*
10439 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10442 MonoMethod *method, *inflated;
10443 MonoMethodInflated *imethod;
10444 MonoGenericContext tmp_context;
10445 MonoGenericInst *ginst;
10446 MonoType **type_argv;
10449 MONO_ARCH_SAVE_REGS;
10451 /*FIXME but this no longer should happen*/
10452 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10453 #ifndef DISABLE_REFLECTION_EMIT
10454 MonoReflectionMethodBuilder *mb = NULL;
10455 MonoReflectionTypeBuilder *tb;
10458 mb = (MonoReflectionMethodBuilder *) rmethod;
10459 tb = (MonoReflectionTypeBuilder *) mb->type;
10460 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10462 method = methodbuilder_to_mono_method (klass, mb);
10464 g_assert_not_reached ();
10468 method = rmethod->method;
10471 klass = method->klass;
10473 if (method->is_inflated)
10474 method = ((MonoMethodInflated *) method)->declaring;
10476 count = mono_method_signature (method)->generic_param_count;
10477 if (count != mono_array_length (types))
10480 type_argv = g_new0 (MonoType *, count);
10481 for (i = 0; i < count; i++) {
10482 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10483 type_argv [i] = mono_reflection_type_get_handle (garg);
10485 ginst = mono_metadata_get_generic_inst (count, type_argv);
10486 g_free (type_argv);
10488 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10489 tmp_context.method_inst = ginst;
10491 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10492 imethod = (MonoMethodInflated *) inflated;
10494 /*FIXME but I think this is no longer necessary*/
10495 if (method->klass->image->dynamic) {
10496 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10498 * This table maps metadata structures representing inflated methods/fields
10499 * to the reflection objects representing their generic definitions.
10501 mono_loader_lock ();
10502 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10503 mono_loader_unlock ();
10506 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10507 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10509 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10512 #ifndef DISABLE_REFLECTION_EMIT
10514 static MonoMethod *
10515 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10517 MonoMethodInflated *imethod;
10518 MonoGenericContext *context;
10522 * With generic code sharing the klass might not be inflated.
10523 * This can happen because classes inflated with their own
10524 * type arguments are "normalized" to the uninflated class.
10526 if (!klass->generic_class)
10529 context = mono_class_get_context (klass);
10531 if (klass->method.count && klass->methods) {
10532 /* Find the already created inflated method */
10533 for (i = 0; i < klass->method.count; ++i) {
10534 g_assert (klass->methods [i]->is_inflated);
10535 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10538 g_assert (i < klass->method.count);
10539 imethod = (MonoMethodInflated*)klass->methods [i];
10541 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10544 if (method->is_generic && method->klass->image->dynamic) {
10545 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10547 mono_loader_lock ();
10548 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10549 mono_loader_unlock ();
10551 return (MonoMethod *) imethod;
10554 static MonoMethod *
10555 inflate_method (MonoReflectionType *type, MonoObject *obj)
10557 MonoMethod *method;
10560 MonoClass *type_class = mono_object_class (type);
10562 if (is_sre_generic_instance (type_class)) {
10563 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10564 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10565 } else if (is_sre_type_builder (type_class)) {
10566 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10567 } else if (type->type) {
10568 gklass = mono_class_from_mono_type (type->type);
10569 gklass = mono_class_get_generic_type_definition (gklass);
10571 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10574 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10575 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10576 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10578 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10579 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10580 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10581 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10582 method = ((MonoReflectionMethod *) obj)->method;
10584 method = NULL; /* prevent compiler warning */
10585 g_error ("can't handle type %s", obj->vtable->klass->name);
10588 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10591 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10593 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10594 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10597 MonoGenericClass *gclass;
10598 MonoDynamicGenericClass *dgclass;
10599 MonoClass *klass, *gklass;
10603 MONO_ARCH_SAVE_REGS;
10605 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10606 klass = mono_class_from_mono_type (gtype);
10607 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10608 gclass = gtype->data.generic_class;
10610 if (!gclass->is_dynamic)
10613 dgclass = (MonoDynamicGenericClass *) gclass;
10615 if (dgclass->initialized)
10618 gklass = gclass->container_class;
10619 mono_class_init (gklass);
10621 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10623 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10624 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10625 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10627 for (i = 0; i < dgclass->count_fields; i++) {
10628 MonoObject *obj = mono_array_get (fields, gpointer, i);
10629 MonoClassField *field, *inflated_field = NULL;
10631 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10632 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10633 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10634 field = ((MonoReflectionField *) obj)->field;
10636 field = NULL; /* prevent compiler warning */
10637 g_assert_not_reached ();
10640 dgclass->fields [i] = *field;
10641 dgclass->fields [i].parent = klass;
10642 dgclass->fields [i].type = mono_class_inflate_generic_type (
10643 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10644 dgclass->field_generic_types [i] = field->type;
10645 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10646 dgclass->field_objects [i] = obj;
10648 if (inflated_field) {
10649 g_free (inflated_field);
10651 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10655 dgclass->initialized = TRUE;
10659 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10661 MonoDynamicGenericClass *dgclass;
10664 g_assert (gclass->is_dynamic);
10666 dgclass = (MonoDynamicGenericClass *)gclass;
10668 for (i = 0; i < dgclass->count_fields; ++i) {
10669 MonoClassField *field = dgclass->fields + i;
10670 mono_metadata_free_type (field->type);
10671 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10676 fix_partial_generic_class (MonoClass *klass)
10678 MonoClass *gklass = klass->generic_class->container_class;
10679 MonoDynamicGenericClass *dgclass;
10682 if (klass->wastypebuilder)
10685 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10686 if (klass->parent != gklass->parent) {
10688 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10689 if (mono_error_ok (&error)) {
10690 MonoClass *parent = mono_class_from_mono_type (parent_type);
10691 mono_metadata_free_type (parent_type);
10692 if (parent != klass->parent) {
10693 /*fool mono_class_setup_parent*/
10694 klass->supertypes = NULL;
10695 mono_class_setup_parent (klass, parent);
10698 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10699 mono_error_cleanup (&error);
10700 if (gklass->wastypebuilder)
10701 klass->wastypebuilder = TRUE;
10706 if (!dgclass->initialized)
10709 if (klass->method.count != gklass->method.count) {
10710 klass->method.count = gklass->method.count;
10711 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10713 for (i = 0; i < klass->method.count; i++) {
10714 klass->methods [i] = mono_class_inflate_generic_method_full (
10715 gklass->methods [i], klass, mono_class_get_context (klass));
10719 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10720 klass->interface_count = gklass->interface_count;
10721 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10722 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10724 for (i = 0; i < gklass->interface_count; ++i) {
10725 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10726 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10727 mono_metadata_free_type (iface_type);
10729 ensure_runtime_vtable (klass->interfaces [i]);
10731 klass->interfaces_inited = 1;
10734 if (klass->field.count != gklass->field.count) {
10735 klass->field.count = gklass->field.count;
10736 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10738 for (i = 0; i < klass->field.count; i++) {
10739 klass->fields [i] = gklass->fields [i];
10740 klass->fields [i].parent = klass;
10741 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10745 /*We can only finish with this klass once it's parent has as well*/
10746 if (gklass->wastypebuilder)
10747 klass->wastypebuilder = TRUE;
10752 ensure_generic_class_runtime_vtable (MonoClass *klass)
10754 MonoClass *gklass = klass->generic_class->container_class;
10756 ensure_runtime_vtable (gklass);
10758 fix_partial_generic_class (klass);
10762 ensure_runtime_vtable (MonoClass *klass)
10764 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10767 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10770 ensure_runtime_vtable (klass->parent);
10773 num = tb->ctors? mono_array_length (tb->ctors): 0;
10774 num += tb->num_methods;
10775 klass->method.count = num;
10776 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10777 num = tb->ctors? mono_array_length (tb->ctors): 0;
10778 for (i = 0; i < num; ++i)
10779 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10780 num = tb->num_methods;
10782 for (i = 0; i < num; ++i)
10783 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10785 if (tb->interfaces) {
10786 klass->interface_count = mono_array_length (tb->interfaces);
10787 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10788 for (i = 0; i < klass->interface_count; ++i) {
10789 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10790 klass->interfaces [i] = mono_class_from_mono_type (iface);
10791 ensure_runtime_vtable (klass->interfaces [i]);
10793 klass->interfaces_inited = 1;
10795 } else if (klass->generic_class){
10796 ensure_generic_class_runtime_vtable (klass);
10799 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10801 for (i = 0; i < klass->method.count; ++i) {
10802 MonoMethod *im = klass->methods [i];
10803 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10804 im->slot = slot_num++;
10807 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10808 mono_class_setup_interface_offsets (klass);
10809 mono_class_setup_interface_id (klass);
10813 * The generic vtable is needed even if image->run is not set since some
10814 * runtime code like ves_icall_Type_GetMethodsByName depends on
10815 * method->slot being defined.
10819 * tb->methods could not be freed since it is used for determining
10820 * overrides during dynamic vtable construction.
10825 mono_reflection_method_get_handle (MonoObject *method)
10827 MonoClass *class = mono_object_class (method);
10828 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10829 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10830 return sr_method->method;
10832 if (is_sre_method_builder (class)) {
10833 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10834 return mb->mhandle;
10836 if (is_sre_method_on_tb_inst (class)) {
10837 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10838 MonoMethod *result;
10839 /*FIXME move this to a proper method and unify with resolve_object*/
10840 if (m->method_args) {
10841 result = mono_reflection_method_on_tb_inst_get_handle (m);
10843 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10844 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10845 MonoMethod *mono_method;
10847 if (is_sre_method_builder (mono_object_class (m->mb)))
10848 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10849 else if (is_sr_mono_method (mono_object_class (m->mb)))
10850 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10852 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)));
10854 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10859 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10864 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10866 MonoReflectionTypeBuilder *tb;
10870 *num_overrides = 0;
10872 g_assert (klass->image->dynamic);
10874 if (!mono_class_get_ref_info (klass))
10877 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10879 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10883 for (i = 0; i < tb->num_methods; ++i) {
10884 MonoReflectionMethodBuilder *mb =
10885 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10886 if (mb->override_method)
10892 *overrides = g_new0 (MonoMethod*, onum * 2);
10895 for (i = 0; i < tb->num_methods; ++i) {
10896 MonoReflectionMethodBuilder *mb =
10897 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10898 if (mb->override_method) {
10899 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10900 (*overrides) [onum * 2 + 1] = mb->mhandle;
10902 g_assert (mb->mhandle);
10909 *num_overrides = onum;
10913 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10915 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10916 MonoReflectionFieldBuilder *fb;
10917 MonoClassField *field;
10918 MonoImage *image = klass->image;
10919 const char *p, *p2;
10921 guint32 len, idx, real_size = 0;
10923 klass->field.count = tb->num_fields;
10924 klass->field.first = 0;
10926 mono_error_init (error);
10928 if (tb->class_size) {
10929 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10930 klass->packing_size = tb->packing_size;
10931 real_size = klass->instance_size + tb->class_size;
10934 if (!klass->field.count) {
10935 klass->instance_size = MAX (klass->instance_size, real_size);
10939 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10940 mono_class_alloc_ext (klass);
10941 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10943 This is, guess what, a hack.
10944 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10945 On the static path no field class is resolved, only types are built. This is the right thing to do
10947 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10949 klass->size_inited = 1;
10951 for (i = 0; i < klass->field.count; ++i) {
10952 fb = mono_array_get (tb->fields, gpointer, i);
10953 field = &klass->fields [i];
10954 field->name = mono_string_to_utf8_image (image, fb->name, error);
10955 if (!mono_error_ok (error))
10958 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10959 field->type->attrs = fb->attrs;
10961 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10963 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10964 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10965 if (fb->offset != -1)
10966 field->offset = fb->offset;
10967 field->parent = klass;
10968 fb->handle = field;
10969 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10971 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10972 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10974 if (fb->def_value) {
10975 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10976 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10977 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10978 /* Copy the data from the blob since it might get realloc-ed */
10979 p = assembly->blob.data + idx;
10980 len = mono_metadata_decode_blob_size (p, &p2);
10982 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10983 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10987 klass->instance_size = MAX (klass->instance_size, real_size);
10988 mono_class_layout_fields (klass);
10992 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10994 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10995 MonoReflectionPropertyBuilder *pb;
10996 MonoImage *image = klass->image;
10997 MonoProperty *properties;
11000 mono_error_init (error);
11003 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11005 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11006 klass->ext->property.first = 0;
11008 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11009 klass->ext->properties = properties;
11010 for (i = 0; i < klass->ext->property.count; ++i) {
11011 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11012 properties [i].parent = klass;
11013 properties [i].attrs = pb->attrs;
11014 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11015 if (!mono_error_ok (error))
11017 if (pb->get_method)
11018 properties [i].get = pb->get_method->mhandle;
11019 if (pb->set_method)
11020 properties [i].set = pb->set_method->mhandle;
11022 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11023 if (pb->def_value) {
11025 const char *p, *p2;
11026 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11027 if (!klass->ext->prop_def_values)
11028 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11029 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11030 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11031 /* Copy the data from the blob since it might get realloc-ed */
11032 p = assembly->blob.data + idx;
11033 len = mono_metadata_decode_blob_size (p, &p2);
11035 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11036 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11041 MonoReflectionEvent *
11042 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11044 MonoEvent *event = g_new0 (MonoEvent, 1);
11047 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11049 event->parent = klass;
11050 event->attrs = eb->attrs;
11051 event->name = mono_string_to_utf8 (eb->name);
11052 if (eb->add_method)
11053 event->add = eb->add_method->mhandle;
11054 if (eb->remove_method)
11055 event->remove = eb->remove_method->mhandle;
11056 if (eb->raise_method)
11057 event->raise = eb->raise_method->mhandle;
11059 #ifndef MONO_SMALL_CONFIG
11060 if (eb->other_methods) {
11062 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11063 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11064 MonoReflectionMethodBuilder *mb =
11065 mono_array_get (eb->other_methods,
11066 MonoReflectionMethodBuilder*, j);
11067 event->other [j] = mb->mhandle;
11072 return mono_event_get_object (mono_object_domain (tb), klass, event);
11076 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11078 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11079 MonoReflectionEventBuilder *eb;
11080 MonoImage *image = klass->image;
11084 mono_error_init (error);
11087 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11089 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11090 klass->ext->event.first = 0;
11092 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11093 klass->ext->events = events;
11094 for (i = 0; i < klass->ext->event.count; ++i) {
11095 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11096 events [i].parent = klass;
11097 events [i].attrs = eb->attrs;
11098 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11099 if (!mono_error_ok (error))
11101 if (eb->add_method)
11102 events [i].add = eb->add_method->mhandle;
11103 if (eb->remove_method)
11104 events [i].remove = eb->remove_method->mhandle;
11105 if (eb->raise_method)
11106 events [i].raise = eb->raise_method->mhandle;
11108 #ifndef MONO_SMALL_CONFIG
11109 if (eb->other_methods) {
11111 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11112 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11113 MonoReflectionMethodBuilder *mb =
11114 mono_array_get (eb->other_methods,
11115 MonoReflectionMethodBuilder*, j);
11116 events [i].other [j] = mb->mhandle;
11120 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11125 remove_instantiations_of_and_ensure_contents (gpointer key,
11127 gpointer user_data)
11129 MonoType *type = (MonoType*)key;
11130 MonoClass *klass = (MonoClass*)user_data;
11132 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11133 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11140 check_array_for_usertypes (MonoArray *arr)
11147 for (i = 0; i < mono_array_length (arr); ++i)
11148 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11151 MonoReflectionType*
11152 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11156 MonoDomain* domain;
11157 MonoReflectionType* res;
11160 MONO_ARCH_SAVE_REGS;
11162 domain = mono_object_domain (tb);
11163 klass = mono_class_from_mono_type (tb->type.type);
11166 * Check for user defined Type subclasses.
11168 RESOLVE_TYPE (tb->parent);
11169 check_array_for_usertypes (tb->interfaces);
11171 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11172 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11174 RESOLVE_TYPE (fb->type);
11175 check_array_for_usertypes (fb->modreq);
11176 check_array_for_usertypes (fb->modopt);
11177 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11178 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11183 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11184 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11186 RESOLVE_TYPE (mb->rtype);
11187 check_array_for_usertypes (mb->return_modreq);
11188 check_array_for_usertypes (mb->return_modopt);
11189 check_array_for_usertypes (mb->parameters);
11190 if (mb->param_modreq)
11191 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11192 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11193 if (mb->param_modopt)
11194 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11195 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11200 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11201 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11203 check_array_for_usertypes (mb->parameters);
11204 if (mb->param_modreq)
11205 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11206 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11207 if (mb->param_modopt)
11208 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11209 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11214 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11217 * we need to lock the domain because the lock will be taken inside
11218 * So, we need to keep the locking order correct.
11220 mono_loader_lock ();
11221 mono_domain_lock (domain);
11222 if (klass->wastypebuilder) {
11223 mono_domain_unlock (domain);
11224 mono_loader_unlock ();
11225 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11228 * Fields to set in klass:
11229 * the various flags: delegate/unicode/contextbound etc.
11231 klass->flags = tb->attrs;
11232 klass->has_cctor = 1;
11233 klass->has_finalize = 1;
11234 klass->has_finalize_inited = 1;
11236 /* fool mono_class_setup_parent */
11237 klass->supertypes = NULL;
11238 mono_class_setup_parent (klass, klass->parent);
11239 mono_class_setup_mono_type (klass);
11242 if (!((MonoDynamicImage*)klass->image)->run) {
11243 if (klass->generic_container) {
11244 /* FIXME: The code below can't handle generic classes */
11245 klass->wastypebuilder = TRUE;
11246 mono_loader_unlock ();
11247 mono_domain_unlock (domain);
11248 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11253 /* enums are done right away */
11254 if (!klass->enumtype)
11255 ensure_runtime_vtable (klass);
11257 if (tb->subtypes) {
11258 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11259 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11260 mono_class_alloc_ext (klass);
11261 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)));
11265 klass->nested_classes_inited = TRUE;
11267 /* fields and object layout */
11268 if (klass->parent) {
11269 if (!klass->parent->size_inited)
11270 mono_class_init (klass->parent);
11271 klass->instance_size = klass->parent->instance_size;
11272 klass->sizes.class_size = 0;
11273 klass->min_align = klass->parent->min_align;
11274 /* if the type has no fields we won't call the field_setup
11275 * routine which sets up klass->has_references.
11277 klass->has_references |= klass->parent->has_references;
11279 klass->instance_size = sizeof (MonoObject);
11280 klass->min_align = 1;
11283 /* FIXME: handle packing_size and instance_size */
11284 typebuilder_setup_fields (klass, &error);
11285 if (!mono_error_ok (&error))
11287 typebuilder_setup_properties (klass, &error);
11288 if (!mono_error_ok (&error))
11291 typebuilder_setup_events (klass, &error);
11292 if (!mono_error_ok (&error))
11295 klass->wastypebuilder = TRUE;
11298 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11299 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11300 * we want to return normal System.MonoType objects, so clear these out from the cache.
11302 * Together with this we must ensure the contents of all instances to match the created type.
11304 if (domain->type_hash && klass->generic_container)
11305 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11307 mono_domain_unlock (domain);
11308 mono_loader_unlock ();
11310 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11311 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11312 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11315 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11316 g_assert (res != (MonoReflectionType*)tb);
11321 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11322 klass->wastypebuilder = TRUE;
11323 mono_domain_unlock (domain);
11324 mono_loader_unlock ();
11325 mono_error_raise_exception (&error);
11330 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11332 MonoGenericParamFull *param;
11337 MONO_ARCH_SAVE_REGS;
11339 image = &gparam->tbuilder->module->dynamic_image->image;
11341 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11343 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11344 g_assert (mono_error_ok (&error));
11345 param->param.num = gparam->index;
11347 if (gparam->mbuilder) {
11348 if (!gparam->mbuilder->generic_container) {
11349 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11350 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11351 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11352 gparam->mbuilder->generic_container->is_method = TRUE;
11354 * Cannot set owner.method, since the MonoMethod is not created yet.
11355 * Set the image field instead, so type_in_image () works.
11357 gparam->mbuilder->generic_container->image = klass->image;
11359 param->param.owner = gparam->mbuilder->generic_container;
11360 } else if (gparam->tbuilder) {
11361 if (!gparam->tbuilder->generic_container) {
11362 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11363 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11364 gparam->tbuilder->generic_container->owner.klass = klass;
11366 param->param.owner = gparam->tbuilder->generic_container;
11369 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11371 gparam->type.type = &pklass->byval_arg;
11373 mono_class_set_ref_info (pklass, gparam);
11374 mono_image_lock (image);
11375 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11376 mono_image_unlock (image);
11380 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11382 MonoReflectionModuleBuilder *module = sig->module;
11383 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11384 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11389 check_array_for_usertypes (sig->arguments);
11391 sigbuffer_init (&buf, 32);
11393 sigbuffer_add_value (&buf, 0x07);
11394 sigbuffer_add_value (&buf, na);
11395 if (assembly != NULL){
11396 for (i = 0; i < na; ++i) {
11397 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11398 encode_reflection_type (assembly, type, &buf);
11402 buflen = buf.p - buf.buf;
11403 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11404 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11405 sigbuffer_free (&buf);
11411 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11413 MonoDynamicImage *assembly = sig->module->dynamic_image;
11414 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11419 check_array_for_usertypes (sig->arguments);
11421 sigbuffer_init (&buf, 32);
11423 sigbuffer_add_value (&buf, 0x06);
11424 for (i = 0; i < na; ++i) {
11425 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11426 encode_reflection_type (assembly, type, &buf);
11429 buflen = buf.p - buf.buf;
11430 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11431 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11432 sigbuffer_free (&buf);
11438 MonoMethod *handle;
11439 MonoDomain *domain;
11440 } DynamicMethodReleaseData;
11443 * The runtime automatically clean up those after finalization.
11445 static MonoReferenceQueue *dynamic_method_queue;
11448 free_dynamic_method (void *dynamic_method)
11450 DynamicMethodReleaseData *data = dynamic_method;
11452 mono_runtime_free_method (data->domain, data->handle);
11457 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11459 MonoReferenceQueue *queue;
11460 MonoMethod *handle;
11461 DynamicMethodReleaseData *release_data;
11462 ReflectionMethodBuilder rmb;
11463 MonoMethodSignature *sig;
11468 if (mono_runtime_is_shutting_down ())
11469 mono_raise_exception (mono_get_exception_invalid_operation (""));
11471 if (!(queue = dynamic_method_queue)) {
11472 mono_loader_lock ();
11473 if (!(queue = dynamic_method_queue))
11474 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11475 mono_loader_unlock ();
11478 sig = dynamic_method_to_signature (mb);
11480 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11483 * Resolve references.
11486 * Every second entry in the refs array is reserved for storing handle_class,
11487 * which is needed by the ldtoken implementation in the JIT.
11489 rmb.nrefs = mb->nrefs;
11490 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11491 for (i = 0; i < mb->nrefs; i += 2) {
11492 MonoClass *handle_class;
11494 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11496 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11497 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11499 * The referenced DynamicMethod should already be created by the managed
11500 * code, except in the case of circular references. In that case, we store
11501 * method in the refs array, and fix it up later when the referenced
11502 * DynamicMethod is created.
11504 if (method->mhandle) {
11505 ref = method->mhandle;
11507 /* FIXME: GC object stored in unmanaged memory */
11510 /* FIXME: GC object stored in unmanaged memory */
11511 method->referenced_by = g_slist_append (method->referenced_by, mb);
11513 handle_class = mono_defaults.methodhandle_class;
11515 MonoException *ex = NULL;
11516 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11518 ex = mono_get_exception_type_load (NULL, NULL);
11519 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11520 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11524 mono_raise_exception (ex);
11529 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11530 rmb.refs [i + 1] = handle_class;
11533 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11535 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11536 release_data = g_new (DynamicMethodReleaseData, 1);
11537 release_data->handle = handle;
11538 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11539 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11540 g_free (release_data);
11542 /* Fix up refs entries pointing at us */
11543 for (l = mb->referenced_by; l; l = l->next) {
11544 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11545 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11548 g_assert (method->mhandle);
11550 data = (gpointer*)wrapper->method_data;
11551 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11552 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11553 data [i + 1] = mb->mhandle;
11556 g_slist_free (mb->referenced_by);
11560 /* ilgen is no longer needed */
11564 #endif /* DISABLE_REFLECTION_EMIT */
11568 * mono_reflection_is_valid_dynamic_token:
11570 * Returns TRUE if token is valid.
11574 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11576 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11579 MonoMethodSignature *
11580 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11582 MonoMethodSignature *sig;
11583 g_assert (image->dynamic);
11585 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11589 return mono_method_signature (method);
11592 #ifndef DISABLE_REFLECTION_EMIT
11595 * mono_reflection_lookup_dynamic_token:
11597 * Finish the Builder object pointed to by TOKEN and return the corresponding
11598 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11599 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11602 * LOCKING: Take the loader lock
11605 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11607 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11611 mono_loader_lock ();
11612 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11613 mono_loader_unlock ();
11616 g_error ("Could not find required dynamic token 0x%08x", token);
11622 handle_class = &klass;
11623 return resolve_object (image, obj, handle_class, context);
11627 * ensure_complete_type:
11629 * Ensure that KLASS is completed if it is a dynamic type, or references
11633 ensure_complete_type (MonoClass *klass)
11635 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11636 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11638 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11640 // Asserting here could break a lot of code
11641 //g_assert (klass->wastypebuilder);
11644 if (klass->generic_class) {
11645 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11648 for (i = 0; i < inst->type_argc; ++i) {
11649 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11655 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11657 gpointer result = NULL;
11659 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11660 result = mono_string_intern ((MonoString*)obj);
11661 *handle_class = mono_defaults.string_class;
11663 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11664 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11665 MonoClass *mc = mono_class_from_mono_type (type);
11666 if (!mono_class_init (mc))
11667 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11670 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11671 result = mono_class_from_mono_type (inflated);
11672 mono_metadata_free_type (inflated);
11674 result = mono_class_from_mono_type (type);
11676 *handle_class = mono_defaults.typehandle_class;
11678 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11679 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11680 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11681 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11682 result = ((MonoReflectionMethod*)obj)->method;
11684 result = mono_class_inflate_generic_method (result, context);
11685 *handle_class = mono_defaults.methodhandle_class;
11687 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11688 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11689 result = mb->mhandle;
11691 /* Type is not yet created */
11692 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11694 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11697 * Hopefully this has been filled in by calling CreateType() on the
11701 * TODO: This won't work if the application finishes another
11702 * TypeBuilder instance instead of this one.
11704 result = mb->mhandle;
11707 result = mono_class_inflate_generic_method (result, context);
11708 *handle_class = mono_defaults.methodhandle_class;
11709 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11710 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11712 result = cb->mhandle;
11714 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11716 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11717 result = cb->mhandle;
11720 result = mono_class_inflate_generic_method (result, context);
11721 *handle_class = mono_defaults.methodhandle_class;
11722 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11723 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11725 ensure_complete_type (field->parent);
11727 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11728 MonoClass *class = mono_class_from_mono_type (inflated);
11729 MonoClassField *inflated_field;
11730 gpointer iter = NULL;
11731 mono_metadata_free_type (inflated);
11732 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11733 if (!strcmp (field->name, inflated_field->name))
11736 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11737 result = inflated_field;
11741 *handle_class = mono_defaults.fieldhandle_class;
11743 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11744 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11745 result = fb->handle;
11748 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11750 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11751 result = fb->handle;
11754 if (fb->handle && fb->handle->parent->generic_container) {
11755 MonoClass *klass = fb->handle->parent;
11756 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11757 MonoClass *inflated = mono_class_from_mono_type (type);
11759 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11761 mono_metadata_free_type (type);
11763 *handle_class = mono_defaults.fieldhandle_class;
11764 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11765 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11766 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11769 klass = type->data.klass;
11770 if (klass->wastypebuilder) {
11771 /* Already created */
11775 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11776 result = type->data.klass;
11779 *handle_class = mono_defaults.typehandle_class;
11780 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11781 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11782 MonoMethodSignature *sig;
11785 if (helper->arguments)
11786 nargs = mono_array_length (helper->arguments);
11790 sig = mono_metadata_signature_alloc (image, nargs);
11791 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11792 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11794 if (helper->unmanaged_call_conv) { /* unmanaged */
11795 sig->call_convention = helper->unmanaged_call_conv - 1;
11796 sig->pinvoke = TRUE;
11797 } else if (helper->call_conv & 0x02) {
11798 sig->call_convention = MONO_CALL_VARARG;
11800 sig->call_convention = MONO_CALL_DEFAULT;
11803 sig->param_count = nargs;
11804 /* TODO: Copy type ? */
11805 sig->ret = helper->return_type->type;
11806 for (i = 0; i < nargs; ++i)
11807 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11810 *handle_class = NULL;
11811 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11812 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11813 /* Already created by the managed code */
11814 g_assert (method->mhandle);
11815 result = method->mhandle;
11816 *handle_class = mono_defaults.methodhandle_class;
11817 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11818 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11819 type = mono_class_inflate_generic_type (type, context);
11820 result = mono_class_from_mono_type (type);
11821 *handle_class = mono_defaults.typehandle_class;
11823 mono_metadata_free_type (type);
11824 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11825 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11826 type = mono_class_inflate_generic_type (type, context);
11827 result = mono_class_from_mono_type (type);
11828 *handle_class = mono_defaults.typehandle_class;
11830 mono_metadata_free_type (type);
11831 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11832 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11833 MonoClass *inflated;
11835 MonoClassField *field;
11837 if (is_sre_field_builder (mono_object_class (f->fb)))
11838 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11839 else if (is_sr_mono_field (mono_object_class (f->fb)))
11840 field = ((MonoReflectionField*)f->fb)->field;
11842 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)));
11844 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11845 inflated = mono_class_from_mono_type (type);
11847 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11848 ensure_complete_type (field->parent);
11850 mono_metadata_free_type (type);
11851 *handle_class = mono_defaults.fieldhandle_class;
11852 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11853 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11854 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11855 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11856 MonoMethod *method;
11858 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11859 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11860 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11861 method = ((MonoReflectionMethod *)c->cb)->method;
11863 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)));
11865 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11866 *handle_class = mono_defaults.methodhandle_class;
11867 mono_metadata_free_type (type);
11868 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11869 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11870 if (m->method_args) {
11871 result = mono_reflection_method_on_tb_inst_get_handle (m);
11873 result = mono_class_inflate_generic_method (result, context);
11875 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11876 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11877 MonoMethod *method;
11879 if (is_sre_method_builder (mono_object_class (m->mb)))
11880 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11881 else if (is_sr_mono_method (mono_object_class (m->mb)))
11882 method = ((MonoReflectionMethod *)m->mb)->method;
11884 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)));
11886 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11887 mono_metadata_free_type (type);
11889 *handle_class = mono_defaults.methodhandle_class;
11890 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11891 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11894 MonoMethod *method;
11898 mtype = mono_reflection_type_get_handle (m->parent);
11899 klass = mono_class_from_mono_type (mtype);
11901 /* Find the method */
11903 name = mono_string_to_utf8 (m->name);
11905 while ((method = mono_class_get_methods (klass, &iter))) {
11906 if (!strcmp (method->name, name))
11913 // FIXME: Check parameters/return value etc. match
11916 *handle_class = mono_defaults.methodhandle_class;
11917 } else if (is_sre_array (mono_object_get_class(obj)) ||
11918 is_sre_byref (mono_object_get_class(obj)) ||
11919 is_sre_pointer (mono_object_get_class(obj))) {
11920 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11921 MonoType *type = mono_reflection_type_get_handle (ref_type);
11922 result = mono_class_from_mono_type (type);
11923 *handle_class = mono_defaults.typehandle_class;
11925 g_print ("%s\n", obj->vtable->klass->name);
11926 g_assert_not_reached ();
11931 #else /* DISABLE_REFLECTION_EMIT */
11934 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11936 g_assert_not_reached ();
11941 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11943 g_assert_not_reached ();
11947 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11949 g_assert_not_reached ();
11953 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11955 g_assert_not_reached ();
11959 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11961 g_assert_not_reached ();
11965 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11967 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11971 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11973 g_assert_not_reached ();
11977 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11979 g_assert_not_reached ();
11982 MonoReflectionModule *
11983 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11985 g_assert_not_reached ();
11990 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11992 g_assert_not_reached ();
11997 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11999 g_assert_not_reached ();
12004 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12005 gboolean create_open_instance, gboolean register_token)
12007 g_assert_not_reached ();
12012 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12017 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
12018 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12021 g_assert_not_reached ();
12025 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12028 *num_overrides = 0;
12031 MonoReflectionEvent *
12032 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12034 g_assert_not_reached ();
12038 MonoReflectionType*
12039 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12041 g_assert_not_reached ();
12046 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12048 g_assert_not_reached ();
12052 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12054 g_assert_not_reached ();
12059 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12061 g_assert_not_reached ();
12066 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12071 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12077 mono_reflection_type_get_handle (MonoReflectionType* ref)
12085 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12087 g_assert_not_reached ();
12090 #endif /* DISABLE_REFLECTION_EMIT */
12092 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12093 const static guint32 declsec_flags_map[] = {
12094 0x00000000, /* empty */
12095 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12096 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12097 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12098 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12099 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12100 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12101 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12102 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12103 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12104 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12105 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12106 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12107 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12108 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12109 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12110 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12111 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12112 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12116 * Returns flags that includes all available security action associated to the handle.
12117 * @token: metadata token (either for a class or a method)
12118 * @image: image where resides the metadata.
12121 mono_declsec_get_flags (MonoImage *image, guint32 token)
12123 int index = mono_metadata_declsec_from_index (image, token);
12124 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12125 guint32 result = 0;
12129 /* HasSecurity can be present for other, not specially encoded, attributes,
12130 e.g. SuppressUnmanagedCodeSecurityAttribute */
12134 for (i = index; i < t->rows; i++) {
12135 guint32 cols [MONO_DECL_SECURITY_SIZE];
12137 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12138 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12141 action = cols [MONO_DECL_SECURITY_ACTION];
12142 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12143 result |= declsec_flags_map [action];
12145 g_assert_not_reached ();
12152 * Get the security actions (in the form of flags) associated with the specified method.
12154 * @method: The method for which we want the declarative security flags.
12155 * Return the declarative security flags for the method (only).
12157 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12158 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12161 mono_declsec_flags_from_method (MonoMethod *method)
12163 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12164 /* FIXME: No cache (for the moment) */
12165 guint32 idx = mono_method_get_index (method);
12166 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12167 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12168 return mono_declsec_get_flags (method->klass->image, idx);
12174 * Get the security actions (in the form of flags) associated with the specified class.
12176 * @klass: The class for which we want the declarative security flags.
12177 * Return the declarative security flags for the class.
12179 * Note: We cache the flags inside the MonoClass structure as this will get
12180 * called very often (at least for each method).
12183 mono_declsec_flags_from_class (MonoClass *klass)
12185 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12186 if (!klass->ext || !klass->ext->declsec_flags) {
12189 idx = mono_metadata_token_index (klass->type_token);
12190 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12191 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12192 mono_loader_lock ();
12193 mono_class_alloc_ext (klass);
12194 mono_loader_unlock ();
12195 /* we cache the flags on classes */
12196 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12198 return klass->ext->declsec_flags;
12204 * Get the security actions (in the form of flags) associated with the specified assembly.
12206 * @assembly: The assembly for which we want the declarative security flags.
12207 * Return the declarative security flags for the assembly.
12210 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12212 guint32 idx = 1; /* there is only one assembly */
12213 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12214 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12215 return mono_declsec_get_flags (assembly->image, idx);
12220 * Fill actions for the specific index (which may either be an encoded class token or
12221 * an encoded method token) from the metadata image.
12222 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12225 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12226 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12228 MonoBoolean result = FALSE;
12230 guint32 cols [MONO_DECL_SECURITY_SIZE];
12231 int index = mono_metadata_declsec_from_index (image, token);
12234 t = &image->tables [MONO_TABLE_DECLSECURITY];
12235 for (i = index; i < t->rows; i++) {
12236 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12238 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12241 /* if present only replace (class) permissions with method permissions */
12242 /* if empty accept either class or method permissions */
12243 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12244 if (!actions->demand.blob) {
12245 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12246 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12247 actions->demand.blob = (char*) (blob + 2);
12248 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12251 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12252 if (!actions->noncasdemand.blob) {
12253 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12254 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12255 actions->noncasdemand.blob = (char*) (blob + 2);
12256 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12259 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12260 if (!actions->demandchoice.blob) {
12261 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12262 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12263 actions->demandchoice.blob = (char*) (blob + 2);
12264 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12274 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12275 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12277 guint32 idx = mono_metadata_token_index (klass->type_token);
12278 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12279 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12280 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12284 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12285 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12287 guint32 idx = mono_method_get_index (method);
12288 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12289 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12290 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12294 * Collect all actions (that requires to generate code in mini) assigned for
12295 * the specified method.
12296 * Note: Don't use the content of actions if the function return FALSE.
12299 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12301 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12302 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12303 MonoBoolean result = FALSE;
12306 /* quick exit if no declarative security is present in the metadata */
12307 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12310 /* we want the original as the wrapper is "free" of the security informations */
12311 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12312 method = mono_marshal_method_from_wrapper (method);
12317 /* First we look for method-level attributes */
12318 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12319 mono_class_init (method->klass);
12320 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12322 result = mono_declsec_get_method_demands_params (method, demands,
12323 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12326 /* Here we use (or create) the class declarative cache to look for demands */
12327 flags = mono_declsec_flags_from_class (method->klass);
12328 if (flags & mask) {
12330 mono_class_init (method->klass);
12331 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12333 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12334 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12337 /* The boolean return value is used as a shortcut in case nothing needs to
12338 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12344 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12346 * Note: Don't use the content of actions if the function return FALSE.
12349 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12351 MonoBoolean result = FALSE;
12354 /* quick exit if no declarative security is present in the metadata */
12355 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12358 /* we want the original as the wrapper is "free" of the security informations */
12359 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12360 method = mono_marshal_method_from_wrapper (method);
12365 /* results are independant - zeroize both */
12366 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12367 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12369 /* First we look for method-level attributes */
12370 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12371 mono_class_init (method->klass);
12373 result = mono_declsec_get_method_demands_params (method, cmethod,
12374 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12377 /* Here we use (or create) the class declarative cache to look for demands */
12378 flags = mono_declsec_flags_from_class (method->klass);
12379 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12380 mono_class_init (method->klass);
12382 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12383 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12390 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12392 * @klass The inherited class - this is the class that provides the security check (attributes)
12394 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12396 * Note: Don't use the content of actions if the function return FALSE.
12399 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12401 MonoBoolean result = FALSE;
12404 /* quick exit if no declarative security is present in the metadata */
12405 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12408 /* Here we use (or create) the class declarative cache to look for demands */
12409 flags = mono_declsec_flags_from_class (klass);
12410 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12411 mono_class_init (klass);
12412 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12414 result |= mono_declsec_get_class_demands_params (klass, demands,
12415 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12422 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12424 * Note: Don't use the content of actions if the function return FALSE.
12427 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12429 /* quick exit if no declarative security is present in the metadata */
12430 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12433 /* we want the original as the wrapper is "free" of the security informations */
12434 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12435 method = mono_marshal_method_from_wrapper (method);
12440 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12441 mono_class_init (method->klass);
12442 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12444 return mono_declsec_get_method_demands_params (method, demands,
12445 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12452 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12454 guint32 cols [MONO_DECL_SECURITY_SIZE];
12458 int index = mono_metadata_declsec_from_index (image, token);
12462 t = &image->tables [MONO_TABLE_DECLSECURITY];
12463 for (i = index; i < t->rows; i++) {
12464 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12466 /* shortcut - index are ordered */
12467 if (token != cols [MONO_DECL_SECURITY_PARENT])
12470 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12471 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12472 entry->blob = (char*) (metadata + 2);
12473 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12482 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12484 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12485 guint32 idx = mono_method_get_index (method);
12486 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12487 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12488 return get_declsec_action (method->klass->image, idx, action, entry);
12494 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12497 guint32 flags = mono_declsec_flags_from_class (klass);
12498 if (declsec_flags_map [action] & flags) {
12499 guint32 idx = mono_metadata_token_index (klass->type_token);
12500 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12501 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12502 return get_declsec_action (klass->image, idx, action, entry);
12508 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12510 guint32 idx = 1; /* there is only one assembly */
12511 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12512 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12514 return get_declsec_action (assembly->image, idx, action, entry);
12518 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12520 MonoObject *res, *exc;
12522 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12523 static MonoMethod *method = NULL;
12525 if (!System_Reflection_Emit_TypeBuilder) {
12526 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12527 g_assert (System_Reflection_Emit_TypeBuilder);
12529 if (method == NULL) {
12530 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12535 * The result of mono_type_get_object () might be a System.MonoType but we
12536 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12538 g_assert (mono_class_get_ref_info (klass));
12539 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12541 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12543 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12547 return *(MonoBoolean*)mono_object_unbox (res);