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);
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")) {
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}};
7868 /* See Partition II, Appendix B3 */
7869 etype = MONO_TYPE_OBJECT;
7870 type = MONO_TYPE_SZARRAY;
7871 simple_type.type = etype;
7872 tklass = mono_class_from_mono_type (&simple_type);
7874 } else if (subt == 0x55) {
7877 slen = mono_metadata_decode_value (p, &p);
7878 n = g_memdup (p, slen + 1);
7880 t = mono_reflection_type_from_name (n, image);
7882 g_error ("Cannot load type '%s'", n);
7885 subc = mono_class_from_mono_type (t);
7886 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7887 MonoType simple_type = {{0}};
7888 simple_type.type = subt;
7889 subc = mono_class_from_mono_type (&simple_type);
7891 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7893 val = load_cattr_value (image, &subc->byval_arg, p, end);
7894 obj = mono_object_new (mono_domain_get (), subc);
7895 g_assert (!subc->has_references);
7896 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7900 case MONO_TYPE_SZARRAY: {
7902 guint32 i, alen, basetype;
7905 if (alen == 0xffffffff) {
7909 arr = mono_array_new (mono_domain_get(), tklass, alen);
7910 basetype = tklass->byval_arg.type;
7911 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7912 basetype = mono_class_enum_basetype (tklass)->type;
7917 case MONO_TYPE_BOOLEAN:
7918 for (i = 0; i < alen; i++) {
7919 MonoBoolean val = *p++;
7920 mono_array_set (arr, MonoBoolean, i, val);
7923 case MONO_TYPE_CHAR:
7926 for (i = 0; i < alen; i++) {
7927 guint16 val = read16 (p);
7928 mono_array_set (arr, guint16, i, val);
7935 for (i = 0; i < alen; i++) {
7936 guint32 val = read32 (p);
7937 mono_array_set (arr, guint32, i, val);
7942 for (i = 0; i < alen; i++) {
7945 mono_array_set (arr, double, i, val);
7951 for (i = 0; i < alen; i++) {
7952 guint64 val = read64 (p);
7953 mono_array_set (arr, guint64, i, val);
7957 case MONO_TYPE_CLASS:
7958 case MONO_TYPE_OBJECT:
7959 case MONO_TYPE_STRING:
7960 for (i = 0; i < alen; i++) {
7961 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7962 mono_array_setref (arr, i, item);
7966 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
7972 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
7978 create_cattr_typed_arg (MonoType *t, MonoObject *val)
7980 static MonoClass *klass;
7981 static MonoMethod *ctor;
7983 void *params [2], *unboxed;
7986 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
7988 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
7990 params [0] = mono_type_get_object (mono_domain_get (), t);
7992 retval = mono_object_new (mono_domain_get (), klass);
7993 unboxed = mono_object_unbox (retval);
7994 mono_runtime_invoke (ctor, unboxed, params, NULL);
8000 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8002 static MonoClass *klass;
8003 static MonoMethod *ctor;
8005 void *unboxed, *params [2];
8008 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8010 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8013 params [1] = typedarg;
8014 retval = mono_object_new (mono_domain_get (), klass);
8015 unboxed = mono_object_unbox (retval);
8016 mono_runtime_invoke (ctor, unboxed, params, NULL);
8022 type_is_reference (MonoType *type)
8024 switch (type->type) {
8025 case MONO_TYPE_BOOLEAN:
8026 case MONO_TYPE_CHAR:
8039 case MONO_TYPE_VALUETYPE:
8047 free_param_data (MonoMethodSignature *sig, void **params) {
8049 for (i = 0; i < sig->param_count; ++i) {
8050 if (!type_is_reference (sig->params [i]))
8051 g_free (params [i]);
8056 * Find the field index in the metadata FieldDef table.
8059 find_field_index (MonoClass *klass, MonoClassField *field) {
8062 for (i = 0; i < klass->field.count; ++i) {
8063 if (field == &klass->fields [i])
8064 return klass->field.first + 1 + i;
8070 * Find the property index in the metadata Property table.
8073 find_property_index (MonoClass *klass, MonoProperty *property) {
8076 for (i = 0; i < klass->ext->property.count; ++i) {
8077 if (property == &klass->ext->properties [i])
8078 return klass->ext->property.first + 1 + i;
8084 * Find the event index in the metadata Event table.
8087 find_event_index (MonoClass *klass, MonoEvent *event) {
8090 for (i = 0; i < klass->ext->event.count; ++i) {
8091 if (event == &klass->ext->events [i])
8092 return klass->ext->event.first + 1 + i;
8098 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len, MonoError *error)
8100 const char *p = (const char*)data;
8102 guint32 i, j, num_named;
8104 void *params_buf [32];
8106 MonoMethodSignature *sig;
8108 mono_error_init (error);
8110 mono_class_init (method->klass);
8112 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL)) {
8113 mono_error_set_generic_error (error, "System.Reflection", "CustomAttributeFormatException", "Binary format of the specified custom attribute was invalid.");
8118 attr = mono_object_new (mono_domain_get (), method->klass);
8119 mono_runtime_invoke (method, attr, NULL, NULL);
8123 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8126 /*g_print ("got attr %s\n", method->klass->name);*/
8128 sig = mono_method_signature (method);
8129 if (sig->param_count < 32)
8130 params = params_buf;
8132 /* Allocate using GC so it gets GC tracking */
8133 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8137 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8138 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8142 attr = mono_object_new (mono_domain_get (), method->klass);
8143 mono_runtime_invoke (method, attr, params, NULL);
8144 free_param_data (method->signature, params);
8145 num_named = read16 (named);
8147 for (j = 0; j < num_named; j++) {
8149 char *name, named_type, data_type;
8150 named_type = *named++;
8151 data_type = *named++; /* type of data */
8152 if (data_type == MONO_TYPE_SZARRAY)
8153 data_type = *named++;
8154 if (data_type == MONO_TYPE_ENUM) {
8157 type_len = mono_metadata_decode_blob_size (named, &named);
8158 type_name = g_malloc (type_len + 1);
8159 memcpy (type_name, named, type_len);
8160 type_name [type_len] = 0;
8162 /* FIXME: lookup the type and check type consistency */
8165 name_len = mono_metadata_decode_blob_size (named, &named);
8166 name = g_malloc (name_len + 1);
8167 memcpy (name, named, name_len);
8168 name [name_len] = 0;
8170 if (named_type == 0x53) {
8171 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8172 void *val = load_cattr_value (image, field->type, named, &named);
8173 mono_field_set_value (attr, field, val);
8174 if (!type_is_reference (field->type))
8176 } else if (named_type == 0x54) {
8179 MonoType *prop_type;
8181 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8182 /* can we have more that 1 arg in a custom attr named property? */
8183 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8184 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8185 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8186 mono_property_set_value (prop, attr, pparams, NULL);
8187 if (!type_is_reference (prop_type))
8188 g_free (pparams [0]);
8193 if (params != params_buf)
8194 mono_gc_free_fixed (params);
8200 * mono_reflection_create_custom_attr_data_args:
8202 * Create an array of typed and named arguments from the cattr blob given by DATA.
8203 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8204 * NAMED_ARG_INFO will contain information about the named arguments.
8207 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)
8209 MonoArray *typedargs, *namedargs;
8210 MonoClass *attrklass;
8212 const char *p = (const char*)data;
8214 guint32 i, j, num_named;
8215 CattrNamedArg *arginfo = NULL;
8217 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8220 mono_class_init (method->klass);
8224 *named_arg_info = NULL;
8226 domain = mono_domain_get ();
8228 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8231 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8235 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8239 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8240 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8241 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8242 mono_array_setref (typedargs, i, obj);
8244 if (!type_is_reference (mono_method_signature (method)->params [i]))
8249 num_named = read16 (named);
8250 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8252 attrklass = method->klass;
8254 arginfo = g_new0 (CattrNamedArg, num_named);
8255 *named_arg_info = arginfo;
8257 for (j = 0; j < num_named; j++) {
8259 char *name, named_type, data_type;
8260 named_type = *named++;
8261 data_type = *named++; /* type of data */
8262 if (data_type == MONO_TYPE_SZARRAY)
8263 data_type = *named++;
8264 if (data_type == MONO_TYPE_ENUM) {
8267 type_len = mono_metadata_decode_blob_size (named, &named);
8268 type_name = g_malloc (type_len + 1);
8269 memcpy (type_name, named, type_len);
8270 type_name [type_len] = 0;
8272 /* FIXME: lookup the type and check type consistency */
8275 name_len = mono_metadata_decode_blob_size (named, &named);
8276 name = g_malloc (name_len + 1);
8277 memcpy (name, named, name_len);
8278 name [name_len] = 0;
8280 if (named_type == 0x53) {
8282 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8285 arginfo [j].type = field->type;
8286 arginfo [j].field = field;
8288 val = load_cattr_value (image, field->type, named, &named);
8289 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8290 mono_array_setref (namedargs, j, obj);
8291 if (!type_is_reference (field->type))
8293 } else if (named_type == 0x54) {
8295 MonoType *prop_type;
8296 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8299 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8300 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8302 arginfo [j].type = prop_type;
8303 arginfo [j].prop = prop;
8305 val = load_cattr_value (image, prop_type, named, &named);
8306 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8307 mono_array_setref (namedargs, j, obj);
8308 if (!type_is_reference (prop_type))
8314 *typed_args = typedargs;
8315 *named_args = namedargs;
8319 mono_reflection_resolve_custom_attribute_data (MonoReflectionMethod *ref_method, MonoReflectionAssembly *assembly, gpointer data, guint32 len, MonoArray **ctor_args, MonoArray **named_args)
8322 MonoArray *typedargs, *namedargs;
8325 CattrNamedArg *arginfo;
8334 image = assembly->assembly->image;
8335 method = ref_method->method;
8336 domain = mono_object_domain (ref_method);
8338 if (!mono_class_init (method->klass))
8339 mono_raise_exception (mono_class_get_exception_for_failure (method->klass));
8341 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8342 if (mono_loader_get_last_error ())
8343 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
8345 if (!typedargs || !namedargs)
8348 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8349 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8350 MonoObject *typedarg;
8352 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8353 mono_array_setref (typedargs, i, typedarg);
8356 for (i = 0; i < mono_array_length (namedargs); ++i) {
8357 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8358 MonoObject *typedarg, *namedarg, *minfo;
8360 if (arginfo [i].prop)
8361 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8363 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8365 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8366 namedarg = create_cattr_named_arg (minfo, typedarg);
8368 mono_array_setref (namedargs, i, namedarg);
8371 *ctor_args = typedargs;
8372 *named_args = namedargs;
8376 create_custom_attr_data (MonoImage *image, MonoCustomAttrEntry *cattr)
8378 static MonoMethod *ctor;
8383 g_assert (image->assembly);
8386 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 4);
8388 domain = mono_domain_get ();
8389 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8390 params [0] = mono_method_get_object (domain, cattr->ctor, NULL);
8391 params [1] = mono_assembly_get_object (domain, image->assembly);
8392 params [2] = (gpointer)&cattr->data;
8393 params [3] = &cattr->data_size;
8394 mono_runtime_invoke (ctor, attr, params, NULL);
8399 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass, MonoError *error)
8405 mono_error_init (error);
8408 for (i = 0; i < cinfo->num_attrs; ++i) {
8409 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8413 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8415 for (i = 0; i < cinfo->num_attrs; ++i) {
8416 if (!cinfo->attrs [i].ctor)
8417 /* The cattr type is not finished yet */
8418 /* We should include the type name but cinfo doesn't contain it */
8419 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8420 if (!attr_klass || mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8421 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size, error);
8422 if (!mono_error_ok (error))
8424 mono_array_setref (result, n, attr);
8432 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8436 return mono_custom_attrs_construct_by_type (cinfo, NULL, &error);
8440 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8446 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8447 for (i = 0; i < cinfo->num_attrs; ++i) {
8448 attr = create_custom_attr_data (cinfo->image, &cinfo->attrs [i]);
8449 mono_array_setref (result, i, attr);
8455 * mono_custom_attrs_from_index:
8457 * Returns: NULL if no attributes are found or if a loading error occurs.
8460 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8462 guint32 mtoken, i, len;
8463 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8465 MonoCustomAttrInfo *ainfo;
8466 GList *tmp, *list = NULL;
8469 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8471 i = mono_metadata_custom_attrs_from_index (image, idx);
8475 while (i < ca->rows) {
8476 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8478 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8481 len = g_list_length (list);
8484 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8485 ainfo->num_attrs = len;
8486 ainfo->image = image;
8487 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8488 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8489 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8490 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8491 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8492 mtoken |= MONO_TOKEN_METHOD_DEF;
8494 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8495 mtoken |= MONO_TOKEN_MEMBER_REF;
8498 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8501 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8502 if (!ainfo->attrs [i].ctor) {
8503 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8509 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8510 /*FIXME raising an exception here doesn't make any sense*/
8511 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8516 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8517 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8518 ainfo->attrs [i].data = (guchar*)data;
8526 mono_custom_attrs_from_method (MonoMethod *method)
8531 * An instantiated method has the same cattrs as the generic method definition.
8533 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8534 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8536 if (method->is_inflated)
8537 method = ((MonoMethodInflated *) method)->declaring;
8539 if (method->dynamic || method->klass->image->dynamic)
8540 return lookup_custom_attr (method->klass->image, method);
8543 /* Synthetic methods */
8546 idx = mono_method_get_index (method);
8547 idx <<= MONO_CUSTOM_ATTR_BITS;
8548 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8549 return mono_custom_attrs_from_index (method->klass->image, idx);
8553 mono_custom_attrs_from_class (MonoClass *klass)
8557 if (klass->generic_class)
8558 klass = klass->generic_class->container_class;
8560 if (klass->image->dynamic)
8561 return lookup_custom_attr (klass->image, klass);
8563 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8564 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8565 idx <<= MONO_CUSTOM_ATTR_BITS;
8566 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8568 idx = mono_metadata_token_index (klass->type_token);
8569 idx <<= MONO_CUSTOM_ATTR_BITS;
8570 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8572 return mono_custom_attrs_from_index (klass->image, idx);
8576 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8580 if (assembly->image->dynamic)
8581 return lookup_custom_attr (assembly->image, assembly);
8582 idx = 1; /* there is only one assembly */
8583 idx <<= MONO_CUSTOM_ATTR_BITS;
8584 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8585 return mono_custom_attrs_from_index (assembly->image, idx);
8588 static MonoCustomAttrInfo*
8589 mono_custom_attrs_from_module (MonoImage *image)
8594 return lookup_custom_attr (image, image);
8595 idx = 1; /* there is only one module */
8596 idx <<= MONO_CUSTOM_ATTR_BITS;
8597 idx |= MONO_CUSTOM_ATTR_MODULE;
8598 return mono_custom_attrs_from_index (image, idx);
8602 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8606 if (klass->image->dynamic) {
8607 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8608 return lookup_custom_attr (klass->image, property);
8610 idx = find_property_index (klass, property);
8611 idx <<= MONO_CUSTOM_ATTR_BITS;
8612 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8613 return mono_custom_attrs_from_index (klass->image, idx);
8617 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8621 if (klass->image->dynamic) {
8622 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8623 return lookup_custom_attr (klass->image, event);
8625 idx = find_event_index (klass, event);
8626 idx <<= MONO_CUSTOM_ATTR_BITS;
8627 idx |= MONO_CUSTOM_ATTR_EVENT;
8628 return mono_custom_attrs_from_index (klass->image, idx);
8632 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8635 if (klass->image->dynamic) {
8636 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8637 return lookup_custom_attr (klass->image, field);
8639 idx = find_field_index (klass, field);
8640 idx <<= MONO_CUSTOM_ATTR_BITS;
8641 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8642 return mono_custom_attrs_from_index (klass->image, idx);
8646 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8649 guint32 i, idx, method_index;
8650 guint32 param_list, param_last, param_pos, found;
8652 MonoReflectionMethodAux *aux;
8655 * An instantiated method has the same cattrs as the generic method definition.
8657 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8658 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8660 if (method->is_inflated)
8661 method = ((MonoMethodInflated *) method)->declaring;
8663 if (method->klass->image->dynamic) {
8664 MonoCustomAttrInfo *res, *ainfo;
8667 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8668 if (!aux || !aux->param_cattr)
8671 /* Need to copy since it will be freed later */
8672 ainfo = aux->param_cattr [param];
8675 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8676 res = g_malloc0 (size);
8677 memcpy (res, ainfo, size);
8681 image = method->klass->image;
8682 method_index = mono_method_get_index (method);
8685 ca = &image->tables [MONO_TABLE_METHOD];
8687 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8688 if (method_index == ca->rows) {
8689 ca = &image->tables [MONO_TABLE_PARAM];
8690 param_last = ca->rows + 1;
8692 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8693 ca = &image->tables [MONO_TABLE_PARAM];
8696 for (i = param_list; i < param_last; ++i) {
8697 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8698 if (param_pos == param) {
8706 idx <<= MONO_CUSTOM_ATTR_BITS;
8707 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8708 return mono_custom_attrs_from_index (image, idx);
8712 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8716 for (i = 0; i < ainfo->num_attrs; ++i) {
8717 klass = ainfo->attrs [i].ctor->klass;
8718 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8725 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8732 for (i = 0; i < ainfo->num_attrs; ++i) {
8733 klass = ainfo->attrs [i].ctor->klass;
8734 if (mono_class_has_parent (klass, attr_klass)) {
8739 if (attr_index == -1)
8742 attrs = mono_custom_attrs_construct (ainfo);
8744 return mono_array_get (attrs, MonoObject*, attr_index);
8750 * mono_reflection_get_custom_attrs_info:
8751 * @obj: a reflection object handle
8753 * Return the custom attribute info for attributes defined for the
8754 * reflection handle @obj. The objects.
8756 * FIXME this function leaks like a sieve for SRE objects.
8759 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8762 MonoCustomAttrInfo *cinfo = NULL;
8764 klass = obj->vtable->klass;
8765 if (klass == mono_defaults.monotype_class) {
8766 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8767 klass = mono_class_from_mono_type (type);
8768 /*We cannot mono_class_init the class from which we'll load the custom attributes since this must work with broken types.*/
8769 cinfo = mono_custom_attrs_from_class (klass);
8770 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8771 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8772 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8773 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8774 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8775 cinfo = mono_custom_attrs_from_module (module->image);
8776 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8777 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8778 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8779 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8780 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8781 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8782 } else if (strcmp ("MonoField", klass->name) == 0) {
8783 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8784 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8785 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8786 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8787 cinfo = mono_custom_attrs_from_method (rmethod->method);
8788 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8789 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8790 cinfo = mono_custom_attrs_from_method (rmethod->method);
8791 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8792 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8793 MonoClass *member_class = mono_object_class (param->MemberImpl);
8794 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8795 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8796 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8797 } else if (is_sr_mono_property (member_class)) {
8798 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8800 if (!(method = prop->property->get))
8801 method = prop->property->set;
8804 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8806 #ifndef DISABLE_REFLECTION_EMIT
8807 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8808 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8809 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8810 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8811 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8812 MonoMethod *method = NULL;
8813 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8814 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8815 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8816 method = ((MonoReflectionMethod *)c->cb)->method;
8818 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));
8820 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8824 char *type_name = mono_type_get_full_name (member_class);
8825 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8826 MonoException *ex = mono_get_exception_not_supported (msg);
8829 mono_raise_exception (ex);
8831 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8832 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8833 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8834 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8835 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8836 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8837 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8838 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8839 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8840 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8841 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8842 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8843 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8844 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8845 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8846 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8847 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8848 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8849 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8850 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8851 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8852 } else { /* handle other types here... */
8853 g_error ("get custom attrs not yet supported for %s", klass->name);
8860 * mono_reflection_get_custom_attrs_by_type:
8861 * @obj: a reflection object handle
8863 * Return an array with all the custom attributes defined of the
8864 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8865 * of that type are returned. The objects are fully build. Return NULL if a loading error
8869 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass, MonoError *error)
8872 MonoCustomAttrInfo *cinfo;
8874 mono_error_init (error);
8876 cinfo = mono_reflection_get_custom_attrs_info (obj);
8878 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass, error);
8880 mono_custom_attrs_free (cinfo);
8882 if (mono_loader_get_last_error ())
8884 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8891 * mono_reflection_get_custom_attrs:
8892 * @obj: a reflection object handle
8894 * Return an array with all the custom attributes defined of the
8895 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8899 mono_reflection_get_custom_attrs (MonoObject *obj)
8903 return mono_reflection_get_custom_attrs_by_type (obj, NULL, &error);
8907 * mono_reflection_get_custom_attrs_data:
8908 * @obj: a reflection obj handle
8910 * Returns an array of System.Reflection.CustomAttributeData,
8911 * which include information about attributes reflected on
8912 * types loaded using the Reflection Only methods
8915 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8918 MonoCustomAttrInfo *cinfo;
8920 cinfo = mono_reflection_get_custom_attrs_info (obj);
8922 result = mono_custom_attrs_data_construct (cinfo);
8924 mono_custom_attrs_free (cinfo);
8926 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8931 static MonoReflectionType*
8932 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8934 static MonoMethod *method_get_underlying_system_type = NULL;
8935 MonoMethod *usertype_method;
8937 if (!method_get_underlying_system_type)
8938 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8939 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8940 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8945 is_corlib_type (MonoClass *class)
8947 return class->image == mono_defaults.corlib;
8950 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8951 static MonoClass *cached_class; \
8953 return cached_class == _class; \
8954 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8955 cached_class = _class; \
8962 #ifndef DISABLE_REFLECTION_EMIT
8964 is_sre_array (MonoClass *class)
8966 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8970 is_sre_byref (MonoClass *class)
8972 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8976 is_sre_pointer (MonoClass *class)
8978 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8982 is_sre_generic_instance (MonoClass *class)
8984 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8988 is_sre_type_builder (MonoClass *class)
8990 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8994 is_sre_method_builder (MonoClass *class)
8996 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9000 is_sre_ctor_builder (MonoClass *class)
9002 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9006 is_sre_field_builder (MonoClass *class)
9008 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9012 is_sre_method_on_tb_inst (MonoClass *class)
9014 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9018 is_sre_ctor_on_tb_inst (MonoClass *class)
9020 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9024 mono_reflection_type_get_handle (MonoReflectionType* ref)
9032 if (is_usertype (ref)) {
9033 ref = mono_reflection_type_get_underlying_system_type (ref);
9034 if (ref == NULL || is_usertype (ref))
9040 class = mono_object_class (ref);
9042 if (is_sre_array (class)) {
9044 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9045 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9047 if (sre_array->rank == 0) //single dimentional array
9048 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9050 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9051 sre_array->type.type = res;
9053 } else if (is_sre_byref (class)) {
9055 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9056 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9058 res = &mono_class_from_mono_type (base)->this_arg;
9059 sre_byref->type.type = res;
9061 } else if (is_sre_pointer (class)) {
9063 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9064 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9066 res = &mono_ptr_class_get (base)->byval_arg;
9067 sre_pointer->type.type = res;
9069 } else if (is_sre_generic_instance (class)) {
9070 MonoType *res, **types;
9071 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9074 count = mono_array_length (gclass->type_arguments);
9075 types = g_new0 (MonoType*, count);
9076 for (i = 0; i < count; ++i) {
9077 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9078 types [i] = mono_reflection_type_get_handle (t);
9085 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9088 gclass->type.type = res;
9092 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9099 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9101 mono_reflection_type_get_handle (type);
9105 mono_reflection_register_with_runtime (MonoReflectionType *type)
9107 MonoType *res = mono_reflection_type_get_handle (type);
9108 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9112 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9114 class = mono_class_from_mono_type (res);
9116 mono_loader_lock (); /*same locking as mono_type_get_object*/
9117 mono_domain_lock (domain);
9119 if (!class->image->dynamic) {
9120 mono_class_setup_supertypes (class);
9122 if (!domain->type_hash)
9123 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mono_metadata_type_hash,
9124 (GCompareFunc)mono_metadata_type_equal, MONO_HASH_VALUE_GC);
9125 mono_g_hash_table_insert (domain->type_hash, res, type);
9127 mono_domain_unlock (domain);
9128 mono_loader_unlock ();
9132 * LOCKING: Assumes the loader lock is held.
9134 static MonoMethodSignature*
9135 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9136 MonoMethodSignature *sig;
9139 count = parameters? mono_array_length (parameters): 0;
9141 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9142 sig->param_count = count;
9143 sig->sentinelpos = -1; /* FIXME */
9144 for (i = 0; i < count; ++i)
9145 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9150 * LOCKING: Assumes the loader lock is held.
9152 static MonoMethodSignature*
9153 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9154 MonoMethodSignature *sig;
9156 sig = parameters_to_signature (image, ctor->parameters);
9157 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9158 sig->ret = &mono_defaults.void_class->byval_arg;
9163 * LOCKING: Assumes the loader lock is held.
9165 static MonoMethodSignature*
9166 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9167 MonoMethodSignature *sig;
9169 sig = parameters_to_signature (image, method->parameters);
9170 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9171 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9172 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9176 static MonoMethodSignature*
9177 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9178 MonoMethodSignature *sig;
9180 sig = parameters_to_signature (NULL, method->parameters);
9181 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9182 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9183 sig->generic_param_count = 0;
9188 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9190 MonoClass *klass = mono_object_class (prop);
9191 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9192 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9193 *name = mono_string_to_utf8 (pb->name);
9194 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9196 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9197 *name = g_strdup (p->property->name);
9198 if (p->property->get)
9199 *type = mono_method_signature (p->property->get)->ret;
9201 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9206 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9208 MonoClass *klass = mono_object_class (field);
9209 if (strcmp (klass->name, "FieldBuilder") == 0) {
9210 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9211 *name = mono_string_to_utf8 (fb->name);
9212 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9214 MonoReflectionField *f = (MonoReflectionField *)field;
9215 *name = g_strdup (mono_field_get_name (f->field));
9216 *type = f->field->type;
9220 #else /* DISABLE_REFLECTION_EMIT */
9223 mono_reflection_register_with_runtime (MonoReflectionType *type)
9229 is_sre_type_builder (MonoClass *class)
9235 is_sre_generic_instance (MonoClass *class)
9241 init_type_builder_generics (MonoObject *type)
9245 #endif /* !DISABLE_REFLECTION_EMIT */
9249 is_sr_mono_field (MonoClass *class)
9251 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9255 is_sr_mono_property (MonoClass *class)
9257 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9261 is_sr_mono_method (MonoClass *class)
9263 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9267 is_sr_mono_cmethod (MonoClass *class)
9269 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9273 is_sr_mono_generic_method (MonoClass *class)
9275 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9279 is_sr_mono_generic_cmethod (MonoClass *class)
9281 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9285 mono_class_is_reflection_method_or_constructor (MonoClass *class)
9287 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9291 is_usertype (MonoReflectionType *ref)
9293 MonoClass *class = mono_object_class (ref);
9294 return class->image != mono_defaults.corlib || strcmp ("TypeDelegator", class->name) == 0;
9297 static MonoReflectionType*
9298 mono_reflection_type_resolve_user_types (MonoReflectionType *type)
9300 if (!type || type->type)
9303 if (is_usertype (type)) {
9304 type = mono_reflection_type_get_underlying_system_type (type);
9305 if (is_usertype (type))
9306 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9312 * Encode a value in a custom attribute stream of bytes.
9313 * The value to encode is either supplied as an object in argument val
9314 * (valuetypes are boxed), or as a pointer to the data in the
9316 * @type represents the type of the value
9317 * @buffer is the start of the buffer
9318 * @p the current position in the buffer
9319 * @buflen contains the size of the buffer and is used to return the new buffer size
9320 * if this needs to be realloced.
9321 * @retbuffer and @retp return the start and the position of the buffer
9324 encode_cattr_value (MonoAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, MonoObject *arg, char *argval)
9326 MonoTypeEnum simple_type;
9328 if ((p-buffer) + 10 >= *buflen) {
9331 newbuf = g_realloc (buffer, *buflen);
9332 p = newbuf + (p-buffer);
9336 argval = ((char*)arg + sizeof (MonoObject));
9337 simple_type = type->type;
9339 switch (simple_type) {
9340 case MONO_TYPE_BOOLEAN:
9345 case MONO_TYPE_CHAR:
9348 swap_with_size (p, argval, 2, 1);
9354 swap_with_size (p, argval, 4, 1);
9358 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9368 swap_with_size (p, argval, 8, 1);
9374 swap_with_size (p, argval, 8, 1);
9377 case MONO_TYPE_VALUETYPE:
9378 if (type->data.klass->enumtype) {
9379 simple_type = mono_class_enum_basetype (type->data.klass)->type;
9382 g_warning ("generic valutype %s not handled in custom attr value decoding", type->data.klass->name);
9385 case MONO_TYPE_STRING: {
9392 str = mono_string_to_utf8 ((MonoString*)arg);
9393 slen = strlen (str);
9394 if ((p-buffer) + 10 + slen >= *buflen) {
9398 newbuf = g_realloc (buffer, *buflen);
9399 p = newbuf + (p-buffer);
9402 mono_metadata_encode_value (slen, p, &p);
9403 memcpy (p, str, slen);
9408 case MONO_TYPE_CLASS: {
9416 str = type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)arg), NULL);
9417 slen = strlen (str);
9418 if ((p-buffer) + 10 + slen >= *buflen) {
9422 newbuf = g_realloc (buffer, *buflen);
9423 p = newbuf + (p-buffer);
9426 mono_metadata_encode_value (slen, p, &p);
9427 memcpy (p, str, slen);
9432 case MONO_TYPE_SZARRAY: {
9434 MonoClass *eclass, *arg_eclass;
9437 *p++ = 0xff; *p++ = 0xff; *p++ = 0xff; *p++ = 0xff;
9440 len = mono_array_length ((MonoArray*)arg);
9442 *p++ = (len >> 8) & 0xff;
9443 *p++ = (len >> 16) & 0xff;
9444 *p++ = (len >> 24) & 0xff;
9446 *retbuffer = buffer;
9447 eclass = type->data.klass;
9448 arg_eclass = mono_object_class (arg)->element_class;
9451 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9452 eclass = mono_defaults.object_class;
9454 if (eclass == mono_defaults.object_class && arg_eclass->valuetype) {
9455 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9456 int elsize = mono_class_array_element_size (arg_eclass);
9457 for (i = 0; i < len; ++i) {
9458 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &arg_eclass->byval_arg, NULL, elptr);
9461 } else if (eclass->valuetype && arg_eclass->valuetype) {
9462 char *elptr = mono_array_addr ((MonoArray*)arg, char, 0);
9463 int elsize = mono_class_array_element_size (eclass);
9464 for (i = 0; i < len; ++i) {
9465 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, NULL, elptr);
9469 for (i = 0; i < len; ++i) {
9470 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &eclass->byval_arg, mono_array_get ((MonoArray*)arg, MonoObject*, i), NULL);
9475 case MONO_TYPE_OBJECT: {
9481 * The parameter type is 'object' but the type of the actual
9482 * argument is not. So we have to add type information to the blob
9483 * too. This is completely undocumented in the spec.
9487 *p++ = MONO_TYPE_STRING; // It's same hack as MS uses
9492 klass = mono_object_class (arg);
9494 if (mono_object_isinst (arg, mono_defaults.systemtype_class)) {
9497 } else if (klass->enumtype) {
9499 } else if (klass == mono_defaults.string_class) {
9500 simple_type = MONO_TYPE_STRING;
9503 } else if (klass->rank == 1) {
9505 if (klass->element_class->byval_arg.type == MONO_TYPE_OBJECT)
9506 /* See Partition II, Appendix B3 */
9509 *p++ = klass->element_class->byval_arg.type;
9510 encode_cattr_value (assembly, buffer, p, &buffer, &p, buflen, &klass->byval_arg, arg, NULL);
9512 } else if (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8) {
9513 *p++ = simple_type = klass->byval_arg.type;
9516 g_error ("unhandled type in custom attr");
9518 str = type_get_qualified_name (mono_class_get_type(klass), NULL);
9519 slen = strlen (str);
9520 if ((p-buffer) + 10 + slen >= *buflen) {
9524 newbuf = g_realloc (buffer, *buflen);
9525 p = newbuf + (p-buffer);
9528 mono_metadata_encode_value (slen, p, &p);
9529 memcpy (p, str, slen);
9532 simple_type = mono_class_enum_basetype (klass)->type;
9536 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type);
9539 *retbuffer = buffer;
9543 encode_field_or_prop_type (MonoType *type, char *p, char **retp)
9545 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9546 char *str = type_get_qualified_name (type, NULL);
9547 int slen = strlen (str);
9551 * This seems to be optional...
9554 mono_metadata_encode_value (slen, p, &p);
9555 memcpy (p, str, slen);
9558 } else if (type->type == MONO_TYPE_OBJECT) {
9560 } else if (type->type == MONO_TYPE_CLASS) {
9561 /* it should be a type: encode_cattr_value () has the check */
9564 mono_metadata_encode_value (type->type, p, &p);
9565 if (type->type == MONO_TYPE_SZARRAY)
9566 /* See the examples in Partition VI, Annex B */
9567 encode_field_or_prop_type (&type->data.klass->byval_arg, p, &p);
9573 #ifndef DISABLE_REFLECTION_EMIT
9575 encode_named_val (MonoReflectionAssembly *assembly, char *buffer, char *p, char **retbuffer, char **retp, guint32 *buflen, MonoType *type, char *name, MonoObject *value)
9578 /* Preallocate a large enough buffer */
9579 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype) {
9580 char *str = type_get_qualified_name (type, NULL);
9583 } else if (type->type == MONO_TYPE_SZARRAY && type->data.klass->enumtype) {
9584 char *str = type_get_qualified_name (&type->data.klass->byval_arg, NULL);
9590 len += strlen (name);
9592 if ((p-buffer) + 20 + len >= *buflen) {
9596 newbuf = g_realloc (buffer, *buflen);
9597 p = newbuf + (p-buffer);
9601 encode_field_or_prop_type (type, p, &p);
9603 len = strlen (name);
9604 mono_metadata_encode_value (len, p, &p);
9605 memcpy (p, name, len);
9607 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, buflen, type, value, NULL);
9609 *retbuffer = buffer;
9613 * mono_reflection_get_custom_attrs_blob:
9614 * @ctor: custom attribute constructor
9615 * @ctorArgs: arguments o the constructor
9621 * Creates the blob of data that needs to be saved in the metadata and that represents
9622 * the custom attributed described by @ctor, @ctorArgs etc.
9623 * Returns: a Byte array representing the blob of data.
9626 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
9629 MonoMethodSignature *sig;
9634 MONO_ARCH_SAVE_REGS;
9636 if (strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
9637 /* sig is freed later so allocate it in the heap */
9638 sig = ctor_builder_to_signature (NULL, (MonoReflectionCtorBuilder*)ctor);
9640 sig = mono_method_signature (((MonoReflectionMethod*)ctor)->method);
9643 g_assert (mono_array_length (ctorArgs) == sig->param_count);
9645 p = buffer = g_malloc (buflen);
9646 /* write the prolog */
9649 for (i = 0; i < sig->param_count; ++i) {
9650 arg = mono_array_get (ctorArgs, MonoObject*, i);
9651 encode_cattr_value (assembly->assembly, buffer, p, &buffer, &p, &buflen, sig->params [i], arg, NULL);
9655 i += mono_array_length (properties);
9657 i += mono_array_length (fields);
9659 *p++ = (i >> 8) & 0xff;
9662 for (i = 0; i < mono_array_length (properties); ++i) {
9666 prop = mono_array_get (properties, gpointer, i);
9667 get_prop_name_and_type (prop, &pname, &ptype);
9668 *p++ = 0x54; /* PROPERTY signature */
9669 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ptype, pname, (MonoObject*)mono_array_get (propValues, gpointer, i));
9676 for (i = 0; i < mono_array_length (fields); ++i) {
9680 field = mono_array_get (fields, gpointer, i);
9681 get_field_name_and_type (field, &fname, &ftype);
9682 *p++ = 0x53; /* FIELD signature */
9683 encode_named_val (assembly, buffer, p, &buffer, &p, &buflen, ftype, fname, (MonoObject*)mono_array_get (fieldValues, gpointer, i));
9688 g_assert (p - buffer <= buflen);
9689 buflen = p - buffer;
9690 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
9691 p = mono_array_addr (result, char, 0);
9692 memcpy (p, buffer, buflen);
9694 if (strcmp (ctor->vtable->klass->name, "MonoCMethod"))
9700 * mono_reflection_setup_internal_class:
9701 * @tb: a TypeBuilder object
9703 * Creates a MonoClass that represents the TypeBuilder.
9704 * This is a trick that lets us simplify a lot of reflection code
9705 * (and will allow us to support Build and Run assemblies easier).
9708 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
9711 MonoClass *klass, *parent;
9713 MONO_ARCH_SAVE_REGS;
9715 RESOLVE_TYPE (tb->parent);
9717 mono_loader_lock ();
9720 /* check so we can compile corlib correctly */
9721 if (strcmp (mono_object_class (tb->parent)->name, "TypeBuilder") == 0) {
9722 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9723 parent = mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent)->data.klass;
9725 parent = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
9731 /* the type has already being created: it means we just have to change the parent */
9732 if (tb->type.type) {
9733 klass = mono_class_from_mono_type (tb->type.type);
9734 klass->parent = NULL;
9735 /* fool mono_class_setup_parent */
9736 klass->supertypes = NULL;
9737 mono_class_setup_parent (klass, parent);
9738 mono_class_setup_mono_type (klass);
9739 mono_loader_unlock ();
9743 klass = mono_image_alloc0 (&tb->module->dynamic_image->image, sizeof (MonoClass));
9745 klass->image = &tb->module->dynamic_image->image;
9747 klass->inited = 1; /* we lie to the runtime */
9748 klass->name = mono_string_to_utf8_image (klass->image, tb->name, &error);
9749 if (!mono_error_ok (&error))
9751 klass->name_space = mono_string_to_utf8_image (klass->image, tb->nspace, &error);
9752 if (!mono_error_ok (&error))
9754 klass->type_token = MONO_TOKEN_TYPE_DEF | tb->table_idx;
9755 klass->flags = tb->attrs;
9757 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
9759 klass->element_class = klass;
9761 if (mono_class_get_ref_info (klass) == NULL) {
9763 mono_class_set_ref_info (klass, tb);
9765 /* Put into cache so mono_class_get () will find it.
9766 Skip nested types as those should not be available on the global scope. */
9767 if (!tb->nesting_type) {
9768 mono_image_add_to_name_cache (klass->image, klass->name_space, klass->name, tb->table_idx);
9770 klass->image->reflection_info_unregister_classes =
9771 g_slist_prepend (klass->image->reflection_info_unregister_classes, klass);
9774 g_assert (mono_class_get_ref_info (klass) == tb);
9777 mono_g_hash_table_insert (tb->module->dynamic_image->tokens,
9778 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF | tb->table_idx), tb);
9780 if (parent != NULL) {
9781 mono_class_setup_parent (klass, parent);
9782 } else if (strcmp (klass->name, "Object") == 0 && strcmp (klass->name_space, "System") == 0) {
9783 const char *old_n = klass->name;
9784 /* trick to get relative numbering right when compiling corlib */
9785 klass->name = "BuildingObject";
9786 mono_class_setup_parent (klass, mono_defaults.object_class);
9787 klass->name = old_n;
9790 if ((!strcmp (klass->name, "ValueType") && !strcmp (klass->name_space, "System")) ||
9791 (!strcmp (klass->name, "Object") && !strcmp (klass->name_space, "System")) ||
9792 (!strcmp (klass->name, "Enum") && !strcmp (klass->name_space, "System"))) {
9793 klass->instance_size = sizeof (MonoObject);
9794 klass->size_inited = 1;
9795 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9798 mono_class_setup_mono_type (klass);
9800 mono_class_setup_supertypes (klass);
9803 * FIXME: handle interfaces.
9806 tb->type.type = &klass->byval_arg;
9808 if (tb->nesting_type) {
9809 g_assert (tb->nesting_type->type);
9810 klass->nested_in = mono_class_from_mono_type (mono_reflection_type_get_handle (tb->nesting_type));
9813 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9815 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
9817 mono_loader_unlock ();
9821 mono_loader_unlock ();
9822 mono_error_raise_exception (&error);
9826 * mono_reflection_setup_generic_class:
9827 * @tb: a TypeBuilder object
9829 * Setup the generic class before adding the first generic parameter.
9832 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
9837 * mono_reflection_create_generic_class:
9838 * @tb: a TypeBuilder object
9840 * Creates the generic class after all generic parameters have been added.
9843 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
9848 MONO_ARCH_SAVE_REGS;
9850 klass = mono_class_from_mono_type (tb->type.type);
9852 count = tb->generic_params ? mono_array_length (tb->generic_params) : 0;
9854 if (klass->generic_container || (count == 0))
9857 g_assert (tb->generic_container && (tb->generic_container->owner.klass == klass));
9859 klass->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
9861 klass->generic_container->owner.klass = klass;
9862 klass->generic_container->type_argc = count;
9863 klass->generic_container->type_params = mono_image_alloc0 (klass->image, sizeof (MonoGenericParamFull) * count);
9865 klass->is_generic = 1;
9867 for (i = 0; i < count; i++) {
9868 MonoReflectionGenericParam *gparam = mono_array_get (tb->generic_params, gpointer, i);
9869 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gparam)->data.generic_param;
9870 klass->generic_container->type_params [i] = *param;
9871 /*Make sure we are a diferent type instance */
9872 klass->generic_container->type_params [i].param.owner = klass->generic_container;
9873 klass->generic_container->type_params [i].info.pklass = NULL;
9874 klass->generic_container->type_params [i].info.flags = gparam->attrs;
9876 g_assert (klass->generic_container->type_params [i].param.owner);
9879 klass->generic_container->context.class_inst = mono_get_shared_generic_inst (klass->generic_container);
9883 * mono_reflection_create_internal_class:
9884 * @tb: a TypeBuilder object
9886 * Actually create the MonoClass that is associated with the TypeBuilder.
9889 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
9893 MONO_ARCH_SAVE_REGS;
9895 klass = mono_class_from_mono_type (tb->type.type);
9897 mono_loader_lock ();
9898 if (klass->enumtype && mono_class_enum_basetype (klass) == NULL) {
9899 MonoReflectionFieldBuilder *fb;
9901 MonoType *enum_basetype;
9903 g_assert (tb->fields != NULL);
9904 g_assert (mono_array_length (tb->fields) >= 1);
9906 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, 0);
9908 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType*)fb->type))) {
9909 mono_loader_unlock ();
9913 enum_basetype = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9914 klass->element_class = mono_class_from_mono_type (enum_basetype);
9915 if (!klass->element_class)
9916 klass->element_class = mono_class_from_mono_type (enum_basetype);
9919 * get the element_class from the current corlib.
9921 ec = default_class_from_mono_type (enum_basetype);
9922 klass->instance_size = ec->instance_size;
9923 klass->size_inited = 1;
9925 * this is almost safe to do with enums and it's needed to be able
9926 * to create objects of the enum type (for use in SetConstant).
9928 /* FIXME: Does this mean enums can't have method overrides ? */
9929 mono_class_setup_vtable_general (klass, NULL, 0, NULL);
9931 mono_loader_unlock ();
9934 static MonoMarshalSpec*
9935 mono_marshal_spec_from_builder (MonoImage *image, MonoAssembly *assembly,
9936 MonoReflectionMarshal *minfo)
9938 MonoMarshalSpec *res;
9940 res = image_g_new0 (image, MonoMarshalSpec, 1);
9941 res->native = minfo->type;
9943 switch (minfo->type) {
9944 case MONO_NATIVE_LPARRAY:
9945 res->data.array_data.elem_type = minfo->eltype;
9946 if (minfo->has_size) {
9947 res->data.array_data.param_num = minfo->param_num;
9948 res->data.array_data.num_elem = minfo->count;
9949 res->data.array_data.elem_mult = minfo->param_num == -1 ? 0 : 1;
9952 res->data.array_data.param_num = -1;
9953 res->data.array_data.num_elem = -1;
9954 res->data.array_data.elem_mult = -1;
9958 case MONO_NATIVE_BYVALTSTR:
9959 case MONO_NATIVE_BYVALARRAY:
9960 res->data.array_data.num_elem = minfo->count;
9963 case MONO_NATIVE_CUSTOM:
9964 if (minfo->marshaltyperef)
9965 res->data.custom_data.custom_name =
9966 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
9968 res->data.custom_data.cookie = mono_string_to_utf8 (minfo->mcookie);
9977 #endif /* !DISABLE_REFLECTION_EMIT */
9979 MonoReflectionMarshal*
9980 mono_reflection_marshal_from_marshal_spec (MonoDomain *domain, MonoClass *klass,
9981 MonoMarshalSpec *spec)
9983 static MonoClass *System_Reflection_Emit_UnmanagedMarshalClass;
9984 MonoReflectionMarshal *minfo;
9987 if (!System_Reflection_Emit_UnmanagedMarshalClass) {
9988 System_Reflection_Emit_UnmanagedMarshalClass = mono_class_from_name (
9989 mono_defaults.corlib, "System.Reflection.Emit", "UnmanagedMarshal");
9990 g_assert (System_Reflection_Emit_UnmanagedMarshalClass);
9993 minfo = (MonoReflectionMarshal*)mono_object_new (domain, System_Reflection_Emit_UnmanagedMarshalClass);
9994 minfo->type = spec->native;
9996 switch (minfo->type) {
9997 case MONO_NATIVE_LPARRAY:
9998 minfo->eltype = spec->data.array_data.elem_type;
9999 minfo->count = spec->data.array_data.num_elem;
10000 minfo->param_num = spec->data.array_data.param_num;
10003 case MONO_NATIVE_BYVALTSTR:
10004 case MONO_NATIVE_BYVALARRAY:
10005 minfo->count = spec->data.array_data.num_elem;
10008 case MONO_NATIVE_CUSTOM:
10009 if (spec->data.custom_data.custom_name) {
10010 mtype = mono_reflection_type_from_name (spec->data.custom_data.custom_name, klass->image);
10012 MONO_OBJECT_SETREF (minfo, marshaltyperef, mono_type_get_object (domain, mtype));
10014 MONO_OBJECT_SETREF (minfo, marshaltype, mono_string_new (domain, spec->data.custom_data.custom_name));
10016 if (spec->data.custom_data.cookie)
10017 MONO_OBJECT_SETREF (minfo, mcookie, mono_string_new (domain, spec->data.custom_data.cookie));
10027 #ifndef DISABLE_REFLECTION_EMIT
10029 reflection_methodbuilder_to_mono_method (MonoClass *klass,
10030 ReflectionMethodBuilder *rmb,
10031 MonoMethodSignature *sig)
10035 MonoMethodWrapper *wrapperm;
10036 MonoMarshalSpec **specs;
10037 MonoReflectionMethodAux *method_aux;
10042 mono_error_init (&error);
10044 * Methods created using a MethodBuilder should have their memory allocated
10045 * inside the image mempool, while dynamic methods should have their memory
10048 dynamic = rmb->refs != NULL;
10049 image = dynamic ? NULL : klass->image;
10052 g_assert (!klass->generic_class);
10054 mono_loader_lock ();
10056 if ((rmb->attrs & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
10057 (rmb->iattrs & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL))
10058 m = (MonoMethod *)image_g_new0 (image, MonoMethodPInvoke, 1);
10060 m = (MonoMethod *)image_g_new0 (image, MonoMethodWrapper, 1);
10062 wrapperm = (MonoMethodWrapper*)m;
10064 m->dynamic = dynamic;
10066 m->flags = rmb->attrs;
10067 m->iflags = rmb->iattrs;
10068 m->name = mono_string_to_utf8_image (image, rmb->name, &error);
10069 g_assert (mono_error_ok (&error));
10071 m->signature = sig;
10072 m->sre_method = TRUE;
10073 m->skip_visibility = rmb->skip_visibility;
10074 if (rmb->table_idx)
10075 m->token = MONO_TOKEN_METHOD_DEF | (*rmb->table_idx);
10077 if (m->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
10078 if (klass == mono_defaults.string_class && !strcmp (m->name, ".ctor"))
10079 m->string_ctor = 1;
10081 m->signature->pinvoke = 1;
10082 } else if (m->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
10083 m->signature->pinvoke = 1;
10085 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10087 method_aux->dllentry = rmb->dllentry ? mono_string_to_utf8_image (image, rmb->dllentry, &error) : image_strdup (image, m->name);
10088 g_assert (mono_error_ok (&error));
10089 method_aux->dll = mono_string_to_utf8_image (image, rmb->dll, &error);
10090 g_assert (mono_error_ok (&error));
10092 ((MonoMethodPInvoke*)m)->piflags = (rmb->native_cc << 8) | (rmb->charset ? (rmb->charset - 1) * 2 : 0) | rmb->extra_flags;
10094 if (klass->image->dynamic)
10095 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10097 mono_loader_unlock ();
10100 } else if (!(m->flags & METHOD_ATTRIBUTE_ABSTRACT) &&
10101 !(m->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME)) {
10102 MonoMethodHeader *header;
10104 gint32 max_stack, i;
10105 gint32 num_locals = 0;
10106 gint32 num_clauses = 0;
10110 code = mono_array_addr (rmb->ilgen->code, guint8, 0);
10111 code_size = rmb->ilgen->code_len;
10112 max_stack = rmb->ilgen->max_stack;
10113 num_locals = rmb->ilgen->locals ? mono_array_length (rmb->ilgen->locals) : 0;
10114 if (rmb->ilgen->ex_handlers)
10115 num_clauses = method_count_clauses (rmb->ilgen);
10118 code = mono_array_addr (rmb->code, guint8, 0);
10119 code_size = mono_array_length (rmb->code);
10120 /* we probably need to run a verifier on the code... */
10130 header = image_g_malloc0 (image, MONO_SIZEOF_METHOD_HEADER + num_locals * sizeof (MonoType*));
10131 header->code_size = code_size;
10132 header->code = image_g_malloc (image, code_size);
10133 memcpy ((char*)header->code, code, code_size);
10134 header->max_stack = max_stack;
10135 header->init_locals = rmb->init_locals;
10136 header->num_locals = num_locals;
10138 for (i = 0; i < num_locals; ++i) {
10139 MonoReflectionLocalBuilder *lb =
10140 mono_array_get (rmb->ilgen->locals, MonoReflectionLocalBuilder*, i);
10142 header->locals [i] = image_g_new0 (image, MonoType, 1);
10143 memcpy (header->locals [i], mono_reflection_type_get_handle ((MonoReflectionType*)lb->type), MONO_SIZEOF_TYPE);
10146 header->num_clauses = num_clauses;
10148 header->clauses = method_encode_clauses (image, (MonoDynamicImage*)klass->image,
10149 rmb->ilgen, num_clauses);
10152 wrapperm->header = header;
10155 if (rmb->generic_params) {
10156 int count = mono_array_length (rmb->generic_params);
10157 MonoGenericContainer *container = rmb->generic_container;
10159 g_assert (container);
10161 container->type_argc = count;
10162 container->type_params = image_g_new0 (image, MonoGenericParamFull, count);
10163 container->owner.method = m;
10165 m->is_generic = TRUE;
10166 mono_method_set_generic_container (m, container);
10168 for (i = 0; i < count; i++) {
10169 MonoReflectionGenericParam *gp =
10170 mono_array_get (rmb->generic_params, MonoReflectionGenericParam*, i);
10171 MonoGenericParamFull *param = (MonoGenericParamFull *) mono_reflection_type_get_handle ((MonoReflectionType*)gp)->data.generic_param;
10172 container->type_params [i] = *param;
10176 * The method signature might have pointers to generic parameters that belong to other methods.
10177 * This is a valid SRE case, but the resulting method signature must be encoded using the proper
10178 * generic parameters.
10180 for (i = 0; i < m->signature->param_count; ++i) {
10181 MonoType *t = m->signature->params [i];
10182 if (t->type == MONO_TYPE_MVAR) {
10183 MonoGenericParam *gparam = t->data.generic_param;
10184 if (gparam->num < count) {
10185 m->signature->params [i] = mono_metadata_type_dup (image, m->signature->params [i]);
10186 m->signature->params [i]->data.generic_param = mono_generic_container_get_param (container, gparam->num);
10192 if (klass->generic_container) {
10193 container->parent = klass->generic_container;
10194 container->context.class_inst = klass->generic_container->context.class_inst;
10196 container->context.method_inst = mono_get_shared_generic_inst (container);
10200 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10204 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10206 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10207 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10208 for (i = 0; i < rmb->nrefs; ++i)
10209 data [i + 1] = rmb->refs [i];
10214 /* Parameter info */
10217 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10218 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10219 for (i = 0; i <= m->signature->param_count; ++i) {
10220 MonoReflectionParamBuilder *pb;
10221 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10222 if ((i > 0) && (pb->attrs)) {
10223 /* Make a copy since it might point to a shared type structure */
10224 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10225 m->signature->params [i - 1]->attrs = pb->attrs;
10228 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10229 MonoDynamicImage *assembly;
10230 guint32 idx, def_type, len;
10234 if (!method_aux->param_defaults) {
10235 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10236 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10238 assembly = (MonoDynamicImage*)klass->image;
10239 idx = encode_constant (assembly, pb->def_value, &def_type);
10240 /* Copy the data from the blob since it might get realloc-ed */
10241 p = assembly->blob.data + idx;
10242 len = mono_metadata_decode_blob_size (p, &p2);
10244 method_aux->param_defaults [i] = image_g_malloc (image, len);
10245 method_aux->param_default_types [i] = def_type;
10246 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10250 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10251 g_assert (mono_error_ok (&error));
10254 if (!method_aux->param_cattr)
10255 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10256 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10262 /* Parameter marshalling */
10265 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10266 MonoReflectionParamBuilder *pb;
10267 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10268 if (pb->marshal_info) {
10270 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10271 specs [pb->position] =
10272 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10276 if (specs != NULL) {
10278 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10279 method_aux->param_marshall = specs;
10282 if (klass->image->dynamic && method_aux)
10283 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10285 mono_loader_unlock ();
10291 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10293 ReflectionMethodBuilder rmb;
10294 MonoMethodSignature *sig;
10296 mono_loader_lock ();
10297 sig = ctor_builder_to_signature (klass->image, mb);
10298 mono_loader_unlock ();
10300 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10302 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10303 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10305 /* If we are in a generic class, we might be called multiple times from inflate_method */
10306 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10307 /* ilgen is no longer needed */
10311 return mb->mhandle;
10315 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10317 ReflectionMethodBuilder rmb;
10318 MonoMethodSignature *sig;
10320 mono_loader_lock ();
10321 sig = method_builder_to_signature (klass->image, mb);
10322 mono_loader_unlock ();
10324 reflection_methodbuilder_from_method_builder (&rmb, mb);
10326 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10327 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10329 /* If we are in a generic class, we might be called multiple times from inflate_method */
10330 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10331 /* ilgen is no longer needed */
10334 return mb->mhandle;
10337 static MonoClassField*
10338 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10340 MonoClassField *field;
10344 field = g_new0 (MonoClassField, 1);
10346 field->name = mono_string_to_utf8_image (klass->image, fb->name, &error);
10347 g_assert (mono_error_ok (&error));
10348 if (fb->attrs || fb->modreq || fb->modopt) {
10349 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10350 field->type->attrs = fb->attrs;
10352 g_assert (klass->image->dynamic);
10353 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10354 g_free (field->type);
10355 field->type = mono_metadata_type_dup (klass->image, custom);
10358 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10360 if (fb->offset != -1)
10361 field->offset = fb->offset;
10362 field->parent = klass;
10363 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10365 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10372 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10375 MonoReflectionTypeBuilder *tb = NULL;
10376 gboolean is_dynamic = FALSE;
10377 MonoDomain *domain;
10378 MonoClass *geninst;
10380 mono_loader_lock ();
10382 domain = mono_object_domain (type);
10384 if (is_sre_type_builder (mono_object_class (type))) {
10385 tb = (MonoReflectionTypeBuilder *) type;
10388 } else if (is_sre_generic_instance (mono_object_class (type))) {
10389 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10390 MonoReflectionType *gtd = rgi->generic_type;
10392 if (is_sre_type_builder (mono_object_class (gtd))) {
10393 tb = (MonoReflectionTypeBuilder *)gtd;
10398 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10399 if (tb && tb->generic_container)
10400 mono_reflection_create_generic_class (tb);
10402 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10403 if (!klass->generic_container) {
10404 mono_loader_unlock ();
10408 if (klass->wastypebuilder) {
10409 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10414 mono_loader_unlock ();
10416 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10418 return &geninst->byval_arg;
10422 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10424 MonoGenericClass *gclass;
10425 MonoGenericInst *inst;
10427 g_assert (klass->generic_container);
10429 inst = mono_metadata_get_generic_inst (type_argc, types);
10430 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10432 return mono_generic_class_get_class (gclass);
10435 MonoReflectionMethod*
10436 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10439 MonoMethod *method, *inflated;
10440 MonoMethodInflated *imethod;
10441 MonoGenericContext tmp_context;
10442 MonoGenericInst *ginst;
10443 MonoType **type_argv;
10446 MONO_ARCH_SAVE_REGS;
10448 /*FIXME but this no longer should happen*/
10449 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10450 #ifndef DISABLE_REFLECTION_EMIT
10451 MonoReflectionMethodBuilder *mb = NULL;
10452 MonoReflectionTypeBuilder *tb;
10455 mb = (MonoReflectionMethodBuilder *) rmethod;
10456 tb = (MonoReflectionTypeBuilder *) mb->type;
10457 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10459 method = methodbuilder_to_mono_method (klass, mb);
10461 g_assert_not_reached ();
10465 method = rmethod->method;
10468 klass = method->klass;
10470 if (method->is_inflated)
10471 method = ((MonoMethodInflated *) method)->declaring;
10473 count = mono_method_signature (method)->generic_param_count;
10474 if (count != mono_array_length (types))
10477 type_argv = g_new0 (MonoType *, count);
10478 for (i = 0; i < count; i++) {
10479 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10480 type_argv [i] = mono_reflection_type_get_handle (garg);
10482 ginst = mono_metadata_get_generic_inst (count, type_argv);
10483 g_free (type_argv);
10485 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10486 tmp_context.method_inst = ginst;
10488 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10489 imethod = (MonoMethodInflated *) inflated;
10491 /*FIXME but I think this is no longer necessary*/
10492 if (method->klass->image->dynamic) {
10493 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10495 * This table maps metadata structures representing inflated methods/fields
10496 * to the reflection objects representing their generic definitions.
10498 mono_loader_lock ();
10499 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10500 mono_loader_unlock ();
10503 if (!mono_verifier_is_method_valid_generic_instantiation (inflated))
10504 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
10506 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10509 #ifndef DISABLE_REFLECTION_EMIT
10511 static MonoMethod *
10512 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10514 MonoMethodInflated *imethod;
10515 MonoGenericContext *context;
10519 * With generic code sharing the klass might not be inflated.
10520 * This can happen because classes inflated with their own
10521 * type arguments are "normalized" to the uninflated class.
10523 if (!klass->generic_class)
10526 context = mono_class_get_context (klass);
10528 if (klass->method.count && klass->methods) {
10529 /* Find the already created inflated method */
10530 for (i = 0; i < klass->method.count; ++i) {
10531 g_assert (klass->methods [i]->is_inflated);
10532 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10535 g_assert (i < klass->method.count);
10536 imethod = (MonoMethodInflated*)klass->methods [i];
10538 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10541 if (method->is_generic && method->klass->image->dynamic) {
10542 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10544 mono_loader_lock ();
10545 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10546 mono_loader_unlock ();
10548 return (MonoMethod *) imethod;
10551 static MonoMethod *
10552 inflate_method (MonoReflectionType *type, MonoObject *obj)
10554 MonoMethod *method;
10557 MonoClass *type_class = mono_object_class (type);
10559 if (is_sre_generic_instance (type_class)) {
10560 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10561 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10562 } else if (is_sre_type_builder (type_class)) {
10563 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10564 } else if (type->type) {
10565 gklass = mono_class_from_mono_type (type->type);
10566 gklass = mono_class_get_generic_type_definition (gklass);
10568 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10571 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10572 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10573 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10575 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10576 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10577 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10578 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10579 method = ((MonoReflectionMethod *) obj)->method;
10581 method = NULL; /* prevent compiler warning */
10582 g_error ("can't handle type %s", obj->vtable->klass->name);
10585 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10588 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10590 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10591 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10594 MonoGenericClass *gclass;
10595 MonoDynamicGenericClass *dgclass;
10596 MonoClass *klass, *gklass;
10600 MONO_ARCH_SAVE_REGS;
10602 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10603 klass = mono_class_from_mono_type (gtype);
10604 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10605 gclass = gtype->data.generic_class;
10607 if (!gclass->is_dynamic)
10610 dgclass = (MonoDynamicGenericClass *) gclass;
10612 if (dgclass->initialized)
10615 gklass = gclass->container_class;
10616 mono_class_init (gklass);
10618 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10619 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10620 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10622 dgclass->methods = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_methods);
10623 dgclass->ctors = mono_image_set_new0 (gclass->owner, MonoMethod *, dgclass->count_ctors);
10624 dgclass->fields = mono_image_set_new0 (gclass->owner, MonoClassField, dgclass->count_fields);
10625 dgclass->field_objects = mono_image_set_new0 (gclass->owner, MonoObject*, dgclass->count_fields);
10626 dgclass->field_generic_types = mono_image_set_new0 (gclass->owner, MonoType*, dgclass->count_fields);
10628 for (i = 0; i < dgclass->count_methods; i++) {
10629 MonoObject *obj = mono_array_get (methods, gpointer, i);
10631 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10634 for (i = 0; i < dgclass->count_ctors; i++) {
10635 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10637 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10640 for (i = 0; i < dgclass->count_fields; i++) {
10641 MonoObject *obj = mono_array_get (fields, gpointer, i);
10642 MonoClassField *field, *inflated_field = NULL;
10644 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10645 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10646 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10647 field = ((MonoReflectionField *) obj)->field;
10649 field = NULL; /* prevent compiler warning */
10650 g_assert_not_reached ();
10653 dgclass->fields [i] = *field;
10654 dgclass->fields [i].parent = klass;
10655 dgclass->fields [i].type = mono_class_inflate_generic_type (
10656 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10657 dgclass->field_generic_types [i] = field->type;
10658 MONO_GC_REGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10659 dgclass->field_objects [i] = obj;
10661 if (inflated_field) {
10662 g_free (inflated_field);
10664 dgclass->fields [i].name = mono_image_set_strdup (gclass->owner, dgclass->fields [i].name);
10668 dgclass->initialized = TRUE;
10672 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
10674 MonoDynamicGenericClass *dgclass;
10677 g_assert (gclass->is_dynamic);
10679 dgclass = (MonoDynamicGenericClass *)gclass;
10681 for (i = 0; i < dgclass->count_fields; ++i) {
10682 MonoClassField *field = dgclass->fields + i;
10683 mono_metadata_free_type (field->type);
10684 MONO_GC_UNREGISTER_ROOT_IF_MOVING (dgclass->field_objects [i]);
10689 fix_partial_generic_class (MonoClass *klass)
10691 MonoClass *gklass = klass->generic_class->container_class;
10692 MonoDynamicGenericClass *dgclass;
10695 if (klass->wastypebuilder)
10698 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10699 if (klass->parent != gklass->parent) {
10701 MonoType *parent_type = mono_class_inflate_generic_type_checked (&gklass->parent->byval_arg, &klass->generic_class->context, &error);
10702 if (mono_error_ok (&error)) {
10703 MonoClass *parent = mono_class_from_mono_type (parent_type);
10704 mono_metadata_free_type (parent_type);
10705 if (parent != klass->parent) {
10706 /*fool mono_class_setup_parent*/
10707 klass->supertypes = NULL;
10708 mono_class_setup_parent (klass, parent);
10711 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10712 mono_error_cleanup (&error);
10713 if (gklass->wastypebuilder)
10714 klass->wastypebuilder = TRUE;
10719 if (!dgclass->initialized)
10722 if (klass->method.count != gklass->method.count) {
10723 klass->method.count = gklass->method.count;
10724 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10726 for (i = 0; i < klass->method.count; i++) {
10727 klass->methods [i] = mono_class_inflate_generic_method_full (
10728 gklass->methods [i], klass, mono_class_get_context (klass));
10732 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10733 klass->interface_count = gklass->interface_count;
10734 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10735 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10737 for (i = 0; i < gklass->interface_count; ++i) {
10738 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10739 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10740 mono_metadata_free_type (iface_type);
10742 ensure_runtime_vtable (klass->interfaces [i]);
10744 klass->interfaces_inited = 1;
10747 if (klass->field.count != gklass->field.count) {
10748 klass->field.count = gklass->field.count;
10749 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10751 for (i = 0; i < klass->field.count; i++) {
10752 klass->fields [i] = gklass->fields [i];
10753 klass->fields [i].parent = klass;
10754 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10758 /*We can only finish with this klass once it's parent has as well*/
10759 if (gklass->wastypebuilder)
10760 klass->wastypebuilder = TRUE;
10765 ensure_generic_class_runtime_vtable (MonoClass *klass)
10767 MonoClass *gklass = klass->generic_class->container_class;
10769 ensure_runtime_vtable (gklass);
10771 fix_partial_generic_class (klass);
10775 ensure_runtime_vtable (MonoClass *klass)
10777 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10780 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10783 ensure_runtime_vtable (klass->parent);
10786 num = tb->ctors? mono_array_length (tb->ctors): 0;
10787 num += tb->num_methods;
10788 klass->method.count = num;
10789 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10790 num = tb->ctors? mono_array_length (tb->ctors): 0;
10791 for (i = 0; i < num; ++i)
10792 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10793 num = tb->num_methods;
10795 for (i = 0; i < num; ++i)
10796 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10798 if (tb->interfaces) {
10799 klass->interface_count = mono_array_length (tb->interfaces);
10800 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10801 for (i = 0; i < klass->interface_count; ++i) {
10802 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10803 klass->interfaces [i] = mono_class_from_mono_type (iface);
10804 ensure_runtime_vtable (klass->interfaces [i]);
10806 klass->interfaces_inited = 1;
10808 } else if (klass->generic_class){
10809 ensure_generic_class_runtime_vtable (klass);
10812 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10814 for (i = 0; i < klass->method.count; ++i) {
10815 MonoMethod *im = klass->methods [i];
10816 if (!(im->flags & METHOD_ATTRIBUTE_STATIC))
10817 im->slot = slot_num++;
10820 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10821 mono_class_setup_interface_offsets (klass);
10822 mono_class_setup_interface_id (klass);
10826 * The generic vtable is needed even if image->run is not set since some
10827 * runtime code like ves_icall_Type_GetMethodsByName depends on
10828 * method->slot being defined.
10832 * tb->methods could not be freed since it is used for determining
10833 * overrides during dynamic vtable construction.
10838 mono_reflection_method_get_handle (MonoObject *method)
10840 MonoClass *class = mono_object_class (method);
10841 if (is_sr_mono_method (class) || is_sr_mono_generic_method (class)) {
10842 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10843 return sr_method->method;
10845 if (is_sre_method_builder (class)) {
10846 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10847 return mb->mhandle;
10849 if (is_sre_method_on_tb_inst (class)) {
10850 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10851 MonoMethod *result;
10852 /*FIXME move this to a proper method and unify with resolve_object*/
10853 if (m->method_args) {
10854 result = mono_reflection_method_on_tb_inst_get_handle (m);
10856 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10857 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10858 MonoMethod *mono_method;
10860 if (is_sre_method_builder (mono_object_class (m->mb)))
10861 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10862 else if (is_sr_mono_method (mono_object_class (m->mb)))
10863 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10865 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)));
10867 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10872 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10877 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10879 MonoReflectionTypeBuilder *tb;
10883 *num_overrides = 0;
10885 g_assert (klass->image->dynamic);
10887 if (!mono_class_get_ref_info (klass))
10890 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10892 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10896 for (i = 0; i < tb->num_methods; ++i) {
10897 MonoReflectionMethodBuilder *mb =
10898 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10899 if (mb->override_method)
10905 *overrides = g_new0 (MonoMethod*, onum * 2);
10908 for (i = 0; i < tb->num_methods; ++i) {
10909 MonoReflectionMethodBuilder *mb =
10910 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10911 if (mb->override_method) {
10912 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10913 (*overrides) [onum * 2 + 1] = mb->mhandle;
10915 g_assert (mb->mhandle);
10922 *num_overrides = onum;
10926 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10928 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10929 MonoReflectionFieldBuilder *fb;
10930 MonoClassField *field;
10931 MonoImage *image = klass->image;
10932 const char *p, *p2;
10934 guint32 len, idx, real_size = 0;
10936 klass->field.count = tb->num_fields;
10937 klass->field.first = 0;
10939 mono_error_init (error);
10941 if (tb->class_size) {
10942 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10943 klass->packing_size = tb->packing_size;
10944 real_size = klass->instance_size + tb->class_size;
10947 if (!klass->field.count) {
10948 klass->instance_size = MAX (klass->instance_size, real_size);
10952 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10953 mono_class_alloc_ext (klass);
10954 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10956 This is, guess what, a hack.
10957 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10958 On the static path no field class is resolved, only types are built. This is the right thing to do
10960 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10962 klass->size_inited = 1;
10964 for (i = 0; i < klass->field.count; ++i) {
10965 fb = mono_array_get (tb->fields, gpointer, i);
10966 field = &klass->fields [i];
10967 field->name = mono_string_to_utf8_image (image, fb->name, error);
10968 if (!mono_error_ok (error))
10971 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10972 field->type->attrs = fb->attrs;
10974 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10976 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10977 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10978 if (fb->offset != -1)
10979 field->offset = fb->offset;
10980 field->parent = klass;
10981 fb->handle = field;
10982 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10984 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10985 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10987 if (fb->def_value) {
10988 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10989 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10990 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10991 /* Copy the data from the blob since it might get realloc-ed */
10992 p = assembly->blob.data + idx;
10993 len = mono_metadata_decode_blob_size (p, &p2);
10995 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10996 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
11000 klass->instance_size = MAX (klass->instance_size, real_size);
11001 mono_class_layout_fields (klass);
11005 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
11007 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11008 MonoReflectionPropertyBuilder *pb;
11009 MonoImage *image = klass->image;
11010 MonoProperty *properties;
11013 mono_error_init (error);
11016 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11018 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
11019 klass->ext->property.first = 0;
11021 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
11022 klass->ext->properties = properties;
11023 for (i = 0; i < klass->ext->property.count; ++i) {
11024 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
11025 properties [i].parent = klass;
11026 properties [i].attrs = pb->attrs;
11027 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
11028 if (!mono_error_ok (error))
11030 if (pb->get_method)
11031 properties [i].get = pb->get_method->mhandle;
11032 if (pb->set_method)
11033 properties [i].set = pb->set_method->mhandle;
11035 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
11036 if (pb->def_value) {
11038 const char *p, *p2;
11039 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
11040 if (!klass->ext->prop_def_values)
11041 klass->ext->prop_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->ext->property.count);
11042 properties [i].attrs |= PROPERTY_ATTRIBUTE_HAS_DEFAULT;
11043 idx = encode_constant (assembly, pb->def_value, &klass->ext->prop_def_values [i].def_type);
11044 /* Copy the data from the blob since it might get realloc-ed */
11045 p = assembly->blob.data + idx;
11046 len = mono_metadata_decode_blob_size (p, &p2);
11048 klass->ext->prop_def_values [i].data = mono_image_alloc (image, len);
11049 memcpy ((gpointer)klass->ext->prop_def_values [i].data, p, len);
11054 MonoReflectionEvent *
11055 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11057 MonoEvent *event = g_new0 (MonoEvent, 1);
11060 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11062 event->parent = klass;
11063 event->attrs = eb->attrs;
11064 event->name = mono_string_to_utf8 (eb->name);
11065 if (eb->add_method)
11066 event->add = eb->add_method->mhandle;
11067 if (eb->remove_method)
11068 event->remove = eb->remove_method->mhandle;
11069 if (eb->raise_method)
11070 event->raise = eb->raise_method->mhandle;
11072 #ifndef MONO_SMALL_CONFIG
11073 if (eb->other_methods) {
11075 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
11076 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11077 MonoReflectionMethodBuilder *mb =
11078 mono_array_get (eb->other_methods,
11079 MonoReflectionMethodBuilder*, j);
11080 event->other [j] = mb->mhandle;
11085 return mono_event_get_object (mono_object_domain (tb), klass, event);
11089 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11091 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11092 MonoReflectionEventBuilder *eb;
11093 MonoImage *image = klass->image;
11097 mono_error_init (error);
11100 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11102 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11103 klass->ext->event.first = 0;
11105 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11106 klass->ext->events = events;
11107 for (i = 0; i < klass->ext->event.count; ++i) {
11108 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11109 events [i].parent = klass;
11110 events [i].attrs = eb->attrs;
11111 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11112 if (!mono_error_ok (error))
11114 if (eb->add_method)
11115 events [i].add = eb->add_method->mhandle;
11116 if (eb->remove_method)
11117 events [i].remove = eb->remove_method->mhandle;
11118 if (eb->raise_method)
11119 events [i].raise = eb->raise_method->mhandle;
11121 #ifndef MONO_SMALL_CONFIG
11122 if (eb->other_methods) {
11124 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11125 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11126 MonoReflectionMethodBuilder *mb =
11127 mono_array_get (eb->other_methods,
11128 MonoReflectionMethodBuilder*, j);
11129 events [i].other [j] = mb->mhandle;
11133 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11138 remove_instantiations_of_and_ensure_contents (gpointer key,
11140 gpointer user_data)
11142 MonoType *type = (MonoType*)key;
11143 MonoClass *klass = (MonoClass*)user_data;
11145 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11146 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11153 check_array_for_usertypes (MonoArray *arr)
11160 for (i = 0; i < mono_array_length (arr); ++i)
11161 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11164 MonoReflectionType*
11165 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11169 MonoDomain* domain;
11170 MonoReflectionType* res;
11173 MONO_ARCH_SAVE_REGS;
11175 domain = mono_object_domain (tb);
11176 klass = mono_class_from_mono_type (tb->type.type);
11179 * Check for user defined Type subclasses.
11181 RESOLVE_TYPE (tb->parent);
11182 check_array_for_usertypes (tb->interfaces);
11184 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11185 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11187 RESOLVE_TYPE (fb->type);
11188 check_array_for_usertypes (fb->modreq);
11189 check_array_for_usertypes (fb->modopt);
11190 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11191 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11196 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11197 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11199 RESOLVE_TYPE (mb->rtype);
11200 check_array_for_usertypes (mb->return_modreq);
11201 check_array_for_usertypes (mb->return_modopt);
11202 check_array_for_usertypes (mb->parameters);
11203 if (mb->param_modreq)
11204 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11205 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11206 if (mb->param_modopt)
11207 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11208 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11213 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11214 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11216 check_array_for_usertypes (mb->parameters);
11217 if (mb->param_modreq)
11218 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11219 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11220 if (mb->param_modopt)
11221 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11222 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11227 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11230 * we need to lock the domain because the lock will be taken inside
11231 * So, we need to keep the locking order correct.
11233 mono_loader_lock ();
11234 mono_domain_lock (domain);
11235 if (klass->wastypebuilder) {
11236 mono_domain_unlock (domain);
11237 mono_loader_unlock ();
11238 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11241 * Fields to set in klass:
11242 * the various flags: delegate/unicode/contextbound etc.
11244 klass->flags = tb->attrs;
11245 klass->has_cctor = 1;
11246 klass->has_finalize = 1;
11247 klass->has_finalize_inited = 1;
11249 /* fool mono_class_setup_parent */
11250 klass->supertypes = NULL;
11251 mono_class_setup_parent (klass, klass->parent);
11252 mono_class_setup_mono_type (klass);
11255 if (!((MonoDynamicImage*)klass->image)->run) {
11256 if (klass->generic_container) {
11257 /* FIXME: The code below can't handle generic classes */
11258 klass->wastypebuilder = TRUE;
11259 mono_loader_unlock ();
11260 mono_domain_unlock (domain);
11261 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11266 /* enums are done right away */
11267 if (!klass->enumtype)
11268 ensure_runtime_vtable (klass);
11270 if (tb->subtypes) {
11271 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11272 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11273 mono_class_alloc_ext (klass);
11274 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)));
11278 klass->nested_classes_inited = TRUE;
11280 /* fields and object layout */
11281 if (klass->parent) {
11282 if (!klass->parent->size_inited)
11283 mono_class_init (klass->parent);
11284 klass->instance_size = klass->parent->instance_size;
11285 klass->sizes.class_size = 0;
11286 klass->min_align = klass->parent->min_align;
11287 /* if the type has no fields we won't call the field_setup
11288 * routine which sets up klass->has_references.
11290 klass->has_references |= klass->parent->has_references;
11292 klass->instance_size = sizeof (MonoObject);
11293 klass->min_align = 1;
11296 /* FIXME: handle packing_size and instance_size */
11297 typebuilder_setup_fields (klass, &error);
11298 if (!mono_error_ok (&error))
11300 typebuilder_setup_properties (klass, &error);
11301 if (!mono_error_ok (&error))
11304 typebuilder_setup_events (klass, &error);
11305 if (!mono_error_ok (&error))
11308 klass->wastypebuilder = TRUE;
11311 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11312 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11313 * we want to return normal System.MonoType objects, so clear these out from the cache.
11315 * Together with this we must ensure the contents of all instances to match the created type.
11317 if (domain->type_hash && klass->generic_container)
11318 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11320 mono_domain_unlock (domain);
11321 mono_loader_unlock ();
11323 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11324 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11325 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11328 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11329 g_assert (res != (MonoReflectionType*)tb);
11334 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11335 klass->wastypebuilder = TRUE;
11336 mono_domain_unlock (domain);
11337 mono_loader_unlock ();
11338 mono_error_raise_exception (&error);
11343 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11345 MonoGenericParamFull *param;
11350 MONO_ARCH_SAVE_REGS;
11352 image = &gparam->tbuilder->module->dynamic_image->image;
11354 param = mono_image_new0 (image, MonoGenericParamFull, 1);
11356 param->info.name = mono_string_to_utf8_image (image, gparam->name, &error);
11357 g_assert (mono_error_ok (&error));
11358 param->param.num = gparam->index;
11360 if (gparam->mbuilder) {
11361 if (!gparam->mbuilder->generic_container) {
11362 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11363 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11364 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11365 gparam->mbuilder->generic_container->is_method = TRUE;
11367 * Cannot set owner.method, since the MonoMethod is not created yet.
11368 * Set the image field instead, so type_in_image () works.
11370 gparam->mbuilder->generic_container->image = klass->image;
11372 param->param.owner = gparam->mbuilder->generic_container;
11373 } else if (gparam->tbuilder) {
11374 if (!gparam->tbuilder->generic_container) {
11375 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11376 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11377 gparam->tbuilder->generic_container->owner.klass = klass;
11379 param->param.owner = gparam->tbuilder->generic_container;
11382 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11384 gparam->type.type = &pklass->byval_arg;
11386 mono_class_set_ref_info (pklass, gparam);
11387 mono_image_lock (image);
11388 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11389 mono_image_unlock (image);
11393 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11395 MonoReflectionModuleBuilder *module = sig->module;
11396 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11397 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11402 check_array_for_usertypes (sig->arguments);
11404 sigbuffer_init (&buf, 32);
11406 sigbuffer_add_value (&buf, 0x07);
11407 sigbuffer_add_value (&buf, na);
11408 if (assembly != NULL){
11409 for (i = 0; i < na; ++i) {
11410 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11411 encode_reflection_type (assembly, type, &buf);
11415 buflen = buf.p - buf.buf;
11416 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11417 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11418 sigbuffer_free (&buf);
11424 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11426 MonoDynamicImage *assembly = sig->module->dynamic_image;
11427 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11432 check_array_for_usertypes (sig->arguments);
11434 sigbuffer_init (&buf, 32);
11436 sigbuffer_add_value (&buf, 0x06);
11437 for (i = 0; i < na; ++i) {
11438 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11439 encode_reflection_type (assembly, type, &buf);
11442 buflen = buf.p - buf.buf;
11443 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11444 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11445 sigbuffer_free (&buf);
11451 MonoMethod *handle;
11452 MonoDomain *domain;
11453 } DynamicMethodReleaseData;
11456 * The runtime automatically clean up those after finalization.
11458 static MonoReferenceQueue *dynamic_method_queue;
11461 free_dynamic_method (void *dynamic_method)
11463 DynamicMethodReleaseData *data = dynamic_method;
11465 mono_runtime_free_method (data->domain, data->handle);
11470 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11472 MonoReferenceQueue *queue;
11473 MonoMethod *handle;
11474 DynamicMethodReleaseData *release_data;
11475 ReflectionMethodBuilder rmb;
11476 MonoMethodSignature *sig;
11481 if (mono_runtime_is_shutting_down ())
11482 mono_raise_exception (mono_get_exception_invalid_operation (""));
11484 if (!(queue = dynamic_method_queue)) {
11485 mono_loader_lock ();
11486 if (!(queue = dynamic_method_queue))
11487 queue = dynamic_method_queue = mono_gc_reference_queue_new (free_dynamic_method);
11488 mono_loader_unlock ();
11491 sig = dynamic_method_to_signature (mb);
11493 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11496 * Resolve references.
11499 * Every second entry in the refs array is reserved for storing handle_class,
11500 * which is needed by the ldtoken implementation in the JIT.
11502 rmb.nrefs = mb->nrefs;
11503 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11504 for (i = 0; i < mb->nrefs; i += 2) {
11505 MonoClass *handle_class;
11507 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11509 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11510 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11512 * The referenced DynamicMethod should already be created by the managed
11513 * code, except in the case of circular references. In that case, we store
11514 * method in the refs array, and fix it up later when the referenced
11515 * DynamicMethod is created.
11517 if (method->mhandle) {
11518 ref = method->mhandle;
11520 /* FIXME: GC object stored in unmanaged memory */
11523 /* FIXME: GC object stored in unmanaged memory */
11524 method->referenced_by = g_slist_append (method->referenced_by, mb);
11526 handle_class = mono_defaults.methodhandle_class;
11528 MonoException *ex = NULL;
11529 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11531 ex = mono_get_exception_type_load (NULL, NULL);
11532 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11533 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11537 mono_raise_exception (ex);
11542 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11543 rmb.refs [i + 1] = handle_class;
11546 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11548 mb->mhandle = handle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11549 release_data = g_new (DynamicMethodReleaseData, 1);
11550 release_data->handle = handle;
11551 release_data->domain = mono_object_get_domain ((MonoObject*)mb);
11552 if (!mono_gc_reference_queue_add (queue, (MonoObject*)mb, release_data))
11553 g_free (release_data);
11555 /* Fix up refs entries pointing at us */
11556 for (l = mb->referenced_by; l; l = l->next) {
11557 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11558 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11561 g_assert (method->mhandle);
11563 data = (gpointer*)wrapper->method_data;
11564 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11565 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11566 data [i + 1] = mb->mhandle;
11569 g_slist_free (mb->referenced_by);
11573 /* ilgen is no longer needed */
11577 #endif /* DISABLE_REFLECTION_EMIT */
11581 * mono_reflection_is_valid_dynamic_token:
11583 * Returns TRUE if token is valid.
11587 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11589 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11592 MonoMethodSignature *
11593 mono_reflection_lookup_signature (MonoImage *image, MonoMethod *method, guint32 token)
11595 MonoMethodSignature *sig;
11596 g_assert (image->dynamic);
11598 sig = g_hash_table_lookup (((MonoDynamicImage*)image)->vararg_aux_hash, GUINT_TO_POINTER (token));
11602 return mono_method_signature (method);
11605 #ifndef DISABLE_REFLECTION_EMIT
11608 * mono_reflection_lookup_dynamic_token:
11610 * Finish the Builder object pointed to by TOKEN and return the corresponding
11611 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11612 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11615 * LOCKING: Take the loader lock
11618 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11620 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11624 mono_loader_lock ();
11625 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11626 mono_loader_unlock ();
11629 g_error ("Could not find required dynamic token 0x%08x", token);
11635 handle_class = &klass;
11636 return resolve_object (image, obj, handle_class, context);
11640 * ensure_complete_type:
11642 * Ensure that KLASS is completed if it is a dynamic type, or references
11646 ensure_complete_type (MonoClass *klass)
11648 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11649 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11651 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11653 // Asserting here could break a lot of code
11654 //g_assert (klass->wastypebuilder);
11657 if (klass->generic_class) {
11658 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11661 for (i = 0; i < inst->type_argc; ++i) {
11662 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11668 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11670 gpointer result = NULL;
11672 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11673 result = mono_string_intern ((MonoString*)obj);
11674 *handle_class = mono_defaults.string_class;
11676 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11677 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11678 MonoClass *mc = mono_class_from_mono_type (type);
11679 if (!mono_class_init (mc))
11680 mono_raise_exception (mono_class_get_exception_for_failure (mc));
11683 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11684 result = mono_class_from_mono_type (inflated);
11685 mono_metadata_free_type (inflated);
11687 result = mono_class_from_mono_type (type);
11689 *handle_class = mono_defaults.typehandle_class;
11691 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11692 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11693 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11694 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11695 result = ((MonoReflectionMethod*)obj)->method;
11697 result = mono_class_inflate_generic_method (result, context);
11698 *handle_class = mono_defaults.methodhandle_class;
11700 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11701 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11702 result = mb->mhandle;
11704 /* Type is not yet created */
11705 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11707 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11710 * Hopefully this has been filled in by calling CreateType() on the
11714 * TODO: This won't work if the application finishes another
11715 * TypeBuilder instance instead of this one.
11717 result = mb->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, "ConstructorBuilder") == 0) {
11723 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11725 result = cb->mhandle;
11727 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11729 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11730 result = cb->mhandle;
11733 result = mono_class_inflate_generic_method (result, context);
11734 *handle_class = mono_defaults.methodhandle_class;
11735 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11736 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11738 ensure_complete_type (field->parent);
11740 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11741 MonoClass *class = mono_class_from_mono_type (inflated);
11742 MonoClassField *inflated_field;
11743 gpointer iter = NULL;
11744 mono_metadata_free_type (inflated);
11745 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11746 if (!strcmp (field->name, inflated_field->name))
11749 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11750 result = inflated_field;
11754 *handle_class = mono_defaults.fieldhandle_class;
11756 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11757 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11758 result = fb->handle;
11761 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11763 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11764 result = fb->handle;
11767 if (fb->handle && fb->handle->parent->generic_container) {
11768 MonoClass *klass = fb->handle->parent;
11769 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11770 MonoClass *inflated = mono_class_from_mono_type (type);
11772 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11774 mono_metadata_free_type (type);
11776 *handle_class = mono_defaults.fieldhandle_class;
11777 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11778 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11779 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11782 klass = type->data.klass;
11783 if (klass->wastypebuilder) {
11784 /* Already created */
11788 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11789 result = type->data.klass;
11792 *handle_class = mono_defaults.typehandle_class;
11793 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11794 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11795 MonoMethodSignature *sig;
11798 if (helper->arguments)
11799 nargs = mono_array_length (helper->arguments);
11803 sig = mono_metadata_signature_alloc (image, nargs);
11804 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11805 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11807 if (helper->unmanaged_call_conv) { /* unmanaged */
11808 sig->call_convention = helper->unmanaged_call_conv - 1;
11809 sig->pinvoke = TRUE;
11810 } else if (helper->call_conv & 0x02) {
11811 sig->call_convention = MONO_CALL_VARARG;
11813 sig->call_convention = MONO_CALL_DEFAULT;
11816 sig->param_count = nargs;
11817 /* TODO: Copy type ? */
11818 sig->ret = helper->return_type->type;
11819 for (i = 0; i < nargs; ++i)
11820 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11823 *handle_class = NULL;
11824 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11825 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11826 /* Already created by the managed code */
11827 g_assert (method->mhandle);
11828 result = method->mhandle;
11829 *handle_class = mono_defaults.methodhandle_class;
11830 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11831 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11832 type = mono_class_inflate_generic_type (type, context);
11833 result = mono_class_from_mono_type (type);
11834 *handle_class = mono_defaults.typehandle_class;
11836 mono_metadata_free_type (type);
11837 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11838 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11839 type = mono_class_inflate_generic_type (type, context);
11840 result = mono_class_from_mono_type (type);
11841 *handle_class = mono_defaults.typehandle_class;
11843 mono_metadata_free_type (type);
11844 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11845 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11846 MonoClass *inflated;
11848 MonoClassField *field;
11850 if (is_sre_field_builder (mono_object_class (f->fb)))
11851 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11852 else if (is_sr_mono_field (mono_object_class (f->fb)))
11853 field = ((MonoReflectionField*)f->fb)->field;
11855 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)));
11857 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11858 inflated = mono_class_from_mono_type (type);
11860 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11861 ensure_complete_type (field->parent);
11863 mono_metadata_free_type (type);
11864 *handle_class = mono_defaults.fieldhandle_class;
11865 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11866 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11867 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11868 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11869 MonoMethod *method;
11871 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11872 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11873 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11874 method = ((MonoReflectionMethod *)c->cb)->method;
11876 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)));
11878 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11879 *handle_class = mono_defaults.methodhandle_class;
11880 mono_metadata_free_type (type);
11881 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11882 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11883 if (m->method_args) {
11884 result = mono_reflection_method_on_tb_inst_get_handle (m);
11886 result = mono_class_inflate_generic_method (result, context);
11888 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11889 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11890 MonoMethod *method;
11892 if (is_sre_method_builder (mono_object_class (m->mb)))
11893 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11894 else if (is_sr_mono_method (mono_object_class (m->mb)))
11895 method = ((MonoReflectionMethod *)m->mb)->method;
11897 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)));
11899 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11900 mono_metadata_free_type (type);
11902 *handle_class = mono_defaults.methodhandle_class;
11903 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11904 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11907 MonoMethod *method;
11911 mtype = mono_reflection_type_get_handle (m->parent);
11912 klass = mono_class_from_mono_type (mtype);
11914 /* Find the method */
11916 name = mono_string_to_utf8 (m->name);
11918 while ((method = mono_class_get_methods (klass, &iter))) {
11919 if (!strcmp (method->name, name))
11926 // FIXME: Check parameters/return value etc. match
11929 *handle_class = mono_defaults.methodhandle_class;
11930 } else if (is_sre_array (mono_object_get_class(obj)) ||
11931 is_sre_byref (mono_object_get_class(obj)) ||
11932 is_sre_pointer (mono_object_get_class(obj))) {
11933 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11934 MonoType *type = mono_reflection_type_get_handle (ref_type);
11935 result = mono_class_from_mono_type (type);
11936 *handle_class = mono_defaults.typehandle_class;
11938 g_print ("%s\n", obj->vtable->klass->name);
11939 g_assert_not_reached ();
11944 #else /* DISABLE_REFLECTION_EMIT */
11947 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11949 g_assert_not_reached ();
11954 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11956 g_assert_not_reached ();
11960 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11962 g_assert_not_reached ();
11966 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11968 g_assert_not_reached ();
11972 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11974 g_assert_not_reached ();
11978 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11980 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11984 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11986 g_assert_not_reached ();
11990 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11992 g_assert_not_reached ();
11995 MonoReflectionModule *
11996 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11998 g_assert_not_reached ();
12003 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
12005 g_assert_not_reached ();
12010 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
12012 g_assert_not_reached ();
12017 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
12018 gboolean create_open_instance, gboolean register_token)
12020 g_assert_not_reached ();
12025 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
12030 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
12031 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
12034 g_assert_not_reached ();
12038 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
12041 *num_overrides = 0;
12044 MonoReflectionEvent *
12045 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
12047 g_assert_not_reached ();
12051 MonoReflectionType*
12052 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
12054 g_assert_not_reached ();
12059 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
12061 g_assert_not_reached ();
12065 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
12067 g_assert_not_reached ();
12072 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
12074 g_assert_not_reached ();
12079 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
12084 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
12090 mono_reflection_type_get_handle (MonoReflectionType* ref)
12098 mono_reflection_free_dynamic_generic_class (MonoGenericClass *gclass)
12100 g_assert_not_reached ();
12103 #endif /* DISABLE_REFLECTION_EMIT */
12105 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
12106 const static guint32 declsec_flags_map[] = {
12107 0x00000000, /* empty */
12108 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
12109 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
12110 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
12111 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
12112 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
12113 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
12114 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
12115 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
12116 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
12117 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
12118 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
12119 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
12120 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
12121 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
12122 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
12123 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
12124 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
12125 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
12129 * Returns flags that includes all available security action associated to the handle.
12130 * @token: metadata token (either for a class or a method)
12131 * @image: image where resides the metadata.
12134 mono_declsec_get_flags (MonoImage *image, guint32 token)
12136 int index = mono_metadata_declsec_from_index (image, token);
12137 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12138 guint32 result = 0;
12142 /* HasSecurity can be present for other, not specially encoded, attributes,
12143 e.g. SuppressUnmanagedCodeSecurityAttribute */
12147 for (i = index; i < t->rows; i++) {
12148 guint32 cols [MONO_DECL_SECURITY_SIZE];
12150 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12151 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12154 action = cols [MONO_DECL_SECURITY_ACTION];
12155 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12156 result |= declsec_flags_map [action];
12158 g_assert_not_reached ();
12165 * Get the security actions (in the form of flags) associated with the specified method.
12167 * @method: The method for which we want the declarative security flags.
12168 * Return the declarative security flags for the method (only).
12170 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12171 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12174 mono_declsec_flags_from_method (MonoMethod *method)
12176 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12177 /* FIXME: No cache (for the moment) */
12178 guint32 idx = mono_method_get_index (method);
12179 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12180 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12181 return mono_declsec_get_flags (method->klass->image, idx);
12187 * Get the security actions (in the form of flags) associated with the specified class.
12189 * @klass: The class for which we want the declarative security flags.
12190 * Return the declarative security flags for the class.
12192 * Note: We cache the flags inside the MonoClass structure as this will get
12193 * called very often (at least for each method).
12196 mono_declsec_flags_from_class (MonoClass *klass)
12198 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12199 if (!klass->ext || !klass->ext->declsec_flags) {
12202 idx = mono_metadata_token_index (klass->type_token);
12203 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12204 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12205 mono_loader_lock ();
12206 mono_class_alloc_ext (klass);
12207 mono_loader_unlock ();
12208 /* we cache the flags on classes */
12209 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12211 return klass->ext->declsec_flags;
12217 * Get the security actions (in the form of flags) associated with the specified assembly.
12219 * @assembly: The assembly for which we want the declarative security flags.
12220 * Return the declarative security flags for the assembly.
12223 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12225 guint32 idx = 1; /* there is only one assembly */
12226 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12227 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12228 return mono_declsec_get_flags (assembly->image, idx);
12233 * Fill actions for the specific index (which may either be an encoded class token or
12234 * an encoded method token) from the metadata image.
12235 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12238 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12239 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12241 MonoBoolean result = FALSE;
12243 guint32 cols [MONO_DECL_SECURITY_SIZE];
12244 int index = mono_metadata_declsec_from_index (image, token);
12247 t = &image->tables [MONO_TABLE_DECLSECURITY];
12248 for (i = index; i < t->rows; i++) {
12249 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12251 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12254 /* if present only replace (class) permissions with method permissions */
12255 /* if empty accept either class or method permissions */
12256 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12257 if (!actions->demand.blob) {
12258 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12259 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12260 actions->demand.blob = (char*) (blob + 2);
12261 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12264 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12265 if (!actions->noncasdemand.blob) {
12266 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12267 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12268 actions->noncasdemand.blob = (char*) (blob + 2);
12269 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12272 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12273 if (!actions->demandchoice.blob) {
12274 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12275 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12276 actions->demandchoice.blob = (char*) (blob + 2);
12277 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12287 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12288 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12290 guint32 idx = mono_metadata_token_index (klass->type_token);
12291 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12292 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12293 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12297 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12298 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12300 guint32 idx = mono_method_get_index (method);
12301 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12302 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12303 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12307 * Collect all actions (that requires to generate code in mini) assigned for
12308 * the specified method.
12309 * Note: Don't use the content of actions if the function return FALSE.
12312 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12314 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12315 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12316 MonoBoolean result = FALSE;
12319 /* quick exit if no declarative security is present in the metadata */
12320 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12323 /* we want the original as the wrapper is "free" of the security informations */
12324 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12325 method = mono_marshal_method_from_wrapper (method);
12330 /* First we look for method-level attributes */
12331 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12332 mono_class_init (method->klass);
12333 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12335 result = mono_declsec_get_method_demands_params (method, demands,
12336 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12339 /* Here we use (or create) the class declarative cache to look for demands */
12340 flags = mono_declsec_flags_from_class (method->klass);
12341 if (flags & mask) {
12343 mono_class_init (method->klass);
12344 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12346 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12347 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12350 /* The boolean return value is used as a shortcut in case nothing needs to
12351 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12357 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12359 * Note: Don't use the content of actions if the function return FALSE.
12362 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12364 MonoBoolean result = FALSE;
12367 /* quick exit if no declarative security is present in the metadata */
12368 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12371 /* we want the original as the wrapper is "free" of the security informations */
12372 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12373 method = mono_marshal_method_from_wrapper (method);
12378 /* results are independant - zeroize both */
12379 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12380 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12382 /* First we look for method-level attributes */
12383 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12384 mono_class_init (method->klass);
12386 result = mono_declsec_get_method_demands_params (method, cmethod,
12387 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12390 /* Here we use (or create) the class declarative cache to look for demands */
12391 flags = mono_declsec_flags_from_class (method->klass);
12392 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12393 mono_class_init (method->klass);
12395 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12396 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12403 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12405 * @klass The inherited class - this is the class that provides the security check (attributes)
12407 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12409 * Note: Don't use the content of actions if the function return FALSE.
12412 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12414 MonoBoolean result = FALSE;
12417 /* quick exit if no declarative security is present in the metadata */
12418 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12421 /* Here we use (or create) the class declarative cache to look for demands */
12422 flags = mono_declsec_flags_from_class (klass);
12423 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12424 mono_class_init (klass);
12425 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12427 result |= mono_declsec_get_class_demands_params (klass, demands,
12428 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12435 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12437 * Note: Don't use the content of actions if the function return FALSE.
12440 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12442 /* quick exit if no declarative security is present in the metadata */
12443 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12446 /* we want the original as the wrapper is "free" of the security informations */
12447 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12448 method = mono_marshal_method_from_wrapper (method);
12453 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12454 mono_class_init (method->klass);
12455 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12457 return mono_declsec_get_method_demands_params (method, demands,
12458 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12465 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12467 guint32 cols [MONO_DECL_SECURITY_SIZE];
12471 int index = mono_metadata_declsec_from_index (image, token);
12475 t = &image->tables [MONO_TABLE_DECLSECURITY];
12476 for (i = index; i < t->rows; i++) {
12477 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12479 /* shortcut - index are ordered */
12480 if (token != cols [MONO_DECL_SECURITY_PARENT])
12483 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12484 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12485 entry->blob = (char*) (metadata + 2);
12486 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12495 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12497 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12498 guint32 idx = mono_method_get_index (method);
12499 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12500 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12501 return get_declsec_action (method->klass->image, idx, action, entry);
12507 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12510 guint32 flags = mono_declsec_flags_from_class (klass);
12511 if (declsec_flags_map [action] & flags) {
12512 guint32 idx = mono_metadata_token_index (klass->type_token);
12513 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12514 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12515 return get_declsec_action (klass->image, idx, action, entry);
12521 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12523 guint32 idx = 1; /* there is only one assembly */
12524 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12525 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12527 return get_declsec_action (assembly->image, idx, action, entry);
12531 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12533 MonoObject *res, *exc;
12535 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12536 static MonoMethod *method = NULL;
12538 if (!System_Reflection_Emit_TypeBuilder) {
12539 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12540 g_assert (System_Reflection_Emit_TypeBuilder);
12542 if (method == NULL) {
12543 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12548 * The result of mono_type_get_object () might be a System.MonoType but we
12549 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12551 g_assert (mono_class_get_ref_info (klass));
12552 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12554 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12556 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12560 return *(MonoBoolean*)mono_object_unbox (res);