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/utils/mono-string.h>
43 #include <mono/utils/mono-error-internals.h>
47 static void* reflection_info_desc = NULL;
48 #define MOVING_GC_REGISTER(addr) do { \
49 if (!reflection_info_desc) { \
51 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
53 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
56 #define MOVING_GC_REGISTER(addr)
59 static gboolean is_usertype (MonoReflectionType *ref);
60 static MonoReflectionType *mono_reflection_type_resolve_user_types (MonoReflectionType *type);
68 #define TEXT_OFFSET 512
69 #define CLI_H_SIZE 136
70 #define FILE_ALIGN 512
71 #define VIRT_ALIGN 8192
72 #define START_TEXT_RVA 0x00002000
75 MonoReflectionILGen *ilgen;
76 MonoReflectionType *rtype;
77 MonoArray *parameters;
78 MonoArray *generic_params;
79 MonoGenericContainer *generic_container;
85 guint32 *table_idx; /* note: it's a pointer */
89 MonoBoolean init_locals;
90 MonoBoolean skip_visibility;
91 MonoArray *return_modreq;
92 MonoArray *return_modopt;
93 MonoArray *param_modreq;
94 MonoArray *param_modopt;
95 MonoArray *permissions;
100 int charset, extra_flags, native_cc;
101 MonoString *dll, *dllentry;
102 } ReflectionMethodBuilder;
106 MonoReflectionGenericParam *gparam;
107 } GenericParamTableEntry;
109 const unsigned char table_sizes [MONO_TABLE_NUM] = {
119 MONO_INTERFACEIMPL_SIZE,
120 MONO_MEMBERREF_SIZE, /* 0x0A */
122 MONO_CUSTOM_ATTR_SIZE,
123 MONO_FIELD_MARSHAL_SIZE,
124 MONO_DECL_SECURITY_SIZE,
125 MONO_CLASS_LAYOUT_SIZE,
126 MONO_FIELD_LAYOUT_SIZE, /* 0x10 */
127 MONO_STAND_ALONE_SIGNATURE_SIZE,
131 MONO_PROPERTY_MAP_SIZE,
134 MONO_METHOD_SEMA_SIZE,
135 MONO_METHODIMPL_SIZE,
136 MONO_MODULEREF_SIZE, /* 0x1A */
142 MONO_ASSEMBLY_SIZE, /* 0x20 */
143 MONO_ASSEMBLY_PROCESSOR_SIZE,
144 MONO_ASSEMBLYOS_SIZE,
145 MONO_ASSEMBLYREF_SIZE,
146 MONO_ASSEMBLYREFPROC_SIZE,
147 MONO_ASSEMBLYREFOS_SIZE,
151 MONO_NESTED_CLASS_SIZE,
153 MONO_GENERICPARAM_SIZE, /* 0x2A */
154 MONO_METHODSPEC_SIZE,
155 MONO_GENPARCONSTRAINT_SIZE
159 #ifndef DISABLE_REFLECTION_EMIT
160 static guint32 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec);
161 static guint32 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec);
162 static guint32 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *cb);
163 static guint32 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper);
164 static void ensure_runtime_vtable (MonoClass *klass);
165 static gpointer resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context);
166 static guint32 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method);
167 static guint32 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context);
168 static gpointer register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly);
169 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb);
170 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb);
171 static guint32 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb);
174 static guint32 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type);
175 static guint32 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec);
176 static void mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly);
177 static guint32 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo);
178 static guint32 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type);
179 static char* type_get_qualified_name (MonoType *type, MonoAssembly *ass);
180 static void encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf);
181 static void get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types);
182 static MonoReflectionType *mono_reflection_type_get_underlying_system_type (MonoReflectionType* t);
183 static MonoType* mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve);
184 static MonoReflectionType* mono_reflection_type_resolve_user_types (MonoReflectionType *type);
185 static gboolean is_sre_array (MonoClass *class);
186 static gboolean is_sre_byref (MonoClass *class);
187 static gboolean is_sre_pointer (MonoClass *class);
188 static gboolean is_sre_type_builder (MonoClass *class);
189 static gboolean is_sre_method_builder (MonoClass *class);
190 static gboolean is_sre_ctor_builder (MonoClass *class);
191 static gboolean is_sre_field_builder (MonoClass *class);
192 static gboolean is_sr_mono_method (MonoClass *class);
193 static gboolean is_sr_mono_cmethod (MonoClass *class);
194 static gboolean is_sr_mono_generic_method (MonoClass *class);
195 static gboolean is_sr_mono_generic_cmethod (MonoClass *class);
196 static gboolean is_sr_mono_field (MonoClass *class);
197 static gboolean is_sr_mono_property (MonoClass *class);
198 static gboolean is_sre_method_on_tb_inst (MonoClass *class);
199 static gboolean is_sre_ctor_on_tb_inst (MonoClass *class);
201 static guint32 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method);
202 static guint32 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m);
203 static MonoMethod * inflate_method (MonoReflectionType *type, MonoObject *obj);
205 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
206 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
207 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
208 __type = mono_reflection_type_resolve_user_types (__type); \
209 mono_array_set (arr, MonoReflectionType*, index, __type); \
212 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
215 mono_reflection_init (void)
220 sigbuffer_init (SigBuffer *buf, int size)
222 buf->buf = g_malloc (size);
224 buf->end = buf->buf + size;
228 sigbuffer_make_room (SigBuffer *buf, int size)
230 if (buf->end - buf->p < size) {
231 int new_size = buf->end - buf->buf + size + 32;
232 char *p = g_realloc (buf->buf, new_size);
233 size = buf->p - buf->buf;
236 buf->end = buf->buf + new_size;
241 sigbuffer_add_value (SigBuffer *buf, guint32 val)
243 sigbuffer_make_room (buf, 6);
244 mono_metadata_encode_value (val, buf->p, &buf->p);
248 sigbuffer_add_byte (SigBuffer *buf, guint8 val)
250 sigbuffer_make_room (buf, 1);
256 sigbuffer_add_mem (SigBuffer *buf, char *p, guint32 size)
258 sigbuffer_make_room (buf, size);
259 memcpy (buf->p, p, size);
264 sigbuffer_free (SigBuffer *buf)
269 #ifndef DISABLE_REFLECTION_EMIT
273 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
277 image_g_malloc (MonoImage *image, guint size)
280 return mono_image_alloc (image, size);
282 return g_malloc (size);
284 #endif /* !DISABLE_REFLECTION_EMIT */
289 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
293 image_g_malloc0 (MonoImage *image, guint size)
296 return mono_image_alloc0 (image, size);
298 return g_malloc0 (size);
301 #ifndef DISABLE_REFLECTION_EMIT
303 image_strdup (MonoImage *image, const char *s)
306 return mono_image_strdup (image, s);
312 #define image_g_new(image,struct_type, n_structs) \
313 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
315 #define image_g_new0(image,struct_type, n_structs) \
316 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
320 alloc_table (MonoDynamicTable *table, guint nrows)
323 g_assert (table->columns);
324 if (nrows + 1 >= table->alloc_rows) {
325 while (nrows + 1 >= table->alloc_rows) {
326 if (table->alloc_rows == 0)
327 table->alloc_rows = 16;
329 table->alloc_rows *= 2;
332 table->values = g_renew (guint32, table->values, (table->alloc_rows) * table->columns);
337 make_room_in_stream (MonoDynamicStream *stream, int size)
339 if (size <= stream->alloc_size)
342 while (stream->alloc_size <= size) {
343 if (stream->alloc_size < 4096)
344 stream->alloc_size = 4096;
346 stream->alloc_size *= 2;
349 stream->data = g_realloc (stream->data, stream->alloc_size);
353 string_heap_insert (MonoDynamicStream *sh, const char *str)
357 gpointer oldkey, oldval;
359 if (g_hash_table_lookup_extended (sh->hash, str, &oldkey, &oldval))
360 return GPOINTER_TO_UINT (oldval);
362 len = strlen (str) + 1;
365 make_room_in_stream (sh, idx + len);
368 * We strdup the string even if we already copy them in sh->data
369 * so that the string pointers in the hash remain valid even if
370 * we need to realloc sh->data. We may want to avoid that later.
372 g_hash_table_insert (sh->hash, g_strdup (str), GUINT_TO_POINTER (idx));
373 memcpy (sh->data + idx, str, len);
379 string_heap_insert_mstring (MonoDynamicStream *sh, MonoString *str)
381 char *name = mono_string_to_utf8 (str);
383 idx = string_heap_insert (sh, name);
388 #ifndef DISABLE_REFLECTION_EMIT
390 string_heap_init (MonoDynamicStream *sh)
393 sh->alloc_size = 4096;
394 sh->data = g_malloc (4096);
395 sh->hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
396 string_heap_insert (sh, "");
401 mono_image_add_stream_data (MonoDynamicStream *stream, const char *data, guint32 len)
405 make_room_in_stream (stream, stream->index + len);
406 memcpy (stream->data + stream->index, data, len);
408 stream->index += len;
410 * align index? Not without adding an additional param that controls it since
411 * we may store a blob value in pieces.
417 mono_image_add_stream_zero (MonoDynamicStream *stream, guint32 len)
421 make_room_in_stream (stream, stream->index + len);
422 memset (stream->data + stream->index, 0, len);
424 stream->index += len;
429 stream_data_align (MonoDynamicStream *stream)
432 guint32 count = stream->index % 4;
434 /* we assume the stream data will be aligned */
436 mono_image_add_stream_data (stream, buf, 4 - count);
439 #ifndef DISABLE_REFLECTION_EMIT
441 mono_blob_entry_hash (const char* str)
445 len = mono_metadata_decode_blob_size (str, &str);
449 for (str += 1; str < end; str++)
450 h = (h << 5) - h + *str;
458 mono_blob_entry_equal (const char *str1, const char *str2) {
462 len = mono_metadata_decode_blob_size (str1, &end1);
463 len2 = mono_metadata_decode_blob_size (str2, &end2);
466 return memcmp (end1, end2, len) == 0;
470 add_to_blob_cached (MonoDynamicImage *assembly, char *b1, int s1, char *b2, int s2)
474 gpointer oldkey, oldval;
476 copy = g_malloc (s1+s2);
477 memcpy (copy, b1, s1);
478 memcpy (copy + s1, b2, s2);
479 if (g_hash_table_lookup_extended (assembly->blob_cache, copy, &oldkey, &oldval)) {
481 idx = GPOINTER_TO_UINT (oldval);
483 idx = mono_image_add_stream_data (&assembly->blob, b1, s1);
484 mono_image_add_stream_data (&assembly->blob, b2, s2);
485 g_hash_table_insert (assembly->blob_cache, copy, GUINT_TO_POINTER (idx));
491 sigbuffer_add_to_blob_cached (MonoDynamicImage *assembly, SigBuffer *buf)
495 guint32 size = buf->p - buf->buf;
497 g_assert (size <= (buf->end - buf->buf));
498 mono_metadata_encode_value (size, b, &b);
499 return add_to_blob_cached (assembly, blob_size, b-blob_size, buf->buf, size);
503 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
504 * dest may be misaligned.
507 swap_with_size (char *dest, const char* val, int len, int nelem) {
508 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
511 for (elem = 0; elem < nelem; ++elem) {
537 g_assert_not_reached ();
543 memcpy (dest, val, len * nelem);
548 add_mono_string_to_blob_cached (MonoDynamicImage *assembly, MonoString *str)
552 guint32 idx = 0, len;
554 len = str->length * 2;
555 mono_metadata_encode_value (len, b, &b);
556 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
558 char *swapped = g_malloc (2 * mono_string_length (str));
559 const char *p = (const char*)mono_string_chars (str);
561 swap_with_size (swapped, p, 2, mono_string_length (str));
562 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
566 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
571 #ifndef DISABLE_REFLECTION_EMIT
573 default_class_from_mono_type (MonoType *type)
575 switch (type->type) {
576 case MONO_TYPE_OBJECT:
577 return mono_defaults.object_class;
579 return mono_defaults.void_class;
580 case MONO_TYPE_BOOLEAN:
581 return mono_defaults.boolean_class;
583 return mono_defaults.char_class;
585 return mono_defaults.sbyte_class;
587 return mono_defaults.byte_class;
589 return mono_defaults.int16_class;
591 return mono_defaults.uint16_class;
593 return mono_defaults.int32_class;
595 return mono_defaults.uint32_class;
597 return mono_defaults.int_class;
599 return mono_defaults.uint_class;
601 return mono_defaults.int64_class;
603 return mono_defaults.uint64_class;
605 return mono_defaults.single_class;
607 return mono_defaults.double_class;
608 case MONO_TYPE_STRING:
609 return mono_defaults.string_class;
611 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type->type);
612 g_assert_not_reached ();
620 * mono_class_get_ref_info:
622 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
625 mono_class_get_ref_info (MonoClass *klass)
627 if (klass->ref_info_handle == 0)
630 return mono_gchandle_get_target (klass->ref_info_handle);
634 mono_class_set_ref_info (MonoClass *klass, gpointer obj)
636 klass->ref_info_handle = mono_gchandle_new ((MonoObject*)obj, FALSE);
637 g_assert (klass->ref_info_handle != 0);
641 mono_class_free_ref_info (MonoClass *klass)
643 if (klass->ref_info_handle) {
644 mono_gchandle_free (klass->ref_info_handle);
645 klass->ref_info_handle = 0;
650 encode_generic_class (MonoDynamicImage *assembly, MonoGenericClass *gclass, SigBuffer *buf)
653 MonoGenericInst *class_inst;
658 class_inst = gclass->context.class_inst;
660 sigbuffer_add_value (buf, MONO_TYPE_GENERICINST);
661 klass = gclass->container_class;
662 sigbuffer_add_value (buf, klass->byval_arg.type);
663 sigbuffer_add_value (buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
665 sigbuffer_add_value (buf, class_inst->type_argc);
666 for (i = 0; i < class_inst->type_argc; ++i)
667 encode_type (assembly, class_inst->type_argv [i], buf);
672 encode_type (MonoDynamicImage *assembly, MonoType *type, SigBuffer *buf)
675 g_assert_not_reached ();
680 sigbuffer_add_value (buf, MONO_TYPE_BYREF);
684 case MONO_TYPE_BOOLEAN:
698 case MONO_TYPE_STRING:
699 case MONO_TYPE_OBJECT:
700 case MONO_TYPE_TYPEDBYREF:
701 sigbuffer_add_value (buf, type->type);
704 sigbuffer_add_value (buf, type->type);
705 encode_type (assembly, type->data.type, buf);
707 case MONO_TYPE_SZARRAY:
708 sigbuffer_add_value (buf, type->type);
709 encode_type (assembly, &type->data.klass->byval_arg, buf);
711 case MONO_TYPE_VALUETYPE:
712 case MONO_TYPE_CLASS: {
713 MonoClass *k = mono_class_from_mono_type (type);
715 if (k->generic_container) {
716 MonoGenericClass *gclass = mono_metadata_lookup_generic_class (k, k->generic_container->context.class_inst, TRUE);
717 encode_generic_class (assembly, gclass, buf);
720 * Make sure we use the correct type.
722 sigbuffer_add_value (buf, k->byval_arg.type);
724 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
725 * otherwise two typerefs could point to the same type, leading to
726 * verification errors.
728 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, &k->byval_arg));
732 case MONO_TYPE_ARRAY:
733 sigbuffer_add_value (buf, type->type);
734 encode_type (assembly, &type->data.array->eklass->byval_arg, buf);
735 sigbuffer_add_value (buf, type->data.array->rank);
736 sigbuffer_add_value (buf, 0); /* FIXME: set to 0 for now */
737 sigbuffer_add_value (buf, 0);
739 case MONO_TYPE_GENERICINST:
740 encode_generic_class (assembly, type->data.generic_class, buf);
744 sigbuffer_add_value (buf, type->type);
745 sigbuffer_add_value (buf, mono_type_get_generic_param_num (type));
748 g_error ("need to encode type %x", type->type);
753 encode_reflection_type (MonoDynamicImage *assembly, MonoReflectionType *type, SigBuffer *buf)
756 sigbuffer_add_value (buf, MONO_TYPE_VOID);
760 encode_type (assembly, mono_reflection_type_get_handle (type), buf);
764 encode_custom_modifiers (MonoDynamicImage *assembly, MonoArray *modreq, MonoArray *modopt, SigBuffer *buf)
769 for (i = 0; i < mono_array_length (modreq); ++i) {
770 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
771 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_REQD);
772 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
776 for (i = 0; i < mono_array_length (modopt); ++i) {
777 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
778 sigbuffer_add_byte (buf, MONO_TYPE_CMOD_OPT);
779 sigbuffer_add_value (buf, mono_image_typedef_or_ref (assembly, mod));
784 #ifndef DISABLE_REFLECTION_EMIT
786 method_encode_signature (MonoDynamicImage *assembly, MonoMethodSignature *sig)
790 guint32 nparams = sig->param_count;
796 sigbuffer_init (&buf, 32);
798 * FIXME: vararg, explicit_this, differenc call_conv values...
800 idx = sig->call_convention;
802 idx |= 0x20; /* hasthis */
803 if (sig->generic_param_count)
804 idx |= 0x10; /* generic */
805 sigbuffer_add_byte (&buf, idx);
806 if (sig->generic_param_count)
807 sigbuffer_add_value (&buf, sig->generic_param_count);
808 sigbuffer_add_value (&buf, nparams);
809 encode_type (assembly, sig->ret, &buf);
810 for (i = 0; i < nparams; ++i) {
811 if (i == sig->sentinelpos)
812 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
813 encode_type (assembly, sig->params [i], &buf);
815 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
816 sigbuffer_free (&buf);
822 method_builder_encode_signature (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
825 * FIXME: reuse code from method_encode_signature().
829 guint32 nparams = mb->parameters ? mono_array_length (mb->parameters): 0;
830 guint32 ngparams = mb->generic_params ? mono_array_length (mb->generic_params): 0;
831 guint32 notypes = mb->opt_types ? mono_array_length (mb->opt_types): 0;
834 sigbuffer_init (&buf, 32);
835 /* LAMESPEC: all the call conv spec is foobared */
836 idx = mb->call_conv & 0x60; /* has-this, explicit-this */
837 if (mb->call_conv & 2)
838 idx |= 0x5; /* vararg */
839 if (!(mb->attrs & METHOD_ATTRIBUTE_STATIC))
840 idx |= 0x20; /* hasthis */
842 idx |= 0x10; /* generic */
843 sigbuffer_add_byte (&buf, idx);
845 sigbuffer_add_value (&buf, ngparams);
846 sigbuffer_add_value (&buf, nparams + notypes);
847 encode_custom_modifiers (assembly, mb->return_modreq, mb->return_modopt, &buf);
848 encode_reflection_type (assembly, mb->rtype, &buf);
849 for (i = 0; i < nparams; ++i) {
850 MonoArray *modreq = NULL;
851 MonoArray *modopt = NULL;
852 MonoReflectionType *pt;
854 if (mb->param_modreq && (i < mono_array_length (mb->param_modreq)))
855 modreq = mono_array_get (mb->param_modreq, MonoArray*, i);
856 if (mb->param_modopt && (i < mono_array_length (mb->param_modopt)))
857 modopt = mono_array_get (mb->param_modopt, MonoArray*, i);
858 encode_custom_modifiers (assembly, modreq, modopt, &buf);
859 pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
860 encode_reflection_type (assembly, pt, &buf);
863 sigbuffer_add_byte (&buf, MONO_TYPE_SENTINEL);
864 for (i = 0; i < notypes; ++i) {
865 MonoReflectionType *pt;
867 pt = mono_array_get (mb->opt_types, MonoReflectionType*, i);
868 encode_reflection_type (assembly, pt, &buf);
871 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
872 sigbuffer_free (&buf);
877 encode_locals (MonoDynamicImage *assembly, MonoReflectionILGen *ilgen)
879 MonoDynamicTable *table;
881 guint32 idx, sig_idx;
882 guint nl = mono_array_length (ilgen->locals);
886 sigbuffer_init (&buf, 32);
887 sigbuffer_add_value (&buf, 0x07);
888 sigbuffer_add_value (&buf, nl);
889 for (i = 0; i < nl; ++i) {
890 MonoReflectionLocalBuilder *lb = mono_array_get (ilgen->locals, MonoReflectionLocalBuilder*, i);
893 sigbuffer_add_value (&buf, MONO_TYPE_PINNED);
895 encode_reflection_type (assembly, (MonoReflectionType*)lb->type, &buf);
897 sig_idx = sigbuffer_add_to_blob_cached (assembly, &buf);
898 sigbuffer_free (&buf);
900 if (assembly->standalonesig_cache == NULL)
901 assembly->standalonesig_cache = g_hash_table_new (NULL, NULL);
902 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx)));
906 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
907 idx = table->next_idx ++;
909 alloc_table (table, table->rows);
910 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
912 values [MONO_STAND_ALONE_SIGNATURE] = sig_idx;
914 g_hash_table_insert (assembly->standalonesig_cache, GUINT_TO_POINTER (sig_idx), GUINT_TO_POINTER (idx));
920 method_count_clauses (MonoReflectionILGen *ilgen)
922 guint32 num_clauses = 0;
925 MonoILExceptionInfo *ex_info;
926 for (i = 0; i < mono_array_length (ilgen->ex_handlers); ++i) {
927 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
928 if (ex_info->handlers)
929 num_clauses += mono_array_length (ex_info->handlers);
937 #ifndef DISABLE_REFLECTION_EMIT
938 static MonoExceptionClause*
939 method_encode_clauses (MonoImage *image, MonoDynamicImage *assembly, MonoReflectionILGen *ilgen, guint32 num_clauses)
941 MonoExceptionClause *clauses;
942 MonoExceptionClause *clause;
943 MonoILExceptionInfo *ex_info;
944 MonoILExceptionBlock *ex_block;
945 guint32 finally_start;
946 int i, j, clause_index;;
948 clauses = image_g_new0 (image, MonoExceptionClause, num_clauses);
951 for (i = mono_array_length (ilgen->ex_handlers) - 1; i >= 0; --i) {
952 ex_info = (MonoILExceptionInfo*)mono_array_addr (ilgen->ex_handlers, MonoILExceptionInfo, i);
953 finally_start = ex_info->start + ex_info->len;
954 if (!ex_info->handlers)
956 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
957 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
958 clause = &(clauses [clause_index]);
960 clause->flags = ex_block->type;
961 clause->try_offset = ex_info->start;
963 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
964 clause->try_len = finally_start - ex_info->start;
966 clause->try_len = ex_info->len;
967 clause->handler_offset = ex_block->start;
968 clause->handler_len = ex_block->len;
969 if (ex_block->extype) {
970 clause->data.catch_class = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype));
972 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
973 clause->data.filter_offset = ex_block->filter_offset;
975 clause->data.filter_offset = 0;
977 finally_start = ex_block->start + ex_block->len;
985 #endif /* !DISABLE_REFLECTION_EMIT */
988 method_encode_code (MonoDynamicImage *assembly, ReflectionMethodBuilder *mb)
994 gint32 num_locals = 0;
995 gint32 num_exception = 0;
998 char fat_header [12];
1000 guint16 short_value;
1001 guint32 local_sig = 0;
1002 guint32 header_size = 12;
1005 if ((mb->attrs & (METHOD_ATTRIBUTE_PINVOKE_IMPL | METHOD_ATTRIBUTE_ABSTRACT)) ||
1006 (mb->iattrs & (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL | METHOD_IMPL_ATTRIBUTE_RUNTIME)))
1010 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1012 code = mb->ilgen->code;
1013 code_size = mb->ilgen->code_len;
1014 max_stack = mb->ilgen->max_stack;
1015 num_locals = mb->ilgen->locals ? mono_array_length (mb->ilgen->locals) : 0;
1016 if (mb->ilgen->ex_handlers)
1017 num_exception = method_count_clauses (mb->ilgen);
1021 char *name = mono_string_to_utf8 (mb->name);
1022 char *str = g_strdup_printf ("Method %s does not have any IL associated", name);
1023 MonoException *exception = mono_get_exception_argument (NULL, "a method does not have any IL associated");
1026 mono_raise_exception (exception);
1029 code_size = mono_array_length (code);
1030 max_stack = 8; /* we probably need to run a verifier on the code... */
1033 stream_data_align (&assembly->code);
1035 /* check for exceptions, maxstack, locals */
1036 maybe_small = (max_stack <= 8) && (!num_locals) && (!num_exception);
1038 if (code_size < 64 && !(code_size & 1)) {
1039 flags = (code_size << 2) | 0x2;
1040 } else if (code_size < 32 && (code_size & 1)) {
1041 flags = (code_size << 2) | 0x6; /* LAMESPEC: see metadata.c */
1045 idx = mono_image_add_stream_data (&assembly->code, &flags, 1);
1046 /* add to the fixup todo list */
1047 if (mb->ilgen && mb->ilgen->num_token_fixups)
1048 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 1));
1049 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1050 return assembly->text_rva + idx;
1054 local_sig = MONO_TOKEN_SIGNATURE | encode_locals (assembly, mb->ilgen);
1056 * FIXME: need to set also the header size in fat_flags.
1057 * (and more sects and init locals flags)
1061 fat_flags |= METHOD_HEADER_MORE_SECTS;
1062 if (mb->init_locals)
1063 fat_flags |= METHOD_HEADER_INIT_LOCALS;
1064 fat_header [0] = fat_flags;
1065 fat_header [1] = (header_size / 4 ) << 4;
1066 short_value = GUINT16_TO_LE (max_stack);
1067 memcpy (fat_header + 2, &short_value, 2);
1068 int_value = GUINT32_TO_LE (code_size);
1069 memcpy (fat_header + 4, &int_value, 4);
1070 int_value = GUINT32_TO_LE (local_sig);
1071 memcpy (fat_header + 8, &int_value, 4);
1072 idx = mono_image_add_stream_data (&assembly->code, fat_header, 12);
1073 /* add to the fixup todo list */
1074 if (mb->ilgen && mb->ilgen->num_token_fixups)
1075 mono_g_hash_table_insert (assembly->token_fixups, mb->ilgen, GUINT_TO_POINTER (idx + 12));
1077 mono_image_add_stream_data (&assembly->code, mono_array_addr (code, char, 0), code_size);
1078 if (num_exception) {
1079 unsigned char sheader [4];
1080 MonoILExceptionInfo * ex_info;
1081 MonoILExceptionBlock * ex_block;
1084 stream_data_align (&assembly->code);
1085 /* always use fat format for now */
1086 sheader [0] = METHOD_HEADER_SECTION_FAT_FORMAT | METHOD_HEADER_SECTION_EHTABLE;
1087 num_exception *= 6 * sizeof (guint32);
1088 num_exception += 4; /* include the size of the header */
1089 sheader [1] = num_exception & 0xff;
1090 sheader [2] = (num_exception >> 8) & 0xff;
1091 sheader [3] = (num_exception >> 16) & 0xff;
1092 mono_image_add_stream_data (&assembly->code, (char*)sheader, 4);
1093 /* fat header, so we are already aligned */
1095 for (i = mono_array_length (mb->ilgen->ex_handlers) - 1; i >= 0; --i) {
1096 ex_info = (MonoILExceptionInfo *)mono_array_addr (mb->ilgen->ex_handlers, MonoILExceptionInfo, i);
1097 if (ex_info->handlers) {
1098 int finally_start = ex_info->start + ex_info->len;
1099 for (j = 0; j < mono_array_length (ex_info->handlers); ++j) {
1101 ex_block = (MonoILExceptionBlock*)mono_array_addr (ex_info->handlers, MonoILExceptionBlock, j);
1103 val = GUINT32_TO_LE (ex_block->type);
1104 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1106 val = GUINT32_TO_LE (ex_info->start);
1107 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1108 /* need fault, too, probably */
1109 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FINALLY)
1110 val = GUINT32_TO_LE (finally_start - ex_info->start);
1112 val = GUINT32_TO_LE (ex_info->len);
1113 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1114 /* handler offset */
1115 val = GUINT32_TO_LE (ex_block->start);
1116 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1118 val = GUINT32_TO_LE (ex_block->len);
1119 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1120 finally_start = ex_block->start + ex_block->len;
1121 if (ex_block->extype) {
1122 val = mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)ex_block->extype)));
1124 if (ex_block->type == MONO_EXCEPTION_CLAUSE_FILTER)
1125 val = ex_block->filter_offset;
1129 val = GUINT32_TO_LE (val);
1130 mono_image_add_stream_data (&assembly->code, (char*)&val, sizeof (guint32));
1131 /*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",
1132 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);*/
1135 g_error ("No clauses for ex info block %d", i);
1139 return assembly->text_rva + idx;
1143 find_index_in_table (MonoDynamicImage *assembly, int table_idx, int col, guint32 token)
1146 MonoDynamicTable *table;
1149 table = &assembly->tables [table_idx];
1151 g_assert (col < table->columns);
1153 values = table->values + table->columns;
1154 for (i = 1; i <= table->rows; ++i) {
1155 if (values [col] == token)
1157 values += table->columns;
1163 * LOCKING: Acquires the loader lock.
1165 static MonoCustomAttrInfo*
1166 lookup_custom_attr (MonoImage *image, gpointer member)
1168 MonoCustomAttrInfo* res;
1170 res = mono_image_property_lookup (image, member, MONO_PROP_DYNAMIC_CATTR);
1175 return g_memdup (res, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * res->num_attrs);
1179 custom_attr_visible (MonoImage *image, MonoReflectionCustomAttr *cattr)
1181 /* FIXME: Need to do more checks */
1182 if (cattr->ctor->method && (cattr->ctor->method->klass->image != image)) {
1183 int visibility = cattr->ctor->method->klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
1185 if ((visibility != TYPE_ATTRIBUTE_PUBLIC) && (visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC))
1192 static MonoCustomAttrInfo*
1193 mono_custom_attrs_from_builders (MonoImage *alloc_img, MonoImage *image, MonoArray *cattrs)
1195 int i, index, count, not_visible;
1196 MonoCustomAttrInfo *ainfo;
1197 MonoReflectionCustomAttr *cattr;
1201 /* FIXME: check in assembly the Run flag is set */
1203 count = mono_array_length (cattrs);
1205 /* Skip nonpublic attributes since MS.NET seems to do the same */
1206 /* FIXME: This needs to be done more globally */
1208 for (i = 0; i < count; ++i) {
1209 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1210 if (!custom_attr_visible (image, cattr))
1213 count -= not_visible;
1215 ainfo = image_g_malloc0 (alloc_img, MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * count);
1217 ainfo->image = image;
1218 ainfo->num_attrs = count;
1219 ainfo->cached = alloc_img != NULL;
1221 for (i = 0; i < count; ++i) {
1222 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1223 if (custom_attr_visible (image, cattr)) {
1224 unsigned char *saved = mono_image_alloc (image, mono_array_length (cattr->data));
1225 memcpy (saved, mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1226 ainfo->attrs [index].ctor = cattr->ctor->method;
1227 ainfo->attrs [index].data = saved;
1228 ainfo->attrs [index].data_size = mono_array_length (cattr->data);
1236 #ifndef DISABLE_REFLECTION_EMIT
1238 * LOCKING: Acquires the loader lock.
1241 mono_save_custom_attrs (MonoImage *image, void *obj, MonoArray *cattrs)
1243 MonoCustomAttrInfo *ainfo, *tmp;
1245 if (!cattrs || !mono_array_length (cattrs))
1248 ainfo = mono_custom_attrs_from_builders (image, image, cattrs);
1250 mono_loader_lock ();
1251 tmp = mono_image_property_lookup (image, obj, MONO_PROP_DYNAMIC_CATTR);
1253 mono_custom_attrs_free (tmp);
1254 mono_image_property_insert (image, obj, MONO_PROP_DYNAMIC_CATTR, ainfo);
1255 mono_loader_unlock ();
1261 mono_custom_attrs_free (MonoCustomAttrInfo *ainfo)
1268 * idx is the table index of the object
1269 * type is one of MONO_CUSTOM_ATTR_*
1272 mono_image_add_cattrs (MonoDynamicImage *assembly, guint32 idx, guint32 type, MonoArray *cattrs)
1274 MonoDynamicTable *table;
1275 MonoReflectionCustomAttr *cattr;
1277 guint32 count, i, token;
1279 char *p = blob_size;
1281 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1284 count = mono_array_length (cattrs);
1285 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
1286 table->rows += count;
1287 alloc_table (table, table->rows);
1288 values = table->values + table->next_idx * MONO_CUSTOM_ATTR_SIZE;
1289 idx <<= MONO_CUSTOM_ATTR_BITS;
1291 for (i = 0; i < count; ++i) {
1292 cattr = (MonoReflectionCustomAttr*)mono_array_get (cattrs, gpointer, i);
1293 values [MONO_CUSTOM_ATTR_PARENT] = idx;
1294 token = mono_image_create_token (assembly, (MonoObject*)cattr->ctor, FALSE, FALSE);
1295 type = mono_metadata_token_index (token);
1296 type <<= MONO_CUSTOM_ATTR_TYPE_BITS;
1297 switch (mono_metadata_token_table (token)) {
1298 case MONO_TABLE_METHOD:
1299 type |= MONO_CUSTOM_ATTR_TYPE_METHODDEF;
1301 case MONO_TABLE_MEMBERREF:
1302 type |= MONO_CUSTOM_ATTR_TYPE_MEMBERREF;
1305 g_warning ("got wrong token in custom attr");
1308 values [MONO_CUSTOM_ATTR_TYPE] = type;
1310 mono_metadata_encode_value (mono_array_length (cattr->data), p, &p);
1311 values [MONO_CUSTOM_ATTR_VALUE] = add_to_blob_cached (assembly, blob_size, p - blob_size,
1312 mono_array_addr (cattr->data, char, 0), mono_array_length (cattr->data));
1313 values += MONO_CUSTOM_ATTR_SIZE;
1319 mono_image_add_decl_security (MonoDynamicImage *assembly, guint32 parent_token, MonoArray *permissions)
1321 MonoDynamicTable *table;
1323 guint32 count, i, idx;
1324 MonoReflectionPermissionSet *perm;
1329 count = mono_array_length (permissions);
1330 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
1331 table->rows += count;
1332 alloc_table (table, table->rows);
1334 for (i = 0; i < mono_array_length (permissions); ++i) {
1335 perm = (MonoReflectionPermissionSet*)mono_array_addr (permissions, MonoReflectionPermissionSet, i);
1337 values = table->values + table->next_idx * MONO_DECL_SECURITY_SIZE;
1339 idx = mono_metadata_token_index (parent_token);
1340 idx <<= MONO_HAS_DECL_SECURITY_BITS;
1341 switch (mono_metadata_token_table (parent_token)) {
1342 case MONO_TABLE_TYPEDEF:
1343 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
1345 case MONO_TABLE_METHOD:
1346 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
1348 case MONO_TABLE_ASSEMBLY:
1349 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
1352 g_assert_not_reached ();
1355 values [MONO_DECL_SECURITY_ACTION] = perm->action;
1356 values [MONO_DECL_SECURITY_PARENT] = idx;
1357 values [MONO_DECL_SECURITY_PERMISSIONSET] = add_mono_string_to_blob_cached (assembly, perm->pset);
1364 * Fill in the MethodDef and ParamDef tables for a method.
1365 * This is used for both normal methods and constructors.
1368 mono_image_basic_method (ReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1370 MonoDynamicTable *table;
1374 /* room in this table is already allocated */
1375 table = &assembly->tables [MONO_TABLE_METHOD];
1376 *mb->table_idx = table->next_idx ++;
1377 g_hash_table_insert (assembly->method_to_table_idx, mb->mhandle, GUINT_TO_POINTER ((*mb->table_idx)));
1378 values = table->values + *mb->table_idx * MONO_METHOD_SIZE;
1379 values [MONO_METHOD_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1380 values [MONO_METHOD_FLAGS] = mb->attrs;
1381 values [MONO_METHOD_IMPLFLAGS] = mb->iattrs;
1382 values [MONO_METHOD_SIGNATURE] = method_builder_encode_signature (assembly, mb);
1383 values [MONO_METHOD_RVA] = method_encode_code (assembly, mb);
1385 table = &assembly->tables [MONO_TABLE_PARAM];
1386 values [MONO_METHOD_PARAMLIST] = table->next_idx;
1388 mono_image_add_decl_security (assembly,
1389 mono_metadata_make_token (MONO_TABLE_METHOD, *mb->table_idx), mb->permissions);
1392 MonoDynamicTable *mtable;
1395 mtable = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1396 mvalues = mtable->values + mtable->next_idx * MONO_FIELD_MARSHAL_SIZE;
1399 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1400 if (mono_array_get (mb->pinfo, gpointer, i))
1403 table->rows += count;
1404 alloc_table (table, table->rows);
1405 values = table->values + table->next_idx * MONO_PARAM_SIZE;
1406 for (i = 0; i < mono_array_length (mb->pinfo); ++i) {
1407 MonoReflectionParamBuilder *pb;
1408 if ((pb = mono_array_get (mb->pinfo, MonoReflectionParamBuilder*, i))) {
1409 values [MONO_PARAM_FLAGS] = pb->attrs;
1410 values [MONO_PARAM_SEQUENCE] = i;
1411 if (pb->name != NULL) {
1412 values [MONO_PARAM_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
1414 values [MONO_PARAM_NAME] = 0;
1416 values += MONO_PARAM_SIZE;
1417 if (pb->marshal_info) {
1419 alloc_table (mtable, mtable->rows);
1420 mvalues = mtable->values + mtable->rows * MONO_FIELD_MARSHAL_SIZE;
1421 mvalues [MONO_FIELD_MARSHAL_PARENT] = (table->next_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_PARAMDEF;
1422 mvalues [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, pb->marshal_info);
1424 pb->table_idx = table->next_idx++;
1425 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
1426 guint32 field_type = 0;
1427 mtable = &assembly->tables [MONO_TABLE_CONSTANT];
1429 alloc_table (mtable, mtable->rows);
1430 mvalues = mtable->values + mtable->rows * MONO_CONSTANT_SIZE;
1431 mvalues [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PARAM | (pb->table_idx << MONO_HASCONSTANT_BITS);
1432 mvalues [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
1433 mvalues [MONO_CONSTANT_TYPE] = field_type;
1434 mvalues [MONO_CONSTANT_PADDING] = 0;
1441 #ifndef DISABLE_REFLECTION_EMIT
1443 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder *rmb, MonoReflectionMethodBuilder *mb)
1445 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1447 rmb->ilgen = mb->ilgen;
1448 rmb->rtype = mono_reflection_type_resolve_user_types ((MonoReflectionType*)mb->rtype);
1449 rmb->parameters = mb->parameters;
1450 rmb->generic_params = mb->generic_params;
1451 rmb->generic_container = mb->generic_container;
1452 rmb->opt_types = NULL;
1453 rmb->pinfo = mb->pinfo;
1454 rmb->attrs = mb->attrs;
1455 rmb->iattrs = mb->iattrs;
1456 rmb->call_conv = mb->call_conv;
1457 rmb->code = mb->code;
1458 rmb->type = mb->type;
1459 rmb->name = mb->name;
1460 rmb->table_idx = &mb->table_idx;
1461 rmb->init_locals = mb->init_locals;
1462 rmb->skip_visibility = FALSE;
1463 rmb->return_modreq = mb->return_modreq;
1464 rmb->return_modopt = mb->return_modopt;
1465 rmb->param_modreq = mb->param_modreq;
1466 rmb->param_modopt = mb->param_modopt;
1467 rmb->permissions = mb->permissions;
1468 rmb->mhandle = mb->mhandle;
1473 rmb->charset = mb->charset;
1474 rmb->extra_flags = mb->extra_flags;
1475 rmb->native_cc = mb->native_cc;
1476 rmb->dllentry = mb->dllentry;
1482 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder *rmb, MonoReflectionCtorBuilder *mb)
1484 const char *name = mb->attrs & METHOD_ATTRIBUTE_STATIC ? ".cctor": ".ctor";
1486 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1488 rmb->ilgen = mb->ilgen;
1489 rmb->rtype = mono_type_get_object (mono_domain_get (), &mono_defaults.void_class->byval_arg);
1490 rmb->parameters = mb->parameters;
1491 rmb->generic_params = NULL;
1492 rmb->generic_container = NULL;
1493 rmb->opt_types = NULL;
1494 rmb->pinfo = mb->pinfo;
1495 rmb->attrs = mb->attrs;
1496 rmb->iattrs = mb->iattrs;
1497 rmb->call_conv = mb->call_conv;
1499 rmb->type = mb->type;
1500 rmb->name = mono_string_new (mono_domain_get (), name);
1501 rmb->table_idx = &mb->table_idx;
1502 rmb->init_locals = mb->init_locals;
1503 rmb->skip_visibility = FALSE;
1504 rmb->return_modreq = NULL;
1505 rmb->return_modopt = NULL;
1506 rmb->param_modreq = mb->param_modreq;
1507 rmb->param_modopt = mb->param_modopt;
1508 rmb->permissions = mb->permissions;
1509 rmb->mhandle = mb->mhandle;
1515 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder *rmb, MonoReflectionDynamicMethod *mb)
1517 memset (rmb, 0, sizeof (ReflectionMethodBuilder));
1519 rmb->ilgen = mb->ilgen;
1520 rmb->rtype = mb->rtype;
1521 rmb->parameters = mb->parameters;
1522 rmb->generic_params = NULL;
1523 rmb->generic_container = NULL;
1524 rmb->opt_types = NULL;
1526 rmb->attrs = mb->attrs;
1528 rmb->call_conv = mb->call_conv;
1530 rmb->type = (MonoObject *) mb->owner;
1531 rmb->name = mb->name;
1532 rmb->table_idx = NULL;
1533 rmb->init_locals = mb->init_locals;
1534 rmb->skip_visibility = mb->skip_visibility;
1535 rmb->return_modreq = NULL;
1536 rmb->return_modopt = NULL;
1537 rmb->param_modreq = NULL;
1538 rmb->param_modopt = NULL;
1539 rmb->permissions = NULL;
1540 rmb->mhandle = mb->mhandle;
1547 mono_image_add_methodimpl (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
1549 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
1550 MonoDynamicTable *table;
1554 if (!mb->override_method)
1557 table = &assembly->tables [MONO_TABLE_METHODIMPL];
1559 alloc_table (table, table->rows);
1560 values = table->values + table->rows * MONO_METHODIMPL_SIZE;
1561 values [MONO_METHODIMPL_CLASS] = tb->table_idx;
1562 values [MONO_METHODIMPL_BODY] = MONO_METHODDEFORREF_METHODDEF | (mb->table_idx << MONO_METHODDEFORREF_BITS);
1564 tok = mono_image_create_token (assembly, (MonoObject*)mb->override_method, FALSE, FALSE);
1565 switch (mono_metadata_token_table (tok)) {
1566 case MONO_TABLE_MEMBERREF:
1567 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODREF;
1569 case MONO_TABLE_METHOD:
1570 tok = (mono_metadata_token_index (tok) << MONO_METHODDEFORREF_BITS ) | MONO_METHODDEFORREF_METHODDEF;
1573 g_assert_not_reached ();
1575 values [MONO_METHODIMPL_DECLARATION] = tok;
1578 #ifndef DISABLE_REFLECTION_EMIT
1580 mono_image_get_method_info (MonoReflectionMethodBuilder *mb, MonoDynamicImage *assembly)
1582 MonoDynamicTable *table;
1584 ReflectionMethodBuilder rmb;
1587 reflection_methodbuilder_from_method_builder (&rmb, mb);
1589 mono_image_basic_method (&rmb, assembly);
1590 mb->table_idx = *rmb.table_idx;
1592 if (mb->dll) { /* It's a P/Invoke method */
1594 /* map CharSet values to on-disk values */
1595 int ncharset = (mb->charset ? (mb->charset - 1) * 2 : 0);
1596 int extra_flags = mb->extra_flags;
1597 table = &assembly->tables [MONO_TABLE_IMPLMAP];
1599 alloc_table (table, table->rows);
1600 values = table->values + table->rows * MONO_IMPLMAP_SIZE;
1602 values [MONO_IMPLMAP_FLAGS] = (mb->native_cc << 8) | ncharset | extra_flags;
1603 values [MONO_IMPLMAP_MEMBER] = (mb->table_idx << 1) | 1; /* memberforwarded: method */
1605 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->dllentry);
1607 values [MONO_IMPLMAP_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->name);
1608 moduleref = string_heap_insert_mstring (&assembly->sheap, mb->dll);
1609 if (!(values [MONO_IMPLMAP_SCOPE] = find_index_in_table (assembly, MONO_TABLE_MODULEREF, MONO_MODULEREF_NAME, moduleref))) {
1610 table = &assembly->tables [MONO_TABLE_MODULEREF];
1612 alloc_table (table, table->rows);
1613 table->values [table->rows * MONO_MODULEREF_SIZE + MONO_MODULEREF_NAME] = moduleref;
1614 values [MONO_IMPLMAP_SCOPE] = table->rows;
1618 if (mb->generic_params) {
1619 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
1620 table->rows += mono_array_length (mb->generic_params);
1621 alloc_table (table, table->rows);
1622 for (i = 0; i < mono_array_length (mb->generic_params); ++i) {
1623 guint32 owner = MONO_TYPEORMETHOD_METHOD | (mb->table_idx << MONO_TYPEORMETHOD_BITS);
1625 mono_image_get_generic_param_info (
1626 mono_array_get (mb->generic_params, gpointer, i), owner, assembly);
1633 mono_image_get_ctor_info (MonoDomain *domain, MonoReflectionCtorBuilder *mb, MonoDynamicImage *assembly)
1635 ReflectionMethodBuilder rmb;
1637 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
1639 mono_image_basic_method (&rmb, assembly);
1640 mb->table_idx = *rmb.table_idx;
1645 type_get_fully_qualified_name (MonoType *type)
1647 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1651 type_get_qualified_name (MonoType *type, MonoAssembly *ass) {
1655 klass = mono_class_from_mono_type (type);
1657 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1658 ta = klass->image->assembly;
1659 if (ta->dynamic || (ta == ass)) {
1660 if (klass->generic_class || klass->generic_container)
1661 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1662 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_FULL_NAME);
1664 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_REFLECTION);
1667 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED);
1670 #ifndef DISABLE_REFLECTION_EMIT
1671 /*field_image is the image to which the eventual custom mods have been encoded against*/
1673 fieldref_encode_signature (MonoDynamicImage *assembly, MonoImage *field_image, MonoType *type)
1676 guint32 idx, i, token;
1678 if (!assembly->save)
1681 sigbuffer_init (&buf, 32);
1683 sigbuffer_add_value (&buf, 0x06);
1684 /* encode custom attributes before the type */
1685 if (type->num_mods) {
1686 for (i = 0; i < type->num_mods; ++i) {
1688 MonoClass *class = mono_class_get (field_image, type->modifiers [i].token);
1690 token = mono_image_typedef_or_ref (assembly, &class->byval_arg);
1692 token = type->modifiers [i].token;
1695 if (type->modifiers [i].required)
1696 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_REQD);
1698 sigbuffer_add_byte (&buf, MONO_TYPE_CMOD_OPT);
1700 sigbuffer_add_value (&buf, token);
1703 encode_type (assembly, type, &buf);
1704 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1705 sigbuffer_free (&buf);
1711 field_encode_signature (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
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 */
1721 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
1722 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1723 sigbuffer_free (&buf);
1728 encode_constant (MonoDynamicImage *assembly, MonoObject *val, guint32 *ret_type) {
1729 char blob_size [64];
1730 char *b = blob_size;
1733 guint32 idx = 0, len = 0, dummy = 0;
1735 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1736 guint32 fpa_double [2];
1741 p = buf = g_malloc (64);
1743 *ret_type = MONO_TYPE_CLASS;
1745 box_val = (char*)&dummy;
1747 box_val = ((char*)val) + sizeof (MonoObject);
1748 *ret_type = val->vtable->klass->byval_arg.type;
1751 switch (*ret_type) {
1752 case MONO_TYPE_BOOLEAN:
1757 case MONO_TYPE_CHAR:
1774 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1775 fpa_p = (guint32*)box_val;
1776 fpa_double [0] = fpa_p [1];
1777 fpa_double [1] = fpa_p [0];
1778 box_val = (char*)fpa_double;
1782 case MONO_TYPE_VALUETYPE:
1783 if (val->vtable->klass->enumtype) {
1784 *ret_type = mono_class_enum_basetype (val->vtable->klass)->type;
1787 g_error ("we can't encode valuetypes");
1788 case MONO_TYPE_CLASS:
1790 case MONO_TYPE_STRING: {
1791 MonoString *str = (MonoString*)val;
1792 /* there is no signature */
1793 len = str->length * 2;
1794 mono_metadata_encode_value (len, b, &b);
1795 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1797 char *swapped = g_malloc (2 * mono_string_length (str));
1798 const char *p = (const char*)mono_string_chars (str);
1800 swap_with_size (swapped, p, 2, mono_string_length (str));
1801 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, swapped, len);
1805 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, (char*)mono_string_chars (str), len);
1811 case MONO_TYPE_GENERICINST:
1812 *ret_type = val->vtable->klass->generic_class->container_class->byval_arg.type;
1815 g_error ("we don't encode constant type 0x%02x yet", *ret_type);
1818 /* there is no signature */
1819 mono_metadata_encode_value (len, b, &b);
1820 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1821 idx = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
1822 swap_with_size (blob_size, box_val, len, 1);
1823 mono_image_add_stream_data (&assembly->blob, blob_size, len);
1825 idx = add_to_blob_cached (assembly, blob_size, b-blob_size, box_val, len);
1833 encode_marshal_blob (MonoDynamicImage *assembly, MonoReflectionMarshal *minfo) {
1838 sigbuffer_init (&buf, 32);
1840 sigbuffer_add_value (&buf, minfo->type);
1842 switch (minfo->type) {
1843 case MONO_NATIVE_BYVALTSTR:
1844 case MONO_NATIVE_BYVALARRAY:
1845 sigbuffer_add_value (&buf, minfo->count);
1847 case MONO_NATIVE_LPARRAY:
1848 if (minfo->eltype || minfo->has_size) {
1849 sigbuffer_add_value (&buf, minfo->eltype);
1850 if (minfo->has_size) {
1851 sigbuffer_add_value (&buf, minfo->param_num != -1? minfo->param_num: 0);
1852 sigbuffer_add_value (&buf, minfo->count != -1? minfo->count: 0);
1854 /* LAMESPEC: ElemMult is undocumented */
1855 sigbuffer_add_value (&buf, minfo->param_num != -1? 1: 0);
1859 case MONO_NATIVE_SAFEARRAY:
1861 sigbuffer_add_value (&buf, minfo->eltype);
1863 case MONO_NATIVE_CUSTOM:
1865 str = mono_string_to_utf8 (minfo->guid);
1867 sigbuffer_add_value (&buf, len);
1868 sigbuffer_add_mem (&buf, str, len);
1871 sigbuffer_add_value (&buf, 0);
1873 /* native type name */
1874 sigbuffer_add_value (&buf, 0);
1875 /* custom marshaler type name */
1876 if (minfo->marshaltype || minfo->marshaltyperef) {
1877 if (minfo->marshaltyperef)
1878 str = type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType*)minfo->marshaltyperef));
1880 str = mono_string_to_utf8 (minfo->marshaltype);
1882 sigbuffer_add_value (&buf, len);
1883 sigbuffer_add_mem (&buf, str, len);
1886 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1887 sigbuffer_add_value (&buf, 0);
1889 if (minfo->mcookie) {
1890 str = mono_string_to_utf8 (minfo->mcookie);
1892 sigbuffer_add_value (&buf, len);
1893 sigbuffer_add_mem (&buf, str, len);
1896 sigbuffer_add_value (&buf, 0);
1902 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
1903 sigbuffer_free (&buf);
1908 mono_image_get_field_info (MonoReflectionFieldBuilder *fb, MonoDynamicImage *assembly)
1910 MonoDynamicTable *table;
1913 /* maybe this fixup should be done in the C# code */
1914 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL)
1915 fb->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
1916 table = &assembly->tables [MONO_TABLE_FIELD];
1917 fb->table_idx = table->next_idx ++;
1918 g_hash_table_insert (assembly->field_to_table_idx, fb->handle, GUINT_TO_POINTER (fb->table_idx));
1919 values = table->values + fb->table_idx * MONO_FIELD_SIZE;
1920 values [MONO_FIELD_NAME] = string_heap_insert_mstring (&assembly->sheap, fb->name);
1921 values [MONO_FIELD_FLAGS] = fb->attrs;
1922 values [MONO_FIELD_SIGNATURE] = field_encode_signature (assembly, fb);
1924 if (fb->offset != -1) {
1925 table = &assembly->tables [MONO_TABLE_FIELDLAYOUT];
1927 alloc_table (table, table->rows);
1928 values = table->values + table->rows * MONO_FIELD_LAYOUT_SIZE;
1929 values [MONO_FIELD_LAYOUT_FIELD] = fb->table_idx;
1930 values [MONO_FIELD_LAYOUT_OFFSET] = fb->offset;
1932 if (fb->attrs & FIELD_ATTRIBUTE_LITERAL) {
1933 guint32 field_type = 0;
1934 table = &assembly->tables [MONO_TABLE_CONSTANT];
1936 alloc_table (table, table->rows);
1937 values = table->values + table->rows * MONO_CONSTANT_SIZE;
1938 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_FIEDDEF | (fb->table_idx << MONO_HASCONSTANT_BITS);
1939 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, fb->def_value, &field_type);
1940 values [MONO_CONSTANT_TYPE] = field_type;
1941 values [MONO_CONSTANT_PADDING] = 0;
1943 if (fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
1945 table = &assembly->tables [MONO_TABLE_FIELDRVA];
1947 alloc_table (table, table->rows);
1948 values = table->values + table->rows * MONO_FIELD_RVA_SIZE;
1949 values [MONO_FIELD_RVA_FIELD] = fb->table_idx;
1951 * We store it in the code section because it's simpler for now.
1954 if (mono_array_length (fb->rva_data) >= 10)
1955 stream_data_align (&assembly->code);
1956 rva_idx = mono_image_add_stream_data (&assembly->code, mono_array_addr (fb->rva_data, char, 0), mono_array_length (fb->rva_data));
1958 rva_idx = mono_image_add_stream_zero (&assembly->code, mono_class_value_size (fb->handle->parent, NULL));
1959 values [MONO_FIELD_RVA_RVA] = rva_idx + assembly->text_rva;
1961 if (fb->marshal_info) {
1962 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
1964 alloc_table (table, table->rows);
1965 values = table->values + table->rows * MONO_FIELD_MARSHAL_SIZE;
1966 values [MONO_FIELD_MARSHAL_PARENT] = (fb->table_idx << MONO_HAS_FIELD_MARSHAL_BITS) | MONO_HAS_FIELD_MARSHAL_FIELDSREF;
1967 values [MONO_FIELD_MARSHAL_NATIVE_TYPE] = encode_marshal_blob (assembly, fb->marshal_info);
1972 property_encode_signature (MonoDynamicImage *assembly, MonoReflectionPropertyBuilder *fb)
1975 guint32 nparams = 0;
1976 MonoReflectionMethodBuilder *mb = fb->get_method;
1977 MonoReflectionMethodBuilder *smb = fb->set_method;
1980 if (mb && mb->parameters)
1981 nparams = mono_array_length (mb->parameters);
1982 if (!mb && smb && smb->parameters)
1983 nparams = mono_array_length (smb->parameters) - 1;
1984 sigbuffer_init (&buf, 32);
1985 sigbuffer_add_byte (&buf, 0x08);
1986 sigbuffer_add_value (&buf, nparams);
1988 encode_reflection_type (assembly, (MonoReflectionType*)mb->rtype, &buf);
1989 for (i = 0; i < nparams; ++i) {
1990 MonoReflectionType *pt = mono_array_get (mb->parameters, MonoReflectionType*, i);
1991 encode_reflection_type (assembly, pt, &buf);
1993 } else if (smb && smb->parameters) {
1994 /* the property type is the last param */
1995 encode_reflection_type (assembly, mono_array_get (smb->parameters, MonoReflectionType*, nparams), &buf);
1996 for (i = 0; i < nparams; ++i) {
1997 MonoReflectionType *pt = mono_array_get (smb->parameters, MonoReflectionType*, i);
1998 encode_reflection_type (assembly, pt, &buf);
2001 encode_reflection_type (assembly, (MonoReflectionType*)fb->type, &buf);
2004 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2005 sigbuffer_free (&buf);
2010 mono_image_get_property_info (MonoReflectionPropertyBuilder *pb, MonoDynamicImage *assembly)
2012 MonoDynamicTable *table;
2014 guint num_methods = 0;
2018 * we need to set things in the following tables:
2019 * PROPERTYMAP (info already filled in _get_type_info ())
2020 * PROPERTY (rows already preallocated in _get_type_info ())
2021 * METHOD (method info already done with the generic method code)
2025 table = &assembly->tables [MONO_TABLE_PROPERTY];
2026 pb->table_idx = table->next_idx ++;
2027 values = table->values + pb->table_idx * MONO_PROPERTY_SIZE;
2028 values [MONO_PROPERTY_NAME] = string_heap_insert_mstring (&assembly->sheap, pb->name);
2029 values [MONO_PROPERTY_FLAGS] = pb->attrs;
2030 values [MONO_PROPERTY_TYPE] = property_encode_signature (assembly, pb);
2032 /* FIXME: we still don't handle 'other' methods */
2033 if (pb->get_method) num_methods ++;
2034 if (pb->set_method) num_methods ++;
2036 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2037 table->rows += num_methods;
2038 alloc_table (table, table->rows);
2040 if (pb->get_method) {
2041 semaidx = table->next_idx ++;
2042 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2043 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_GETTER;
2044 values [MONO_METHOD_SEMA_METHOD] = pb->get_method->table_idx;
2045 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2047 if (pb->set_method) {
2048 semaidx = table->next_idx ++;
2049 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2050 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_SETTER;
2051 values [MONO_METHOD_SEMA_METHOD] = pb->set_method->table_idx;
2052 values [MONO_METHOD_SEMA_ASSOCIATION] = (pb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_PROPERTY;
2054 if (pb->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT) {
2055 guint32 field_type = 0;
2056 table = &assembly->tables [MONO_TABLE_CONSTANT];
2058 alloc_table (table, table->rows);
2059 values = table->values + table->rows * MONO_CONSTANT_SIZE;
2060 values [MONO_CONSTANT_PARENT] = MONO_HASCONSTANT_PROPERTY | (pb->table_idx << MONO_HASCONSTANT_BITS);
2061 values [MONO_CONSTANT_VALUE] = encode_constant (assembly, pb->def_value, &field_type);
2062 values [MONO_CONSTANT_TYPE] = field_type;
2063 values [MONO_CONSTANT_PADDING] = 0;
2068 mono_image_get_event_info (MonoReflectionEventBuilder *eb, MonoDynamicImage *assembly)
2070 MonoDynamicTable *table;
2072 guint num_methods = 0;
2076 * we need to set things in the following tables:
2077 * EVENTMAP (info already filled in _get_type_info ())
2078 * EVENT (rows already preallocated in _get_type_info ())
2079 * METHOD (method info already done with the generic method code)
2082 table = &assembly->tables [MONO_TABLE_EVENT];
2083 eb->table_idx = table->next_idx ++;
2084 values = table->values + eb->table_idx * MONO_EVENT_SIZE;
2085 values [MONO_EVENT_NAME] = string_heap_insert_mstring (&assembly->sheap, eb->name);
2086 values [MONO_EVENT_FLAGS] = eb->attrs;
2087 values [MONO_EVENT_TYPE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (eb->type));
2090 * FIXME: we still don't handle 'other' methods
2092 if (eb->add_method) num_methods ++;
2093 if (eb->remove_method) num_methods ++;
2094 if (eb->raise_method) num_methods ++;
2096 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
2097 table->rows += num_methods;
2098 alloc_table (table, table->rows);
2100 if (eb->add_method) {
2101 semaidx = table->next_idx ++;
2102 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2103 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_ADD_ON;
2104 values [MONO_METHOD_SEMA_METHOD] = eb->add_method->table_idx;
2105 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2107 if (eb->remove_method) {
2108 semaidx = table->next_idx ++;
2109 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2110 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_REMOVE_ON;
2111 values [MONO_METHOD_SEMA_METHOD] = eb->remove_method->table_idx;
2112 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2114 if (eb->raise_method) {
2115 semaidx = table->next_idx ++;
2116 values = table->values + semaidx * MONO_METHOD_SEMA_SIZE;
2117 values [MONO_METHOD_SEMA_SEMANTICS] = METHOD_SEMANTIC_FIRE;
2118 values [MONO_METHOD_SEMA_METHOD] = eb->raise_method->table_idx;
2119 values [MONO_METHOD_SEMA_ASSOCIATION] = (eb->table_idx << MONO_HAS_SEMANTICS_BITS) | MONO_HAS_SEMANTICS_EVENT;
2124 encode_constraints (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2126 MonoDynamicTable *table;
2127 guint32 num_constraints, i;
2131 table = &assembly->tables [MONO_TABLE_GENERICPARAMCONSTRAINT];
2132 num_constraints = gparam->iface_constraints ?
2133 mono_array_length (gparam->iface_constraints) : 0;
2134 table->rows += num_constraints;
2135 if (gparam->base_type)
2137 alloc_table (table, table->rows);
2139 if (gparam->base_type) {
2140 table_idx = table->next_idx ++;
2141 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2143 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2144 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2145 assembly, mono_reflection_type_get_handle (gparam->base_type));
2148 for (i = 0; i < num_constraints; i++) {
2149 MonoReflectionType *constraint = mono_array_get (
2150 gparam->iface_constraints, gpointer, i);
2152 table_idx = table->next_idx ++;
2153 values = table->values + table_idx * MONO_GENPARCONSTRAINT_SIZE;
2155 values [MONO_GENPARCONSTRAINT_GENERICPAR] = owner;
2156 values [MONO_GENPARCONSTRAINT_CONSTRAINT] = mono_image_typedef_or_ref (
2157 assembly, mono_reflection_type_get_handle (constraint));
2162 mono_image_get_generic_param_info (MonoReflectionGenericParam *gparam, guint32 owner, MonoDynamicImage *assembly)
2164 GenericParamTableEntry *entry;
2167 * The GenericParam table must be sorted according to the `owner' field.
2168 * We need to do this sorting prior to writing the GenericParamConstraint
2169 * table, since we have to use the final GenericParam table indices there
2170 * and they must also be sorted.
2173 entry = g_new0 (GenericParamTableEntry, 1);
2174 entry->owner = owner;
2175 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2176 MOVING_GC_REGISTER (&entry->gparam);
2177 entry->gparam = gparam;
2179 g_ptr_array_add (assembly->gen_params, entry);
2183 write_generic_param_entry (MonoDynamicImage *assembly, GenericParamTableEntry *entry)
2185 MonoDynamicTable *table;
2186 MonoGenericParam *param;
2190 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
2191 table_idx = table->next_idx ++;
2192 values = table->values + table_idx * MONO_GENERICPARAM_SIZE;
2194 param = mono_reflection_type_get_handle ((MonoReflectionType*)entry->gparam)->data.generic_param;
2196 values [MONO_GENERICPARAM_OWNER] = entry->owner;
2197 values [MONO_GENERICPARAM_FLAGS] = entry->gparam->attrs;
2198 values [MONO_GENERICPARAM_NUMBER] = mono_generic_param_num (param);
2199 values [MONO_GENERICPARAM_NAME] = string_heap_insert (&assembly->sheap, mono_generic_param_info (param)->name);
2201 mono_image_add_cattrs (assembly, table_idx, MONO_CUSTOM_ATTR_GENERICPAR, entry->gparam->cattrs);
2203 encode_constraints (entry->gparam, table_idx, assembly);
2207 resolution_scope_from_image (MonoDynamicImage *assembly, MonoImage *image)
2209 MonoDynamicTable *table;
2212 guint32 cols [MONO_ASSEMBLY_SIZE];
2216 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, image))))
2219 if (image->assembly->dynamic && (image->assembly == assembly->image.assembly)) {
2220 table = &assembly->tables [MONO_TABLE_MODULEREF];
2221 token = table->next_idx ++;
2223 alloc_table (table, table->rows);
2224 values = table->values + token * MONO_MODULEREF_SIZE;
2225 values [MONO_MODULEREF_NAME] = string_heap_insert (&assembly->sheap, image->module_name);
2227 token <<= MONO_RESOLTION_SCOPE_BITS;
2228 token |= MONO_RESOLTION_SCOPE_MODULEREF;
2229 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2234 if (image->assembly->dynamic)
2236 memset (cols, 0, sizeof (cols));
2238 /* image->assembly->image is the manifest module */
2239 image = image->assembly->image;
2240 mono_metadata_decode_row (&image->tables [MONO_TABLE_ASSEMBLY], 0, cols, MONO_ASSEMBLY_SIZE);
2243 table = &assembly->tables [MONO_TABLE_ASSEMBLYREF];
2244 token = table->next_idx ++;
2246 alloc_table (table, table->rows);
2247 values = table->values + token * MONO_ASSEMBLYREF_SIZE;
2248 values [MONO_ASSEMBLYREF_NAME] = string_heap_insert (&assembly->sheap, image->assembly_name);
2249 values [MONO_ASSEMBLYREF_MAJOR_VERSION] = cols [MONO_ASSEMBLY_MAJOR_VERSION];
2250 values [MONO_ASSEMBLYREF_MINOR_VERSION] = cols [MONO_ASSEMBLY_MINOR_VERSION];
2251 values [MONO_ASSEMBLYREF_BUILD_NUMBER] = cols [MONO_ASSEMBLY_BUILD_NUMBER];
2252 values [MONO_ASSEMBLYREF_REV_NUMBER] = cols [MONO_ASSEMBLY_REV_NUMBER];
2253 values [MONO_ASSEMBLYREF_FLAGS] = 0;
2254 values [MONO_ASSEMBLYREF_CULTURE] = 0;
2255 values [MONO_ASSEMBLYREF_HASH_VALUE] = 0;
2257 if (strcmp ("", image->assembly->aname.culture)) {
2258 values [MONO_ASSEMBLYREF_CULTURE] = string_heap_insert (&assembly->sheap,
2259 image->assembly->aname.culture);
2262 if ((pubkey = mono_image_get_public_key (image, &publen))) {
2263 guchar pubtoken [9];
2265 mono_digest_get_public_token (pubtoken + 1, (guchar*)pubkey, publen);
2266 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = mono_image_add_stream_data (&assembly->blob, (char*)pubtoken, 9);
2268 values [MONO_ASSEMBLYREF_PUBLIC_KEY] = 0;
2270 token <<= MONO_RESOLTION_SCOPE_BITS;
2271 token |= MONO_RESOLTION_SCOPE_ASSEMBLYREF;
2272 g_hash_table_insert (assembly->handleref, image, GUINT_TO_POINTER (token));
2277 create_typespec (MonoDynamicImage *assembly, MonoType *type)
2279 MonoDynamicTable *table;
2284 if ((token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type))))
2287 sigbuffer_init (&buf, 32);
2288 switch (type->type) {
2289 case MONO_TYPE_FNPTR:
2291 case MONO_TYPE_SZARRAY:
2292 case MONO_TYPE_ARRAY:
2294 case MONO_TYPE_MVAR:
2295 case MONO_TYPE_GENERICINST:
2296 encode_type (assembly, type, &buf);
2298 case MONO_TYPE_CLASS:
2299 case MONO_TYPE_VALUETYPE: {
2300 MonoClass *k = mono_class_from_mono_type (type);
2301 if (!k || !k->generic_container) {
2302 sigbuffer_free (&buf);
2305 encode_type (assembly, type, &buf);
2309 sigbuffer_free (&buf);
2313 table = &assembly->tables [MONO_TABLE_TYPESPEC];
2314 if (assembly->save) {
2315 token = sigbuffer_add_to_blob_cached (assembly, &buf);
2316 alloc_table (table, table->rows + 1);
2317 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
2318 values [MONO_TYPESPEC_SIGNATURE] = token;
2320 sigbuffer_free (&buf);
2322 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
2323 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
2329 mono_image_typedef_or_ref_full (MonoDynamicImage *assembly, MonoType *type, gboolean try_typespec)
2331 MonoDynamicTable *table;
2333 guint32 token, scope, enclosing;
2336 /* if the type requires a typespec, we must try that first*/
2337 if (try_typespec && (token = create_typespec (assembly, type)))
2339 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typeref, type));
2342 klass = mono_class_from_mono_type (type);
2344 klass = mono_class_from_mono_type (type);
2347 * If it's in the same module and not a generic type parameter:
2349 if ((klass->image == &assembly->image) && (type->type != MONO_TYPE_VAR) &&
2350 (type->type != MONO_TYPE_MVAR)) {
2351 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
2352 token = MONO_TYPEDEFORREF_TYPEDEF | (tb->table_idx << MONO_TYPEDEFORREF_BITS);
2353 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2357 if (klass->nested_in) {
2358 enclosing = mono_image_typedef_or_ref_full (assembly, &klass->nested_in->byval_arg, FALSE);
2359 /* get the typeref idx of the enclosing type */
2360 enclosing >>= MONO_TYPEDEFORREF_BITS;
2361 scope = (enclosing << MONO_RESOLTION_SCOPE_BITS) | MONO_RESOLTION_SCOPE_TYPEREF;
2363 scope = resolution_scope_from_image (assembly, klass->image);
2365 table = &assembly->tables [MONO_TABLE_TYPEREF];
2366 if (assembly->save) {
2367 alloc_table (table, table->rows + 1);
2368 values = table->values + table->next_idx * MONO_TYPEREF_SIZE;
2369 values [MONO_TYPEREF_SCOPE] = scope;
2370 values [MONO_TYPEREF_NAME] = string_heap_insert (&assembly->sheap, klass->name);
2371 values [MONO_TYPEREF_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
2373 token = MONO_TYPEDEFORREF_TYPEREF | (table->next_idx << MONO_TYPEDEFORREF_BITS); /* typeref */
2374 g_hash_table_insert (assembly->typeref, type, GUINT_TO_POINTER(token));
2376 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), mono_class_get_ref_info (klass));
2381 * Despite the name, we handle also TypeSpec (with the above helper).
2384 mono_image_typedef_or_ref (MonoDynamicImage *assembly, MonoType *type)
2386 return mono_image_typedef_or_ref_full (assembly, type, TRUE);
2389 #ifndef DISABLE_REFLECTION_EMIT
2391 mono_image_add_memberef_row (MonoDynamicImage *assembly, guint32 parent, const char *name, guint32 sig)
2393 MonoDynamicTable *table;
2395 guint32 token, pclass;
2397 switch (parent & MONO_TYPEDEFORREF_MASK) {
2398 case MONO_TYPEDEFORREF_TYPEREF:
2399 pclass = MONO_MEMBERREF_PARENT_TYPEREF;
2401 case MONO_TYPEDEFORREF_TYPESPEC:
2402 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
2404 case MONO_TYPEDEFORREF_TYPEDEF:
2405 pclass = MONO_MEMBERREF_PARENT_TYPEDEF;
2408 g_warning ("unknown typeref or def token 0x%08x for %s", parent, name);
2411 /* extract the index */
2412 parent >>= MONO_TYPEDEFORREF_BITS;
2414 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2416 if (assembly->save) {
2417 alloc_table (table, table->rows + 1);
2418 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2419 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
2420 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2421 values [MONO_MEMBERREF_SIGNATURE] = sig;
2424 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2431 * Insert a memberef row into the metadata: the token that point to the memberref
2432 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2433 * mono_image_get_fieldref_token()).
2434 * The sig param is an index to an already built signature.
2437 mono_image_get_memberref_token (MonoDynamicImage *assembly, MonoType *type, const char *name, guint32 sig)
2439 guint32 parent = mono_image_typedef_or_ref (assembly, type);
2440 return mono_image_add_memberef_row (assembly, parent, name, sig);
2445 mono_image_get_methodref_token (MonoDynamicImage *assembly, MonoMethod *method, gboolean create_typespec)
2448 MonoMethodSignature *sig;
2450 create_typespec = create_typespec && method->is_generic && method->klass->image != &assembly->image;
2452 if (create_typespec) {
2453 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1)));
2458 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2459 if (token && !create_typespec)
2462 g_assert (!method->is_inflated);
2465 * A methodref signature can't contain an unmanaged calling convention.
2467 sig = mono_metadata_signature_dup (mono_method_signature (method));
2468 if ((sig->call_convention != MONO_CALL_DEFAULT) && (sig->call_convention != MONO_CALL_VARARG))
2469 sig->call_convention = MONO_CALL_DEFAULT;
2470 token = mono_image_get_memberref_token (assembly, &method->klass->byval_arg,
2471 method->name, method_encode_signature (assembly, sig));
2473 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2476 if (create_typespec) {
2477 MonoDynamicTable *table = &assembly->tables [MONO_TABLE_METHODSPEC];
2478 g_assert (mono_metadata_token_table (token) == MONO_TABLE_MEMBERREF);
2479 token = (mono_metadata_token_index (token) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2481 if (assembly->save) {
2484 alloc_table (table, table->rows + 1);
2485 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2486 values [MONO_METHODSPEC_METHOD] = token;
2487 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_sig (assembly, &mono_method_get_generic_container (method)->context);
2490 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2492 /*methodspec and memberef tokens are diferent, */
2493 g_hash_table_insert (assembly->handleref, GUINT_TO_POINTER (GPOINTER_TO_UINT (method) + 1), GUINT_TO_POINTER (token));
2500 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *method)
2502 guint32 token, parent, sig;
2503 ReflectionMethodBuilder rmb;
2505 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)method->type;
2507 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
2511 name = mono_string_to_utf8 (method->name);
2512 reflection_methodbuilder_from_method_builder (&rmb, method);
2515 * A methodref signature can't contain an unmanaged calling convention.
2516 * Since some flags are encoded as part of call_conv, we need to check against it.
2518 if ((rmb.call_conv & ~0x60) != MONO_CALL_DEFAULT && (rmb.call_conv & ~0x60) != MONO_CALL_VARARG)
2519 rmb.call_conv = (rmb.call_conv & 0x60) | MONO_CALL_DEFAULT;
2521 sig = method_builder_encode_signature (assembly, &rmb);
2523 if (tb->generic_params)
2524 parent = create_generic_typespec (assembly, tb);
2526 parent = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)rmb.type));
2528 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2531 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
2536 mono_image_get_varargs_method_token (MonoDynamicImage *assembly, guint32 original,
2537 const gchar *name, guint32 sig)
2539 MonoDynamicTable *table;
2543 table = &assembly->tables [MONO_TABLE_MEMBERREF];
2545 if (assembly->save) {
2546 alloc_table (table, table->rows + 1);
2547 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
2548 values [MONO_MEMBERREF_CLASS] = original;
2549 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
2550 values [MONO_MEMBERREF_SIGNATURE] = sig;
2553 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
2560 encode_generic_method_definition_sig (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2564 guint32 nparams = mono_array_length (mb->generic_params);
2567 if (!assembly->save)
2570 sigbuffer_init (&buf, 32);
2572 sigbuffer_add_value (&buf, 0xa);
2573 sigbuffer_add_value (&buf, nparams);
2575 for (i = 0; i < nparams; i++) {
2576 sigbuffer_add_value (&buf, MONO_TYPE_MVAR);
2577 sigbuffer_add_value (&buf, i);
2580 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2581 sigbuffer_free (&buf);
2586 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb)
2588 MonoDynamicTable *table;
2590 guint32 token, mtoken = 0;
2592 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->methodspec, mb));
2596 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2598 mtoken = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2599 switch (mono_metadata_token_table (mtoken)) {
2600 case MONO_TABLE_MEMBERREF:
2601 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2603 case MONO_TABLE_METHOD:
2604 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2607 g_assert_not_reached ();
2610 if (assembly->save) {
2611 alloc_table (table, table->rows + 1);
2612 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2613 values [MONO_METHODSPEC_METHOD] = mtoken;
2614 values [MONO_METHODSPEC_SIGNATURE] = encode_generic_method_definition_sig (assembly, mb);
2617 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
2620 mono_g_hash_table_insert (assembly->methodspec, mb, GUINT_TO_POINTER(token));
2625 mono_image_get_methodbuilder_token (MonoDynamicImage *assembly, MonoReflectionMethodBuilder *mb, gboolean create_methodspec)
2629 if (mb->generic_params && create_methodspec)
2630 return mono_image_get_methodspec_token_for_generic_method_definition (assembly, mb);
2632 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2636 token = mono_image_get_methodref_token_for_methodbuilder (assembly, mb);
2637 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2642 mono_image_get_ctorbuilder_token (MonoDynamicImage *assembly, MonoReflectionCtorBuilder *mb)
2644 guint32 token, parent, sig;
2645 ReflectionMethodBuilder rmb;
2647 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mb->type;
2649 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, mb));
2653 g_assert (tb->generic_params);
2655 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
2657 parent = create_generic_typespec (assembly, tb);
2658 name = mono_string_to_utf8 (rmb.name);
2659 sig = method_builder_encode_signature (assembly, &rmb);
2661 token = mono_image_add_memberef_row (assembly, parent, name, sig);
2664 mono_g_hash_table_insert (assembly->handleref_managed, mb, GUINT_TO_POINTER(token));
2670 is_field_on_inst (MonoClassField *field)
2672 return (field->parent->generic_class && field->parent->generic_class->is_dynamic && ((MonoDynamicGenericClass*)field->parent->generic_class)->fields);
2676 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2679 get_field_on_inst_generic_type (MonoClassField *field)
2681 MonoClass *class, *gtd;
2682 MonoDynamicGenericClass *dgclass;
2685 g_assert (is_field_on_inst (field));
2687 dgclass = (MonoDynamicGenericClass*)field->parent->generic_class;
2689 if (field >= dgclass->fields && field - dgclass->fields < dgclass->count_fields) {
2690 field_index = field - dgclass->fields;
2691 return dgclass->field_generic_types [field_index];
2694 class = field->parent;
2695 gtd = class->generic_class->container_class;
2697 if (field >= class->fields && field - class->fields < class->field.count) {
2698 field_index = field - class->fields;
2699 return gtd->fields [field_index].type;
2702 g_assert_not_reached ();
2706 #ifndef DISABLE_REFLECTION_EMIT
2708 mono_image_get_fieldref_token (MonoDynamicImage *assembly, MonoReflectionField *f)
2712 MonoClassField *field;
2714 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2717 g_assert (f->field->parent);
2720 if (field->parent->generic_class && field->parent->generic_class->container_class && field->parent->generic_class->container_class->fields) {
2721 int index = field - field->parent->fields;
2722 type = field->parent->generic_class->container_class->fields [index].type;
2724 if (is_field_on_inst (f->field))
2725 type = get_field_on_inst_generic_type (f->field);
2727 type = f->field->type;
2729 token = mono_image_get_memberref_token (assembly, &f->field->parent->byval_arg,
2730 mono_field_get_name (f->field),
2731 fieldref_encode_signature (assembly, field->parent->image, type));
2732 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER(token));
2737 mono_image_get_field_on_inst_token (MonoDynamicImage *assembly, MonoReflectionFieldOnTypeBuilderInst *f)
2741 MonoGenericClass *gclass;
2742 MonoDynamicGenericClass *dgclass;
2746 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, f));
2749 if (is_sre_field_builder (mono_object_class (f->fb))) {
2750 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)f->fb;
2751 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2752 klass = mono_class_from_mono_type (type);
2753 gclass = type->data.generic_class;
2754 g_assert (gclass->is_dynamic);
2755 dgclass = (MonoDynamicGenericClass *) gclass;
2757 name = mono_string_to_utf8 (fb->name);
2758 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name,
2759 field_encode_signature (assembly, fb));
2761 } else if (is_sr_mono_field (mono_object_class (f->fb))) {
2763 MonoClassField *field = ((MonoReflectionField *)f->fb)->field;
2765 type = mono_reflection_type_get_handle ((MonoReflectionType*)f->inst);
2766 klass = mono_class_from_mono_type (type);
2768 sig = fieldref_encode_signature (assembly, field->parent->image, field->type);
2769 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, field->name, sig);
2771 char *name = mono_type_get_full_name (mono_object_class (f->fb));
2772 g_error ("mono_image_get_field_on_inst_token: don't know how to handle %s", name);
2775 mono_g_hash_table_insert (assembly->handleref_managed, f, GUINT_TO_POINTER (token));
2780 mono_image_get_ctor_on_inst_token (MonoDynamicImage *assembly, MonoReflectionCtorOnTypeBuilderInst *c, gboolean create_methodspec)
2784 MonoGenericClass *gclass;
2787 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2789 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, c));
2793 if (is_sre_ctor_builder (mono_object_class (c->cb))) {
2794 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder *)c->cb;
2795 MonoDynamicGenericClass *dgclass;
2796 ReflectionMethodBuilder rmb;
2799 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2800 klass = mono_class_from_mono_type (type);
2802 gclass = type->data.generic_class;
2803 g_assert (gclass->is_dynamic);
2804 dgclass = (MonoDynamicGenericClass *) gclass;
2806 reflection_methodbuilder_from_ctor_builder (&rmb, cb);
2808 name = mono_string_to_utf8 (rmb.name);
2810 sig = method_builder_encode_signature (assembly, &rmb);
2812 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2814 } else if (is_sr_mono_cmethod (mono_object_class (c->cb))) {
2815 MonoMethod *mm = ((MonoReflectionMethod *)c->cb)->method;
2817 type = mono_reflection_type_get_handle ((MonoReflectionType*)c->inst);
2818 klass = mono_class_from_mono_type (type);
2820 sig = method_encode_signature (assembly, mono_method_signature (mm));
2821 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2823 char *name = mono_type_get_full_name (mono_object_class (c->cb));
2824 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2828 mono_g_hash_table_insert (assembly->handleref_managed, c, GUINT_TO_POINTER (token));
2833 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst *m)
2836 MonoGenericContext tmp_context;
2837 MonoType **type_argv;
2838 MonoGenericInst *ginst;
2839 MonoMethod *method, *inflated;
2842 method = inflate_method (m->inst, (MonoObject*)m->mb);
2844 klass = method->klass;
2846 if (m->method_args == NULL)
2849 if (method->is_inflated)
2850 method = ((MonoMethodInflated *) method)->declaring;
2852 count = mono_array_length (m->method_args);
2854 type_argv = g_new0 (MonoType *, count);
2855 for (i = 0; i < count; i++) {
2856 MonoReflectionType *garg = mono_array_get (m->method_args, gpointer, i);
2857 type_argv [i] = mono_reflection_type_get_handle (garg);
2859 ginst = mono_metadata_get_generic_inst (count, type_argv);
2862 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
2863 tmp_context.method_inst = ginst;
2865 inflated = mono_class_inflate_generic_method (method, &tmp_context);
2870 mono_image_get_method_on_inst_token (MonoDynamicImage *assembly, MonoReflectionMethodOnTypeBuilderInst *m, gboolean create_methodspec)
2872 guint32 sig, token = 0;
2876 if (m->method_args) {
2877 MonoMethod *inflated;
2879 inflated = mono_reflection_method_on_tb_inst_get_handle (m);
2880 if (create_methodspec)
2881 token = mono_image_get_methodspec_token (assembly, inflated);
2883 token = mono_image_get_inflated_method_token (assembly, inflated);
2887 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, m));
2891 if (is_sre_method_builder (mono_object_class (m->mb))) {
2892 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)m->mb;
2893 MonoGenericClass *gclass;
2894 ReflectionMethodBuilder rmb;
2897 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2898 klass = mono_class_from_mono_type (type);
2899 gclass = type->data.generic_class;
2900 g_assert (gclass->is_dynamic);
2902 reflection_methodbuilder_from_method_builder (&rmb, mb);
2904 name = mono_string_to_utf8 (rmb.name);
2906 sig = method_builder_encode_signature (assembly, &rmb);
2908 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, name, sig);
2910 } else if (is_sr_mono_method (mono_object_class (m->mb))) {
2911 MonoMethod *mm = ((MonoReflectionMethod *)m->mb)->method;
2913 type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
2914 klass = mono_class_from_mono_type (type);
2916 sig = method_encode_signature (assembly, mono_method_signature (mm));
2917 token = mono_image_get_memberref_token (assembly, &klass->byval_arg, mm->name, sig);
2919 char *name = mono_type_get_full_name (mono_object_class (m->mb));
2920 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name);
2923 mono_g_hash_table_insert (assembly->handleref_managed, m, GUINT_TO_POINTER (token));
2928 encode_generic_method_sig (MonoDynamicImage *assembly, MonoGenericContext *context)
2932 guint32 nparams = context->method_inst->type_argc;
2935 if (!assembly->save)
2938 sigbuffer_init (&buf, 32);
2940 * FIXME: vararg, explicit_this, differenc call_conv values...
2942 sigbuffer_add_value (&buf, 0xa); /* FIXME FIXME FIXME */
2943 sigbuffer_add_value (&buf, nparams);
2945 for (i = 0; i < nparams; i++)
2946 encode_type (assembly, context->method_inst->type_argv [i], &buf);
2948 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
2949 sigbuffer_free (&buf);
2954 method_encode_methodspec (MonoDynamicImage *assembly, MonoMethod *method)
2956 MonoDynamicTable *table;
2958 guint32 token, mtoken = 0, sig;
2959 MonoMethodInflated *imethod;
2960 MonoMethod *declaring;
2962 table = &assembly->tables [MONO_TABLE_METHODSPEC];
2964 g_assert (method->is_inflated);
2965 imethod = (MonoMethodInflated *) method;
2966 declaring = imethod->declaring;
2968 sig = method_encode_signature (assembly, mono_method_signature (declaring));
2969 mtoken = mono_image_get_memberref_token (assembly, &method->klass->byval_arg, declaring->name, sig);
2971 if (!mono_method_signature (declaring)->generic_param_count)
2974 switch (mono_metadata_token_table (mtoken)) {
2975 case MONO_TABLE_MEMBERREF:
2976 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODREF;
2978 case MONO_TABLE_METHOD:
2979 mtoken = (mono_metadata_token_index (mtoken) << MONO_METHODDEFORREF_BITS) | MONO_METHODDEFORREF_METHODDEF;
2982 g_assert_not_reached ();
2985 sig = encode_generic_method_sig (assembly, mono_method_get_context (method));
2987 if (assembly->save) {
2988 alloc_table (table, table->rows + 1);
2989 values = table->values + table->next_idx * MONO_METHODSPEC_SIZE;
2990 values [MONO_METHODSPEC_METHOD] = mtoken;
2991 values [MONO_METHODSPEC_SIGNATURE] = sig;
2994 token = MONO_TOKEN_METHOD_SPEC | table->next_idx;
3001 mono_image_get_methodspec_token (MonoDynamicImage *assembly, MonoMethod *method)
3003 MonoMethodInflated *imethod;
3006 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->handleref, method));
3010 g_assert (method->is_inflated);
3011 imethod = (MonoMethodInflated *) method;
3013 if (mono_method_signature (imethod->declaring)->generic_param_count) {
3014 token = method_encode_methodspec (assembly, method);
3016 guint32 sig = method_encode_signature (
3017 assembly, mono_method_signature (imethod->declaring));
3018 token = mono_image_get_memberref_token (
3019 assembly, &method->klass->byval_arg, method->name, sig);
3022 g_hash_table_insert (assembly->handleref, method, GUINT_TO_POINTER(token));
3027 mono_image_get_inflated_method_token (MonoDynamicImage *assembly, MonoMethod *m)
3029 MonoMethodInflated *imethod = (MonoMethodInflated *) m;
3032 sig = method_encode_signature (assembly, mono_method_signature (imethod->declaring));
3033 token = mono_image_get_memberref_token (
3034 assembly, &m->klass->byval_arg, m->name, sig);
3040 create_generic_typespec (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb)
3042 MonoDynamicTable *table;
3051 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3052 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3053 * Because of this, we must not insert it into the `typeref' hash table.
3055 type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
3056 token = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->typespec, type));
3060 sigbuffer_init (&buf, 32);
3062 g_assert (tb->generic_params);
3063 klass = mono_class_from_mono_type (type);
3065 if (tb->generic_container)
3066 mono_reflection_create_generic_class (tb);
3068 sigbuffer_add_value (&buf, MONO_TYPE_GENERICINST);
3069 g_assert (klass->generic_container);
3070 sigbuffer_add_value (&buf, klass->byval_arg.type);
3071 sigbuffer_add_value (&buf, mono_image_typedef_or_ref_full (assembly, &klass->byval_arg, FALSE));
3073 count = mono_array_length (tb->generic_params);
3074 sigbuffer_add_value (&buf, count);
3075 for (i = 0; i < count; i++) {
3076 MonoReflectionGenericParam *gparam;
3078 gparam = mono_array_get (tb->generic_params, MonoReflectionGenericParam *, i);
3080 encode_type (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)gparam), &buf);
3083 table = &assembly->tables [MONO_TABLE_TYPESPEC];
3085 if (assembly->save) {
3086 token = sigbuffer_add_to_blob_cached (assembly, &buf);
3087 alloc_table (table, table->rows + 1);
3088 values = table->values + table->next_idx * MONO_TYPESPEC_SIZE;
3089 values [MONO_TYPESPEC_SIGNATURE] = token;
3091 sigbuffer_free (&buf);
3093 token = MONO_TYPEDEFORREF_TYPESPEC | (table->next_idx << MONO_TYPEDEFORREF_BITS);
3094 g_hash_table_insert (assembly->typespec, type, GUINT_TO_POINTER(token));
3100 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3103 add_custom_modifiers (MonoDynamicImage *assembly, MonoType *type, MonoArray *modreq, MonoArray *modopt)
3105 int i, count, len, pos;
3110 count += mono_array_length (modreq);
3112 count += mono_array_length (modopt);
3115 return mono_metadata_type_dup (NULL, type);
3117 len = MONO_SIZEOF_TYPE + ((gint32)count) * sizeof (MonoCustomMod);
3119 memcpy (t, type, MONO_SIZEOF_TYPE);
3121 t->num_mods = count;
3124 for (i = 0; i < mono_array_length (modreq); ++i) {
3125 MonoType *mod = mono_type_array_get_and_resolve (modreq, i);
3126 t->modifiers [pos].required = 1;
3127 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3132 for (i = 0; i < mono_array_length (modopt); ++i) {
3133 MonoType *mod = mono_type_array_get_and_resolve (modopt, i);
3134 t->modifiers [pos].required = 0;
3135 t->modifiers [pos].token = mono_image_typedef_or_ref (assembly, mod);
3144 mono_image_get_generic_field_token (MonoDynamicImage *assembly, MonoReflectionFieldBuilder *fb)
3146 MonoDynamicTable *table;
3148 MonoType *custom = NULL;
3150 guint32 token, pclass, parent, sig;
3153 token = GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly->handleref_managed, fb));
3157 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (fb->typeb));
3158 name = mono_string_to_utf8 (fb->name);
3160 /* fb->type does not include the custom modifiers */
3161 /* FIXME: We should do this in one place when a fieldbuilder is created */
3162 if (fb->modreq || fb->modopt) {
3163 custom = add_custom_modifiers (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type), fb->modreq, fb->modopt);
3164 sig = fieldref_encode_signature (assembly, NULL, custom);
3167 sig = fieldref_encode_signature (assembly, NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
3170 parent = create_generic_typespec (assembly, (MonoReflectionTypeBuilder *) fb->typeb);
3171 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_TYPEDEFORREF_TYPESPEC);
3173 pclass = MONO_MEMBERREF_PARENT_TYPESPEC;
3174 parent >>= MONO_TYPEDEFORREF_BITS;
3176 table = &assembly->tables [MONO_TABLE_MEMBERREF];
3178 if (assembly->save) {
3179 alloc_table (table, table->rows + 1);
3180 values = table->values + table->next_idx * MONO_MEMBERREF_SIZE;
3181 values [MONO_MEMBERREF_CLASS] = pclass | (parent << MONO_MEMBERREF_PARENT_BITS);
3182 values [MONO_MEMBERREF_NAME] = string_heap_insert (&assembly->sheap, name);
3183 values [MONO_MEMBERREF_SIGNATURE] = sig;
3186 token = MONO_TOKEN_MEMBER_REF | table->next_idx;
3188 mono_g_hash_table_insert (assembly->handleref_managed, fb, GUINT_TO_POINTER(token));
3194 mono_reflection_encode_sighelper (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3201 if (!assembly->save)
3204 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3205 g_assert (helper->type == 2);
3207 if (helper->arguments)
3208 nargs = mono_array_length (helper->arguments);
3212 size = 10 + (nargs * 10);
3214 sigbuffer_init (&buf, 32);
3216 /* Encode calling convention */
3217 /* Change Any to Standard */
3218 if ((helper->call_conv & 0x03) == 0x03)
3219 helper->call_conv = 0x01;
3220 /* explicit_this implies has_this */
3221 if (helper->call_conv & 0x40)
3222 helper->call_conv &= 0x20;
3224 if (helper->call_conv == 0) { /* Unmanaged */
3225 idx = helper->unmanaged_call_conv - 1;
3228 idx = helper->call_conv & 0x60; /* has_this + explicit_this */
3229 if (helper->call_conv & 0x02) /* varargs */
3233 sigbuffer_add_byte (&buf, idx);
3234 sigbuffer_add_value (&buf, nargs);
3235 encode_reflection_type (assembly, helper->return_type, &buf);
3236 for (i = 0; i < nargs; ++i) {
3237 MonoArray *modreqs = NULL;
3238 MonoArray *modopts = NULL;
3239 MonoReflectionType *pt;
3241 if (helper->modreqs && (i < mono_array_length (helper->modreqs)))
3242 modreqs = mono_array_get (helper->modreqs, MonoArray*, i);
3243 if (helper->modopts && (i < mono_array_length (helper->modopts)))
3244 modopts = mono_array_get (helper->modopts, MonoArray*, i);
3246 encode_custom_modifiers (assembly, modreqs, modopts, &buf);
3247 pt = mono_array_get (helper->arguments, MonoReflectionType*, i);
3248 encode_reflection_type (assembly, pt, &buf);
3250 idx = sigbuffer_add_to_blob_cached (assembly, &buf);
3251 sigbuffer_free (&buf);
3257 mono_image_get_sighelper_token (MonoDynamicImage *assembly, MonoReflectionSigHelper *helper)
3260 MonoDynamicTable *table;
3263 table = &assembly->tables [MONO_TABLE_STANDALONESIG];
3264 idx = table->next_idx ++;
3266 alloc_table (table, table->rows);
3267 values = table->values + idx * MONO_STAND_ALONE_SIGNATURE_SIZE;
3269 values [MONO_STAND_ALONE_SIGNATURE] =
3270 mono_reflection_encode_sighelper (assembly, helper);
3276 reflection_cc_to_file (int call_conv) {
3277 switch (call_conv & 0x3) {
3279 case 1: return MONO_CALL_DEFAULT;
3280 case 2: return MONO_CALL_VARARG;
3282 g_assert_not_reached ();
3286 #endif /* !DISABLE_REFLECTION_EMIT */
3290 MonoMethodSignature *sig;
3295 #ifndef DISABLE_REFLECTION_EMIT
3297 mono_image_get_array_token (MonoDynamicImage *assembly, MonoReflectionArrayMethod *m)
3302 MonoMethodSignature *sig;
3306 name = mono_string_to_utf8 (m->name);
3307 nparams = mono_array_length (m->parameters);
3308 sig = g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * nparams);
3310 sig->sentinelpos = -1;
3311 sig->call_convention = reflection_cc_to_file (m->call_conv);
3312 sig->param_count = nparams;
3313 sig->ret = m->ret ? mono_reflection_type_get_handle (m->ret): &mono_defaults.void_class->byval_arg;
3314 mtype = mono_reflection_type_get_handle (m->parent);
3315 for (i = 0; i < nparams; ++i)
3316 sig->params [i] = mono_type_array_get_and_resolve (m->parameters, i);
3318 for (tmp = assembly->array_methods; tmp; tmp = tmp->next) {
3320 if (strcmp (name, am->name) == 0 &&
3321 mono_metadata_type_equal (am->parent, mtype) &&
3322 mono_metadata_signature_equal (am->sig, sig)) {
3325 m->table_idx = am->token & 0xffffff;
3329 am = g_new0 (ArrayMethod, 1);
3333 am->token = mono_image_get_memberref_token (assembly, am->parent, name,
3334 method_encode_signature (assembly, sig));
3335 assembly->array_methods = g_list_prepend (assembly->array_methods, am);
3336 m->table_idx = am->token & 0xffffff;
3341 * Insert into the metadata tables all the info about the TypeBuilder tb.
3342 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3345 mono_image_get_type_info (MonoDomain *domain, MonoReflectionTypeBuilder *tb, MonoDynamicImage *assembly)
3347 MonoDynamicTable *table;
3349 int i, is_object = 0, is_system = 0;
3352 table = &assembly->tables [MONO_TABLE_TYPEDEF];
3353 values = table->values + tb->table_idx * MONO_TYPEDEF_SIZE;
3354 values [MONO_TYPEDEF_FLAGS] = tb->attrs;
3355 n = mono_string_to_utf8 (tb->name);
3356 if (strcmp (n, "Object") == 0)
3358 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, n);
3360 n = mono_string_to_utf8 (tb->nspace);
3361 if (strcmp (n, "System") == 0)
3363 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, n);
3365 if (tb->parent && !(is_system && is_object) &&
3366 !(tb->attrs & TYPE_ATTRIBUTE_INTERFACE)) { /* interfaces don't have a parent */
3367 values [MONO_TYPEDEF_EXTENDS] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle ((MonoReflectionType*)tb->parent));
3369 values [MONO_TYPEDEF_EXTENDS] = 0;
3371 values [MONO_TYPEDEF_FIELD_LIST] = assembly->tables [MONO_TABLE_FIELD].next_idx;
3372 values [MONO_TYPEDEF_METHOD_LIST] = assembly->tables [MONO_TABLE_METHOD].next_idx;
3375 * if we have explicitlayout or sequentiallayouts, output data in the
3376 * ClassLayout table.
3378 if (((tb->attrs & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT) &&
3379 ((tb->class_size > 0) || (tb->packing_size > 0))) {
3380 table = &assembly->tables [MONO_TABLE_CLASSLAYOUT];
3382 alloc_table (table, table->rows);
3383 values = table->values + table->rows * MONO_CLASS_LAYOUT_SIZE;
3384 values [MONO_CLASS_LAYOUT_PARENT] = tb->table_idx;
3385 values [MONO_CLASS_LAYOUT_CLASS_SIZE] = tb->class_size;
3386 values [MONO_CLASS_LAYOUT_PACKING_SIZE] = tb->packing_size;
3389 /* handle interfaces */
3390 if (tb->interfaces) {
3391 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
3393 table->rows += mono_array_length (tb->interfaces);
3394 alloc_table (table, table->rows);
3395 values = table->values + (i + 1) * MONO_INTERFACEIMPL_SIZE;
3396 for (i = 0; i < mono_array_length (tb->interfaces); ++i) {
3397 MonoReflectionType* iface = (MonoReflectionType*) mono_array_get (tb->interfaces, gpointer, i);
3398 values [MONO_INTERFACEIMPL_CLASS] = tb->table_idx;
3399 values [MONO_INTERFACEIMPL_INTERFACE] = mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (iface));
3400 values += MONO_INTERFACEIMPL_SIZE;
3406 table = &assembly->tables [MONO_TABLE_FIELD];
3407 table->rows += tb->num_fields;
3408 alloc_table (table, table->rows);
3409 for (i = 0; i < tb->num_fields; ++i)
3410 mono_image_get_field_info (
3411 mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i), assembly);
3414 /* handle constructors */
3416 table = &assembly->tables [MONO_TABLE_METHOD];
3417 table->rows += mono_array_length (tb->ctors);
3418 alloc_table (table, table->rows);
3419 for (i = 0; i < mono_array_length (tb->ctors); ++i)
3420 mono_image_get_ctor_info (domain,
3421 mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i), assembly);
3424 /* handle methods */
3426 table = &assembly->tables [MONO_TABLE_METHOD];
3427 table->rows += tb->num_methods;
3428 alloc_table (table, table->rows);
3429 for (i = 0; i < tb->num_methods; ++i)
3430 mono_image_get_method_info (
3431 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i), assembly);
3434 /* Do the same with properties etc.. */
3435 if (tb->events && mono_array_length (tb->events)) {
3436 table = &assembly->tables [MONO_TABLE_EVENT];
3437 table->rows += mono_array_length (tb->events);
3438 alloc_table (table, table->rows);
3439 table = &assembly->tables [MONO_TABLE_EVENTMAP];
3441 alloc_table (table, table->rows);
3442 values = table->values + table->rows * MONO_EVENT_MAP_SIZE;
3443 values [MONO_EVENT_MAP_PARENT] = tb->table_idx;
3444 values [MONO_EVENT_MAP_EVENTLIST] = assembly->tables [MONO_TABLE_EVENT].next_idx;
3445 for (i = 0; i < mono_array_length (tb->events); ++i)
3446 mono_image_get_event_info (
3447 mono_array_get (tb->events, MonoReflectionEventBuilder*, i), assembly);
3449 if (tb->properties && mono_array_length (tb->properties)) {
3450 table = &assembly->tables [MONO_TABLE_PROPERTY];
3451 table->rows += mono_array_length (tb->properties);
3452 alloc_table (table, table->rows);
3453 table = &assembly->tables [MONO_TABLE_PROPERTYMAP];
3455 alloc_table (table, table->rows);
3456 values = table->values + table->rows * MONO_PROPERTY_MAP_SIZE;
3457 values [MONO_PROPERTY_MAP_PARENT] = tb->table_idx;
3458 values [MONO_PROPERTY_MAP_PROPERTY_LIST] = assembly->tables [MONO_TABLE_PROPERTY].next_idx;
3459 for (i = 0; i < mono_array_length (tb->properties); ++i)
3460 mono_image_get_property_info (
3461 mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i), assembly);
3464 /* handle generic parameters */
3465 if (tb->generic_params) {
3466 table = &assembly->tables [MONO_TABLE_GENERICPARAM];
3467 table->rows += mono_array_length (tb->generic_params);
3468 alloc_table (table, table->rows);
3469 for (i = 0; i < mono_array_length (tb->generic_params); ++i) {
3470 guint32 owner = MONO_TYPEORMETHOD_TYPE | (tb->table_idx << MONO_TYPEORMETHOD_BITS);
3472 mono_image_get_generic_param_info (
3473 mono_array_get (tb->generic_params, MonoReflectionGenericParam*, i), owner, assembly);
3477 mono_image_add_decl_security (assembly,
3478 mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx), tb->permissions);
3481 MonoDynamicTable *ntable;
3483 ntable = &assembly->tables [MONO_TABLE_NESTEDCLASS];
3484 ntable->rows += mono_array_length (tb->subtypes);
3485 alloc_table (ntable, ntable->rows);
3486 values = ntable->values + ntable->next_idx * MONO_NESTED_CLASS_SIZE;
3488 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
3489 MonoReflectionTypeBuilder *subtype = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
3491 values [MONO_NESTED_CLASS_NESTED] = subtype->table_idx;
3492 values [MONO_NESTED_CLASS_ENCLOSING] = tb->table_idx;
3493 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3494 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3495 mono_string_to_utf8 (tb->name), tb->table_idx,
3496 ntable->next_idx, ntable->rows);*/
3497 values += MONO_NESTED_CLASS_SIZE;
3505 collect_types (GPtrArray *types, MonoReflectionTypeBuilder *type)
3509 g_ptr_array_add (types, type); /* FIXME: GC object added to unmanaged memory */
3511 if (!type->subtypes)
3514 for (i = 0; i < mono_array_length (type->subtypes); ++i) {
3515 MonoReflectionTypeBuilder *subtype = mono_array_get (type->subtypes, MonoReflectionTypeBuilder*, i);
3516 collect_types (types, subtype);
3521 compare_types_by_table_idx (MonoReflectionTypeBuilder **type1, MonoReflectionTypeBuilder **type2)
3523 if ((*type1)->table_idx < (*type2)->table_idx)
3526 if ((*type1)->table_idx > (*type2)->table_idx)
3533 params_add_cattrs (MonoDynamicImage *assembly, MonoArray *pinfo) {
3538 for (i = 0; i < mono_array_length (pinfo); ++i) {
3539 MonoReflectionParamBuilder *pb;
3540 pb = mono_array_get (pinfo, MonoReflectionParamBuilder *, i);
3543 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PARAMDEF, pb->cattrs);
3548 type_add_cattrs (MonoDynamicImage *assembly, MonoReflectionTypeBuilder *tb) {
3551 mono_image_add_cattrs (assembly, tb->table_idx, MONO_CUSTOM_ATTR_TYPEDEF, tb->cattrs);
3553 for (i = 0; i < tb->num_fields; ++i) {
3554 MonoReflectionFieldBuilder* fb;
3555 fb = mono_array_get (tb->fields, MonoReflectionFieldBuilder*, i);
3556 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3560 for (i = 0; i < mono_array_length (tb->events); ++i) {
3561 MonoReflectionEventBuilder* eb;
3562 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
3563 mono_image_add_cattrs (assembly, eb->table_idx, MONO_CUSTOM_ATTR_EVENT, eb->cattrs);
3566 if (tb->properties) {
3567 for (i = 0; i < mono_array_length (tb->properties); ++i) {
3568 MonoReflectionPropertyBuilder* pb;
3569 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
3570 mono_image_add_cattrs (assembly, pb->table_idx, MONO_CUSTOM_ATTR_PROPERTY, pb->cattrs);
3574 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
3575 MonoReflectionCtorBuilder* cb;
3576 cb = mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i);
3577 mono_image_add_cattrs (assembly, cb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, cb->cattrs);
3578 params_add_cattrs (assembly, cb->pinfo);
3583 for (i = 0; i < tb->num_methods; ++i) {
3584 MonoReflectionMethodBuilder* mb;
3585 mb = mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
3586 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3587 params_add_cattrs (assembly, mb->pinfo);
3592 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3593 type_add_cattrs (assembly, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i));
3598 module_add_cattrs (MonoDynamicImage *assembly, MonoReflectionModuleBuilder *moduleb)
3602 mono_image_add_cattrs (assembly, moduleb->table_idx, MONO_CUSTOM_ATTR_MODULE, moduleb->cattrs);
3604 if (moduleb->global_methods) {
3605 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
3606 MonoReflectionMethodBuilder* mb = mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i);
3607 mono_image_add_cattrs (assembly, mb->table_idx, MONO_CUSTOM_ATTR_METHODDEF, mb->cattrs);
3608 params_add_cattrs (assembly, mb->pinfo);
3612 if (moduleb->global_fields) {
3613 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i) {
3614 MonoReflectionFieldBuilder *fb = mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i);
3615 mono_image_add_cattrs (assembly, fb->table_idx, MONO_CUSTOM_ATTR_FIELDDEF, fb->cattrs);
3619 if (moduleb->types) {
3620 for (i = 0; i < moduleb->num_types; ++i)
3621 type_add_cattrs (assembly, mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i));
3626 mono_image_fill_file_table (MonoDomain *domain, MonoReflectionModule *module, MonoDynamicImage *assembly)
3628 MonoDynamicTable *table;
3632 char *b = blob_size;
3635 table = &assembly->tables [MONO_TABLE_FILE];
3637 alloc_table (table, table->rows);
3638 values = table->values + table->next_idx * MONO_FILE_SIZE;
3639 values [MONO_FILE_FLAGS] = FILE_CONTAINS_METADATA;
3640 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, module->image->module_name);
3641 if (module->image->dynamic) {
3642 /* This depends on the fact that the main module is emitted last */
3643 dir = mono_string_to_utf8 (((MonoReflectionModuleBuilder*)module)->assemblyb->dir);
3644 path = g_strdup_printf ("%s%c%s", dir, G_DIR_SEPARATOR, module->image->module_name);
3647 path = g_strdup (module->image->name);
3649 mono_sha1_get_digest_from_file (path, hash);
3652 mono_metadata_encode_value (20, b, &b);
3653 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
3654 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
3659 mono_image_fill_module_table (MonoDomain *domain, MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly)
3661 MonoDynamicTable *table;
3664 table = &assembly->tables [MONO_TABLE_MODULE];
3665 mb->table_idx = table->next_idx ++;
3666 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_NAME] = string_heap_insert_mstring (&assembly->sheap, mb->module.name);
3667 i = mono_image_add_stream_data (&assembly->guid, mono_array_addr (mb->guid, char, 0), 16);
3670 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_GENERATION] = 0;
3671 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_MVID] = i;
3672 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENC] = 0;
3673 table->values [mb->table_idx * MONO_MODULE_SIZE + MONO_MODULE_ENCBASE] = 0;
3677 mono_image_fill_export_table_from_class (MonoDomain *domain, MonoClass *klass,
3678 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3680 MonoDynamicTable *table;
3684 visib = klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3685 if (! ((visib & TYPE_ATTRIBUTE_PUBLIC) || (visib & TYPE_ATTRIBUTE_NESTED_PUBLIC)))
3688 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3690 alloc_table (table, table->rows);
3691 values = table->values + table->next_idx * MONO_EXP_TYPE_SIZE;
3693 values [MONO_EXP_TYPE_FLAGS] = klass->flags;
3694 values [MONO_EXP_TYPE_TYPEDEF] = klass->type_token;
3695 if (klass->nested_in)
3696 values [MONO_EXP_TYPE_IMPLEMENTATION] = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3698 values [MONO_EXP_TYPE_IMPLEMENTATION] = (module_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_FILE;
3699 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3700 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3702 res = table->next_idx;
3706 /* Emit nested types */
3707 if (klass->ext && klass->ext->nested_classes) {
3710 for (tmp = klass->ext->nested_classes; tmp; tmp = tmp->next)
3711 mono_image_fill_export_table_from_class (domain, tmp->data, module_index, table->next_idx - 1, assembly);
3718 mono_image_fill_export_table (MonoDomain *domain, MonoReflectionTypeBuilder *tb,
3719 guint32 module_index, guint32 parent_index, MonoDynamicImage *assembly)
3724 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
3726 klass->type_token = mono_metadata_make_token (MONO_TABLE_TYPEDEF, tb->table_idx);
3728 idx = mono_image_fill_export_table_from_class (domain, klass, module_index,
3729 parent_index, assembly);
3733 * We need to do this ourselves since klass->nested_classes is not set up.
3736 for (i = 0; i < mono_array_length (tb->subtypes); ++i)
3737 mono_image_fill_export_table (domain, mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i), module_index, idx, assembly);
3742 mono_image_fill_export_table_from_module (MonoDomain *domain, MonoReflectionModule *module,
3743 guint32 module_index, MonoDynamicImage *assembly)
3745 MonoImage *image = module->image;
3749 t = &image->tables [MONO_TABLE_TYPEDEF];
3751 for (i = 0; i < t->rows; ++i) {
3752 MonoClass *klass = mono_class_get (image, mono_metadata_make_token (MONO_TABLE_TYPEDEF, i + 1));
3754 if (klass->flags & TYPE_ATTRIBUTE_PUBLIC)
3755 mono_image_fill_export_table_from_class (domain, klass, module_index, 0, assembly);
3760 add_exported_type (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly, MonoClass *klass, guint32 parent_index)
3762 MonoDynamicTable *table;
3764 guint32 scope, scope_idx, impl, current_idx;
3765 gboolean forwarder = TRUE;
3766 gpointer iter = NULL;
3769 if (klass->nested_in) {
3770 impl = (parent_index << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_EXP_TYPE;
3773 scope = resolution_scope_from_image (assembly, klass->image);
3774 g_assert ((scope & MONO_RESOLTION_SCOPE_MASK) == MONO_RESOLTION_SCOPE_ASSEMBLYREF);
3775 scope_idx = scope >> MONO_RESOLTION_SCOPE_BITS;
3776 impl = (scope_idx << MONO_IMPLEMENTATION_BITS) + MONO_IMPLEMENTATION_ASSEMBLYREF;
3779 table = &assembly->tables [MONO_TABLE_EXPORTEDTYPE];
3782 alloc_table (table, table->rows);
3783 current_idx = table->next_idx;
3784 values = table->values + current_idx * MONO_EXP_TYPE_SIZE;
3786 values [MONO_EXP_TYPE_FLAGS] = forwarder ? TYPE_ATTRIBUTE_FORWARDER : 0;
3787 values [MONO_EXP_TYPE_TYPEDEF] = 0;
3788 values [MONO_EXP_TYPE_IMPLEMENTATION] = impl;
3789 values [MONO_EXP_TYPE_NAME] = string_heap_insert (&assembly->sheap, klass->name);
3790 values [MONO_EXP_TYPE_NAMESPACE] = string_heap_insert (&assembly->sheap, klass->name_space);
3794 while ((nested = mono_class_get_nested_types (klass, &iter)))
3795 add_exported_type (assemblyb, assembly, nested, current_idx);
3799 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder *assemblyb, MonoDynamicImage *assembly)
3804 if (!assemblyb->type_forwarders)
3807 for (i = 0; i < mono_array_length (assemblyb->type_forwarders); ++i) {
3808 MonoReflectionType *t = mono_array_get (assemblyb->type_forwarders, MonoReflectionType *, i);
3813 type = mono_reflection_type_get_handle (t);
3816 klass = mono_class_from_mono_type (type);
3818 add_exported_type (assemblyb, assembly, klass, 0);
3822 #define align_pointer(base,p)\
3824 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3826 (p) += 4 - (__diff & 3);\
3830 compare_constants (const void *a, const void *b)
3832 const guint32 *a_values = a;
3833 const guint32 *b_values = b;
3834 return a_values [MONO_CONSTANT_PARENT] - b_values [MONO_CONSTANT_PARENT];
3838 compare_semantics (const void *a, const void *b)
3840 const guint32 *a_values = a;
3841 const guint32 *b_values = b;
3842 int assoc = a_values [MONO_METHOD_SEMA_ASSOCIATION] - b_values [MONO_METHOD_SEMA_ASSOCIATION];
3845 return a_values [MONO_METHOD_SEMA_SEMANTICS] - b_values [MONO_METHOD_SEMA_SEMANTICS];
3849 compare_custom_attrs (const void *a, const void *b)
3851 const guint32 *a_values = a;
3852 const guint32 *b_values = b;
3854 return a_values [MONO_CUSTOM_ATTR_PARENT] - b_values [MONO_CUSTOM_ATTR_PARENT];
3858 compare_field_marshal (const void *a, const void *b)
3860 const guint32 *a_values = a;
3861 const guint32 *b_values = b;
3863 return a_values [MONO_FIELD_MARSHAL_PARENT] - b_values [MONO_FIELD_MARSHAL_PARENT];
3867 compare_nested (const void *a, const void *b)
3869 const guint32 *a_values = a;
3870 const guint32 *b_values = b;
3872 return a_values [MONO_NESTED_CLASS_NESTED] - b_values [MONO_NESTED_CLASS_NESTED];
3876 compare_genericparam (const void *a, const void *b)
3878 const GenericParamTableEntry **a_entry = (const GenericParamTableEntry **) a;
3879 const GenericParamTableEntry **b_entry = (const GenericParamTableEntry **) b;
3881 if ((*b_entry)->owner == (*a_entry)->owner)
3883 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*a_entry)->gparam)) -
3884 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType*)(*b_entry)->gparam));
3886 return (*a_entry)->owner - (*b_entry)->owner;
3890 compare_declsecurity_attrs (const void *a, const void *b)
3892 const guint32 *a_values = a;
3893 const guint32 *b_values = b;
3895 return a_values [MONO_DECL_SECURITY_PARENT] - b_values [MONO_DECL_SECURITY_PARENT];
3899 compare_interface_impl (const void *a, const void *b)
3901 const guint32 *a_values = a;
3902 const guint32 *b_values = b;
3904 int klass = a_values [MONO_INTERFACEIMPL_CLASS] - b_values [MONO_INTERFACEIMPL_CLASS];
3908 return a_values [MONO_INTERFACEIMPL_INTERFACE] - b_values [MONO_INTERFACEIMPL_INTERFACE];
3912 pad_heap (MonoDynamicStream *sh)
3914 if (sh->index & 3) {
3915 int sz = 4 - (sh->index & 3);
3916 memset (sh->data + sh->index, 0, sz);
3923 MonoDynamicStream *stream;
3927 * build_compressed_metadata() fills in the blob of data that represents the
3928 * raw metadata as it will be saved in the PE file. The five streams are output
3929 * and the metadata tables are comnpressed from the guint32 array representation,
3930 * to the compressed on-disk format.
3933 build_compressed_metadata (MonoDynamicImage *assembly)
3935 MonoDynamicTable *table;
3937 guint64 valid_mask = 0;
3938 guint64 sorted_mask;
3939 guint32 heapt_size = 0;
3940 guint32 meta_size = 256; /* allow for header and other stuff */
3941 guint32 table_offset;
3942 guint32 ntables = 0;
3948 struct StreamDesc stream_desc [5];
3950 qsort (assembly->gen_params->pdata, assembly->gen_params->len, sizeof (gpointer), compare_genericparam);
3951 for (i = 0; i < assembly->gen_params->len; i++){
3952 GenericParamTableEntry *entry = g_ptr_array_index (assembly->gen_params, i);
3953 write_generic_param_entry (assembly, entry);
3956 stream_desc [0].name = "#~";
3957 stream_desc [0].stream = &assembly->tstream;
3958 stream_desc [1].name = "#Strings";
3959 stream_desc [1].stream = &assembly->sheap;
3960 stream_desc [2].name = "#US";
3961 stream_desc [2].stream = &assembly->us;
3962 stream_desc [3].name = "#Blob";
3963 stream_desc [3].stream = &assembly->blob;
3964 stream_desc [4].name = "#GUID";
3965 stream_desc [4].stream = &assembly->guid;
3967 /* tables that are sorted */
3968 sorted_mask = ((guint64)1 << MONO_TABLE_CONSTANT) | ((guint64)1 << MONO_TABLE_FIELDMARSHAL)
3969 | ((guint64)1 << MONO_TABLE_METHODSEMANTICS) | ((guint64)1 << MONO_TABLE_CLASSLAYOUT)
3970 | ((guint64)1 << MONO_TABLE_FIELDLAYOUT) | ((guint64)1 << MONO_TABLE_FIELDRVA)
3971 | ((guint64)1 << MONO_TABLE_IMPLMAP) | ((guint64)1 << MONO_TABLE_NESTEDCLASS)
3972 | ((guint64)1 << MONO_TABLE_METHODIMPL) | ((guint64)1 << MONO_TABLE_CUSTOMATTRIBUTE)
3973 | ((guint64)1 << MONO_TABLE_DECLSECURITY) | ((guint64)1 << MONO_TABLE_GENERICPARAM)
3974 | ((guint64)1 << MONO_TABLE_INTERFACEIMPL);
3976 /* Compute table sizes */
3977 /* the MonoImage has already been created in mono_image_basic_init() */
3978 meta = &assembly->image;
3980 /* sizes should be multiple of 4 */
3981 pad_heap (&assembly->blob);
3982 pad_heap (&assembly->guid);
3983 pad_heap (&assembly->sheap);
3984 pad_heap (&assembly->us);
3986 /* Setup the info used by compute_sizes () */
3987 meta->idx_blob_wide = assembly->blob.index >= 65536 ? 1 : 0;
3988 meta->idx_guid_wide = assembly->guid.index >= 65536 ? 1 : 0;
3989 meta->idx_string_wide = assembly->sheap.index >= 65536 ? 1 : 0;
3991 meta_size += assembly->blob.index;
3992 meta_size += assembly->guid.index;
3993 meta_size += assembly->sheap.index;
3994 meta_size += assembly->us.index;
3996 for (i=0; i < MONO_TABLE_NUM; ++i)
3997 meta->tables [i].rows = assembly->tables [i].rows;
3999 for (i = 0; i < MONO_TABLE_NUM; i++){
4000 if (meta->tables [i].rows == 0)
4002 valid_mask |= (guint64)1 << i;
4004 meta->tables [i].row_size = mono_metadata_compute_size (
4005 meta, i, &meta->tables [i].size_bitfield);
4006 heapt_size += meta->tables [i].row_size * meta->tables [i].rows;
4008 heapt_size += 24; /* #~ header size */
4009 heapt_size += ntables * 4;
4010 /* make multiple of 4 */
4013 meta_size += heapt_size;
4014 meta->raw_metadata = g_malloc0 (meta_size);
4015 p = (unsigned char*)meta->raw_metadata;
4016 /* the metadata signature */
4017 *p++ = 'B'; *p++ = 'S'; *p++ = 'J'; *p++ = 'B';
4018 /* version numbers and 4 bytes reserved */
4019 int16val = (guint16*)p;
4020 *int16val++ = GUINT16_TO_LE (meta->md_version_major);
4021 *int16val = GUINT16_TO_LE (meta->md_version_minor);
4023 /* version string */
4024 int32val = (guint32*)p;
4025 *int32val = GUINT32_TO_LE ((strlen (meta->version) + 3) & (~3)); /* needs to be multiple of 4 */
4027 memcpy (p, meta->version, strlen (meta->version));
4028 p += GUINT32_FROM_LE (*int32val);
4029 align_pointer (meta->raw_metadata, p);
4030 int16val = (guint16*)p;
4031 *int16val++ = GUINT16_TO_LE (0); /* flags must be 0 */
4032 *int16val = GUINT16_TO_LE (5); /* number of streams */
4036 * write the stream info.
4038 table_offset = (p - (unsigned char*)meta->raw_metadata) + 5 * 8 + 40; /* room needed for stream headers */
4039 table_offset += 3; table_offset &= ~3;
4041 assembly->tstream.index = heapt_size;
4042 for (i = 0; i < 5; ++i) {
4043 int32val = (guint32*)p;
4044 stream_desc [i].stream->offset = table_offset;
4045 *int32val++ = GUINT32_TO_LE (table_offset);
4046 *int32val = GUINT32_TO_LE (stream_desc [i].stream->index);
4047 table_offset += GUINT32_FROM_LE (*int32val);
4048 table_offset += 3; table_offset &= ~3;
4050 strcpy ((char*)p, stream_desc [i].name);
4051 p += strlen (stream_desc [i].name) + 1;
4052 align_pointer (meta->raw_metadata, p);
4055 * now copy the data, the table stream header and contents goes first.
4057 g_assert ((p - (unsigned char*)meta->raw_metadata) < assembly->tstream.offset);
4058 p = (guchar*)meta->raw_metadata + assembly->tstream.offset;
4059 int32val = (guint32*)p;
4060 *int32val = GUINT32_TO_LE (0); /* reserved */
4063 *p++ = 2; /* version */
4066 if (meta->idx_string_wide)
4068 if (meta->idx_guid_wide)
4070 if (meta->idx_blob_wide)
4073 *p++ = 1; /* reserved */
4074 int64val = (guint64*)p;
4075 *int64val++ = GUINT64_TO_LE (valid_mask);
4076 *int64val++ = GUINT64_TO_LE (valid_mask & sorted_mask); /* bitvector of sorted tables */
4078 int32val = (guint32*)p;
4079 for (i = 0; i < MONO_TABLE_NUM; i++){
4080 if (meta->tables [i].rows == 0)
4082 *int32val++ = GUINT32_TO_LE (meta->tables [i].rows);
4084 p = (unsigned char*)int32val;
4086 /* sort the tables that still need sorting */
4087 table = &assembly->tables [MONO_TABLE_CONSTANT];
4089 qsort (table->values + MONO_CONSTANT_SIZE, table->rows, sizeof (guint32) * MONO_CONSTANT_SIZE, compare_constants);
4090 table = &assembly->tables [MONO_TABLE_METHODSEMANTICS];
4092 qsort (table->values + MONO_METHOD_SEMA_SIZE, table->rows, sizeof (guint32) * MONO_METHOD_SEMA_SIZE, compare_semantics);
4093 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4095 qsort (table->values + MONO_CUSTOM_ATTR_SIZE, table->rows, sizeof (guint32) * MONO_CUSTOM_ATTR_SIZE, compare_custom_attrs);
4096 table = &assembly->tables [MONO_TABLE_FIELDMARSHAL];
4098 qsort (table->values + MONO_FIELD_MARSHAL_SIZE, table->rows, sizeof (guint32) * MONO_FIELD_MARSHAL_SIZE, compare_field_marshal);
4099 table = &assembly->tables [MONO_TABLE_NESTEDCLASS];
4101 qsort (table->values + MONO_NESTED_CLASS_SIZE, table->rows, sizeof (guint32) * MONO_NESTED_CLASS_SIZE, compare_nested);
4102 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4103 table = &assembly->tables [MONO_TABLE_DECLSECURITY];
4105 qsort (table->values + MONO_DECL_SECURITY_SIZE, table->rows, sizeof (guint32) * MONO_DECL_SECURITY_SIZE, compare_declsecurity_attrs);
4106 table = &assembly->tables [MONO_TABLE_INTERFACEIMPL];
4108 qsort (table->values + MONO_INTERFACEIMPL_SIZE, table->rows, sizeof (guint32) * MONO_INTERFACEIMPL_SIZE, compare_interface_impl);
4110 /* compress the tables */
4111 for (i = 0; i < MONO_TABLE_NUM; i++){
4114 guint32 bitfield = meta->tables [i].size_bitfield;
4115 if (!meta->tables [i].rows)
4117 if (assembly->tables [i].columns != mono_metadata_table_count (bitfield))
4118 g_error ("col count mismatch in %d: %d %d", i, assembly->tables [i].columns, mono_metadata_table_count (bitfield));
4119 meta->tables [i].base = (char*)p;
4120 for (row = 1; row <= meta->tables [i].rows; ++row) {
4121 values = assembly->tables [i].values + row * assembly->tables [i].columns;
4122 for (col = 0; col < assembly->tables [i].columns; ++col) {
4123 switch (mono_metadata_table_size (bitfield, col)) {
4125 *p++ = values [col];
4128 *p++ = values [col] & 0xff;
4129 *p++ = (values [col] >> 8) & 0xff;
4132 *p++ = values [col] & 0xff;
4133 *p++ = (values [col] >> 8) & 0xff;
4134 *p++ = (values [col] >> 16) & 0xff;
4135 *p++ = (values [col] >> 24) & 0xff;
4138 g_assert_not_reached ();
4142 g_assert ((p - (const unsigned char*)meta->tables [i].base) == (meta->tables [i].rows * meta->tables [i].row_size));
4145 g_assert (assembly->guid.offset + assembly->guid.index < meta_size);
4146 memcpy (meta->raw_metadata + assembly->sheap.offset, assembly->sheap.data, assembly->sheap.index);
4147 memcpy (meta->raw_metadata + assembly->us.offset, assembly->us.data, assembly->us.index);
4148 memcpy (meta->raw_metadata + assembly->blob.offset, assembly->blob.data, assembly->blob.index);
4149 memcpy (meta->raw_metadata + assembly->guid.offset, assembly->guid.data, assembly->guid.index);
4151 assembly->meta_size = assembly->guid.offset + assembly->guid.index;
4155 * Some tables in metadata need to be sorted according to some criteria, but
4156 * when methods and fields are first created with reflection, they may be assigned a token
4157 * that doesn't correspond to the final token they will get assigned after the sorting.
4158 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4159 * with the reflection objects that represent them. Once all the tables are set up, the
4160 * reflection objects will contains the correct table index. fixup_method() will fixup the
4161 * tokens for the method with ILGenerator @ilgen.
4164 fixup_method (MonoReflectionILGen *ilgen, gpointer value, MonoDynamicImage *assembly)
4166 guint32 code_idx = GPOINTER_TO_UINT (value);
4167 MonoReflectionILTokenInfo *iltoken;
4168 MonoReflectionFieldBuilder *field;
4169 MonoReflectionCtorBuilder *ctor;
4170 MonoReflectionMethodBuilder *method;
4171 MonoReflectionTypeBuilder *tb;
4172 MonoReflectionArrayMethod *am;
4174 unsigned char *target;
4176 for (i = 0; i < ilgen->num_token_fixups; ++i) {
4177 iltoken = (MonoReflectionILTokenInfo *)mono_array_addr_with_size (ilgen->token_fixups, sizeof (MonoReflectionILTokenInfo), i);
4178 target = (guchar*)assembly->code.data + code_idx + iltoken->code_pos;
4179 switch (target [3]) {
4180 case MONO_TABLE_FIELD:
4181 if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4182 field = (MonoReflectionFieldBuilder *)iltoken->member;
4183 idx = field->table_idx;
4184 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4185 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4186 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->field_to_table_idx, f));
4188 g_assert_not_reached ();
4191 case MONO_TABLE_METHOD:
4192 if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4193 method = (MonoReflectionMethodBuilder *)iltoken->member;
4194 idx = method->table_idx;
4195 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4196 ctor = (MonoReflectionCtorBuilder *)iltoken->member;
4197 idx = ctor->table_idx;
4198 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4199 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod")) {
4200 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4201 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4203 g_assert_not_reached ();
4206 case MONO_TABLE_TYPEDEF:
4207 if (strcmp (iltoken->member->vtable->klass->name, "TypeBuilder"))
4208 g_assert_not_reached ();
4209 tb = (MonoReflectionTypeBuilder *)iltoken->member;
4210 idx = tb->table_idx;
4212 case MONO_TABLE_MEMBERREF:
4213 if (!strcmp (iltoken->member->vtable->klass->name, "MonoArrayMethod")) {
4214 am = (MonoReflectionArrayMethod*)iltoken->member;
4215 idx = am->table_idx;
4216 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoMethod") ||
4217 !strcmp (iltoken->member->vtable->klass->name, "MonoCMethod") ||
4218 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod") ||
4219 !strcmp (iltoken->member->vtable->klass->name, "MonoGenericCMethod")) {
4220 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4221 g_assert (m->klass->generic_class || m->klass->generic_container);
4223 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldBuilder")) {
4225 } else if (!strcmp (iltoken->member->vtable->klass->name, "MonoField")) {
4226 MonoClassField *f = ((MonoReflectionField*)iltoken->member)->field;
4227 g_assert (is_field_on_inst (f));
4229 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder") ||
4230 !strcmp (iltoken->member->vtable->klass->name, "ConstructorBuilder")) {
4232 } else if (!strcmp (iltoken->member->vtable->klass->name, "FieldOnTypeBuilderInst")) {
4234 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4236 } else if (!strcmp (iltoken->member->vtable->klass->name, "ConstructorOnTypeBuilderInst")) {
4239 g_assert_not_reached ();
4242 case MONO_TABLE_METHODSPEC:
4243 if (!strcmp (iltoken->member->vtable->klass->name, "MonoGenericMethod")) {
4244 MonoMethod *m = ((MonoReflectionMethod*)iltoken->member)->method;
4245 g_assert (mono_method_signature (m)->generic_param_count);
4247 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodBuilder")) {
4249 } else if (!strcmp (iltoken->member->vtable->klass->name, "MethodOnTypeBuilderInst")) {
4252 g_assert_not_reached ();
4256 g_error ("got unexpected table 0x%02x in fixup", target [3]);
4258 target [0] = idx & 0xff;
4259 target [1] = (idx >> 8) & 0xff;
4260 target [2] = (idx >> 16) & 0xff;
4267 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4268 * value is not known when the table is emitted.
4271 fixup_cattrs (MonoDynamicImage *assembly)
4273 MonoDynamicTable *table;
4275 guint32 type, i, idx, token;
4278 table = &assembly->tables [MONO_TABLE_CUSTOMATTRIBUTE];
4280 for (i = 0; i < table->rows; ++i) {
4281 values = table->values + ((i + 1) * MONO_CUSTOM_ATTR_SIZE);
4283 type = values [MONO_CUSTOM_ATTR_TYPE];
4284 if ((type & MONO_CUSTOM_ATTR_TYPE_MASK) == MONO_CUSTOM_ATTR_TYPE_METHODDEF) {
4285 idx = type >> MONO_CUSTOM_ATTR_TYPE_BITS;
4286 token = mono_metadata_make_token (MONO_TABLE_METHOD, idx);
4287 ctor = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4290 if (!strcmp (ctor->vtable->klass->name, "MonoCMethod")) {
4291 MonoMethod *m = ((MonoReflectionMethod*)ctor)->method;
4292 idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, m));
4293 values [MONO_CUSTOM_ATTR_TYPE] = (idx << MONO_CUSTOM_ATTR_TYPE_BITS) | MONO_CUSTOM_ATTR_TYPE_METHODDEF;
4300 assembly_add_resource_manifest (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc, guint32 implementation)
4302 MonoDynamicTable *table;
4305 table = &assembly->tables [MONO_TABLE_MANIFESTRESOURCE];
4307 alloc_table (table, table->rows);
4308 values = table->values + table->next_idx * MONO_MANIFEST_SIZE;
4309 values [MONO_MANIFEST_OFFSET] = rsrc->offset;
4310 values [MONO_MANIFEST_FLAGS] = rsrc->attrs;
4311 values [MONO_MANIFEST_NAME] = string_heap_insert_mstring (&assembly->sheap, rsrc->name);
4312 values [MONO_MANIFEST_IMPLEMENTATION] = implementation;
4317 assembly_add_resource (MonoReflectionModuleBuilder *mb, MonoDynamicImage *assembly, MonoReflectionResource *rsrc)
4319 MonoDynamicTable *table;
4323 char *b = blob_size;
4325 guint32 idx, offset;
4327 if (rsrc->filename) {
4328 name = mono_string_to_utf8 (rsrc->filename);
4329 sname = g_path_get_basename (name);
4331 table = &assembly->tables [MONO_TABLE_FILE];
4333 alloc_table (table, table->rows);
4334 values = table->values + table->next_idx * MONO_FILE_SIZE;
4335 values [MONO_FILE_FLAGS] = FILE_CONTAINS_NO_METADATA;
4336 values [MONO_FILE_NAME] = string_heap_insert (&assembly->sheap, sname);
4339 mono_sha1_get_digest_from_file (name, hash);
4340 mono_metadata_encode_value (20, b, &b);
4341 values [MONO_FILE_HASH_VALUE] = mono_image_add_stream_data (&assembly->blob, blob_size, b-blob_size);
4342 mono_image_add_stream_data (&assembly->blob, (char*)hash, 20);
4344 idx = table->next_idx++;
4346 idx = MONO_IMPLEMENTATION_FILE | (idx << MONO_IMPLEMENTATION_BITS);
4352 data = mono_array_addr (rsrc->data, char, 0);
4353 len = mono_array_length (rsrc->data);
4359 sizebuf [0] = offset; sizebuf [1] = offset >> 8;
4360 sizebuf [2] = offset >> 16; sizebuf [3] = offset >> 24;
4361 rsrc->offset = mono_image_add_stream_data (&assembly->resources, sizebuf, 4);
4362 mono_image_add_stream_data (&assembly->resources, data, len);
4366 * The entry should be emitted into the MANIFESTRESOURCE table of
4367 * the main module, but that needs to reference the FILE table
4368 * which isn't emitted yet.
4375 assembly_add_resource_manifest (mb, assembly, rsrc, idx);
4379 set_version_from_string (MonoString *version, guint32 *values)
4381 gchar *ver, *p, *str;
4384 values [MONO_ASSEMBLY_MAJOR_VERSION] = 0;
4385 values [MONO_ASSEMBLY_MINOR_VERSION] = 0;
4386 values [MONO_ASSEMBLY_REV_NUMBER] = 0;
4387 values [MONO_ASSEMBLY_BUILD_NUMBER] = 0;
4390 ver = str = mono_string_to_utf8 (version);
4391 for (i = 0; i < 4; ++i) {
4392 values [MONO_ASSEMBLY_MAJOR_VERSION + i] = strtol (ver, &p, 10);
4398 /* handle Revision and Build */
4408 load_public_key (MonoArray *pkey, MonoDynamicImage *assembly) {
4412 char *b = blob_size;
4417 len = mono_array_length (pkey);
4418 mono_metadata_encode_value (len, b, &b);
4419 token = mono_image_add_stream_data (&assembly->blob, blob_size, b - blob_size);
4420 mono_image_add_stream_data (&assembly->blob, mono_array_addr (pkey, char, 0), len);
4422 assembly->public_key = g_malloc (len);
4423 memcpy (assembly->public_key, mono_array_addr (pkey, char, 0), len);
4424 assembly->public_key_len = len;
4426 /* Special case: check for ECMA key (16 bytes) */
4427 if ((len == MONO_ECMA_KEY_LENGTH) && mono_is_ecma_key (mono_array_addr (pkey, char, 0), len)) {
4428 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4429 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH;
4430 } else if (len >= MONO_PUBLIC_KEY_HEADER_LENGTH + MONO_MINIMUM_PUBLIC_KEY_LENGTH) {
4431 /* minimum key size (in 2.0) is 384 bits */
4432 assembly->strong_name_size = len - MONO_PUBLIC_KEY_HEADER_LENGTH;
4434 /* FIXME - verifier */
4435 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len), (int)len);
4436 assembly->strong_name_size = MONO_DEFAULT_PUBLIC_KEY_LENGTH; /* to be safe */
4438 assembly->strong_name = g_malloc0 (assembly->strong_name_size);
4444 mono_image_emit_manifest (MonoReflectionModuleBuilder *moduleb)
4446 MonoDynamicTable *table;
4447 MonoDynamicImage *assembly;
4448 MonoReflectionAssemblyBuilder *assemblyb;
4452 guint32 module_index;
4454 assemblyb = moduleb->assemblyb;
4455 assembly = moduleb->dynamic_image;
4456 domain = mono_object_domain (assemblyb);
4458 /* Emit ASSEMBLY table */
4459 table = &assembly->tables [MONO_TABLE_ASSEMBLY];
4460 alloc_table (table, 1);
4461 values = table->values + MONO_ASSEMBLY_SIZE;
4462 values [MONO_ASSEMBLY_HASH_ALG] = assemblyb->algid? assemblyb->algid: ASSEMBLY_HASH_SHA1;
4463 values [MONO_ASSEMBLY_NAME] = string_heap_insert_mstring (&assembly->sheap, assemblyb->name);
4464 if (assemblyb->culture) {
4465 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert_mstring (&assembly->sheap, assemblyb->culture);
4467 values [MONO_ASSEMBLY_CULTURE] = string_heap_insert (&assembly->sheap, "");
4469 values [MONO_ASSEMBLY_PUBLIC_KEY] = load_public_key (assemblyb->public_key, assembly);
4470 values [MONO_ASSEMBLY_FLAGS] = assemblyb->flags;
4471 set_version_from_string (assemblyb->version, values);
4473 /* Emit FILE + EXPORTED_TYPE table */
4475 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4477 MonoReflectionModuleBuilder *file_module =
4478 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4479 if (file_module != moduleb) {
4480 mono_image_fill_file_table (domain, (MonoReflectionModule*)file_module, assembly);
4482 if (file_module->types) {
4483 for (j = 0; j < file_module->num_types; ++j) {
4484 MonoReflectionTypeBuilder *tb = mono_array_get (file_module->types, MonoReflectionTypeBuilder*, j);
4485 mono_image_fill_export_table (domain, tb, module_index, 0, assembly);
4490 if (assemblyb->loaded_modules) {
4491 for (i = 0; i < mono_array_length (assemblyb->loaded_modules); ++i) {
4492 MonoReflectionModule *file_module =
4493 mono_array_get (assemblyb->loaded_modules, MonoReflectionModule*, i);
4494 mono_image_fill_file_table (domain, file_module, assembly);
4496 mono_image_fill_export_table_from_module (domain, file_module, module_index, assembly);
4499 if (assemblyb->type_forwarders)
4500 mono_image_fill_export_table_from_type_forwarders (assemblyb, assembly);
4502 /* Emit MANIFESTRESOURCE table */
4504 for (i = 0; i < mono_array_length (assemblyb->modules); ++i) {
4506 MonoReflectionModuleBuilder *file_module =
4507 mono_array_get (assemblyb->modules, MonoReflectionModuleBuilder*, i);
4508 /* The table for the main module is emitted later */
4509 if (file_module != moduleb) {
4511 if (file_module->resources) {
4512 int len = mono_array_length (file_module->resources);
4513 for (j = 0; j < len; ++j) {
4514 MonoReflectionResource* res = (MonoReflectionResource*)mono_array_addr (file_module->resources, MonoReflectionResource, j);
4515 assembly_add_resource_manifest (file_module, assembly, res, MONO_IMPLEMENTATION_FILE | (module_index << MONO_IMPLEMENTATION_BITS));
4522 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4525 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4526 * for the modulebuilder @moduleb.
4527 * At the end of the process, method and field tokens are fixed up and the
4528 * on-disk compressed metadata representation is created.
4531 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4533 MonoDynamicTable *table;
4534 MonoDynamicImage *assembly;
4535 MonoReflectionAssemblyBuilder *assemblyb;
4541 assemblyb = moduleb->assemblyb;
4542 assembly = moduleb->dynamic_image;
4543 domain = mono_object_domain (assemblyb);
4545 if (assembly->text_rva)
4548 assembly->text_rva = START_TEXT_RVA;
4550 if (moduleb->is_main) {
4551 mono_image_emit_manifest (moduleb);
4554 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4555 table->rows = 1; /* .<Module> */
4557 alloc_table (table, table->rows);
4559 * Set the first entry.
4561 values = table->values + table->columns;
4562 values [MONO_TYPEDEF_FLAGS] = 0;
4563 values [MONO_TYPEDEF_NAME] = string_heap_insert (&assembly->sheap, "<Module>") ;
4564 values [MONO_TYPEDEF_NAMESPACE] = string_heap_insert (&assembly->sheap, "") ;
4565 values [MONO_TYPEDEF_EXTENDS] = 0;
4566 values [MONO_TYPEDEF_FIELD_LIST] = 1;
4567 values [MONO_TYPEDEF_METHOD_LIST] = 1;
4570 * handle global methods
4571 * FIXME: test what to do when global methods are defined in multiple modules.
4573 if (moduleb->global_methods) {
4574 table = &assembly->tables [MONO_TABLE_METHOD];
4575 table->rows += mono_array_length (moduleb->global_methods);
4576 alloc_table (table, table->rows);
4577 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i)
4578 mono_image_get_method_info (
4579 mono_array_get (moduleb->global_methods, MonoReflectionMethodBuilder*, i), assembly);
4581 if (moduleb->global_fields) {
4582 table = &assembly->tables [MONO_TABLE_FIELD];
4583 table->rows += mono_array_length (moduleb->global_fields);
4584 alloc_table (table, table->rows);
4585 for (i = 0; i < mono_array_length (moduleb->global_fields); ++i)
4586 mono_image_get_field_info (
4587 mono_array_get (moduleb->global_fields, MonoReflectionFieldBuilder*, i), assembly);
4590 table = &assembly->tables [MONO_TABLE_MODULE];
4591 alloc_table (table, 1);
4592 mono_image_fill_module_table (domain, moduleb, assembly);
4594 /* Collect all types into a list sorted by their table_idx */
4595 types = g_ptr_array_new ();
4598 for (i = 0; i < moduleb->num_types; ++i) {
4599 MonoReflectionTypeBuilder *type = mono_array_get (moduleb->types, MonoReflectionTypeBuilder*, i);
4600 collect_types (types, type);
4603 g_ptr_array_sort (types, (GCompareFunc)compare_types_by_table_idx);
4604 table = &assembly->tables [MONO_TABLE_TYPEDEF];
4605 table->rows += types->len;
4606 alloc_table (table, table->rows);
4609 * Emit type names + namespaces at one place inside the string heap,
4610 * so load_class_names () needs to touch fewer pages.
4612 for (i = 0; i < types->len; ++i) {
4613 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4614 string_heap_insert_mstring (&assembly->sheap, tb->nspace);
4616 for (i = 0; i < types->len; ++i) {
4617 MonoReflectionTypeBuilder *tb = g_ptr_array_index (types, i);
4618 string_heap_insert_mstring (&assembly->sheap, tb->name);
4621 for (i = 0; i < types->len; ++i) {
4622 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4623 mono_image_get_type_info (domain, type, assembly);
4627 * table->rows is already set above and in mono_image_fill_module_table.
4629 /* add all the custom attributes at the end, once all the indexes are stable */
4630 mono_image_add_cattrs (assembly, 1, MONO_CUSTOM_ATTR_ASSEMBLY, assemblyb->cattrs);
4632 /* CAS assembly permissions */
4633 if (assemblyb->permissions_minimum)
4634 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_minimum);
4635 if (assemblyb->permissions_optional)
4636 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_optional);
4637 if (assemblyb->permissions_refused)
4638 mono_image_add_decl_security (assembly, mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1), assemblyb->permissions_refused);
4640 module_add_cattrs (assembly, moduleb);
4643 mono_g_hash_table_foreach (assembly->token_fixups, (GHFunc)fixup_method, assembly);
4645 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4646 * the final tokens and don't need another fixup pass. */
4648 if (moduleb->global_methods) {
4649 for (i = 0; i < mono_array_length (moduleb->global_methods); ++i) {
4650 MonoReflectionMethodBuilder *mb = mono_array_get (
4651 moduleb->global_methods, MonoReflectionMethodBuilder*, i);
4652 mono_image_add_methodimpl (assembly, mb);
4656 for (i = 0; i < types->len; ++i) {
4657 MonoReflectionTypeBuilder *type = g_ptr_array_index (types, i);
4658 if (type->methods) {
4659 for (j = 0; j < type->num_methods; ++j) {
4660 MonoReflectionMethodBuilder *mb = mono_array_get (
4661 type->methods, MonoReflectionMethodBuilder*, j);
4663 mono_image_add_methodimpl (assembly, mb);
4668 g_ptr_array_free (types, TRUE);
4670 fixup_cattrs (assembly);
4673 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4676 mono_image_build_metadata (MonoReflectionModuleBuilder *moduleb)
4678 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4681 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4685 guint32 import_lookup_table;
4689 guint32 import_address_table_rva;
4697 #ifndef DISABLE_REFLECTION_EMIT
4700 * mono_image_insert_string:
4701 * @module: module builder object
4704 * Insert @str into the user string stream of @module.
4707 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
4709 MonoDynamicImage *assembly;
4714 MONO_ARCH_SAVE_REGS;
4716 if (!module->dynamic_image)
4717 mono_image_module_basic_init (module);
4719 assembly = module->dynamic_image;
4721 if (assembly->save) {
4722 mono_metadata_encode_value (1 | (str->length * 2), b, &b);
4723 idx = mono_image_add_stream_data (&assembly->us, buf, b-buf);
4724 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4726 char *swapped = g_malloc (2 * mono_string_length (str));
4727 const char *p = (const char*)mono_string_chars (str);
4729 swap_with_size (swapped, p, 2, mono_string_length (str));
4730 mono_image_add_stream_data (&assembly->us, swapped, str->length * 2);
4734 mono_image_add_stream_data (&assembly->us, (const char*)mono_string_chars (str), str->length * 2);
4736 mono_image_add_stream_data (&assembly->us, "", 1);
4738 idx = assembly->us.index ++;
4741 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (MONO_TOKEN_STRING | idx), str);
4743 return MONO_TOKEN_STRING | idx;
4747 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
4752 klass = obj->vtable->klass;
4753 if (strcmp (klass->name, "MonoMethod") == 0) {
4754 MonoMethod *method = ((MonoReflectionMethod *)obj)->method;
4755 MonoMethodSignature *sig, *old;
4756 guint32 sig_token, parent;
4759 g_assert (opt_param_types && (mono_method_signature (method)->sentinelpos >= 0));
4761 nargs = mono_array_length (opt_param_types);
4762 old = mono_method_signature (method);
4763 sig = mono_metadata_signature_alloc ( &assembly->image, old->param_count + nargs);
4765 sig->hasthis = old->hasthis;
4766 sig->explicit_this = old->explicit_this;
4767 sig->call_convention = old->call_convention;
4768 sig->generic_param_count = old->generic_param_count;
4769 sig->param_count = old->param_count + nargs;
4770 sig->sentinelpos = old->param_count;
4771 sig->ret = old->ret;
4773 for (i = 0; i < old->param_count; i++)
4774 sig->params [i] = old->params [i];
4776 for (i = 0; i < nargs; i++) {
4777 MonoReflectionType *rt = mono_array_get (opt_param_types, MonoReflectionType *, i);
4778 sig->params [old->param_count + i] = mono_reflection_type_get_handle (rt);
4781 parent = mono_image_typedef_or_ref (assembly, &method->klass->byval_arg);
4782 g_assert ((parent & MONO_TYPEDEFORREF_MASK) == MONO_MEMBERREF_PARENT_TYPEREF);
4783 parent >>= MONO_TYPEDEFORREF_BITS;
4785 parent <<= MONO_MEMBERREF_PARENT_BITS;
4786 parent |= MONO_MEMBERREF_PARENT_TYPEREF;
4788 sig_token = method_encode_signature (assembly, sig);
4789 token = mono_image_get_varargs_method_token (assembly, parent, method->name, sig_token);
4790 } else if (strcmp (klass->name, "MethodBuilder") == 0) {
4791 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4792 ReflectionMethodBuilder rmb;
4793 guint32 parent, sig;
4796 reflection_methodbuilder_from_method_builder (&rmb, mb);
4797 rmb.opt_types = opt_param_types;
4799 sig = method_builder_encode_signature (assembly, &rmb);
4801 parent = mono_image_create_token (assembly, obj, TRUE, TRUE);
4802 g_assert (mono_metadata_token_table (parent) == MONO_TABLE_METHOD);
4804 parent = mono_metadata_token_index (parent) << MONO_MEMBERREF_PARENT_BITS;
4805 parent |= MONO_MEMBERREF_PARENT_METHODDEF;
4807 name = mono_string_to_utf8 (rmb.name);
4808 token = mono_image_get_varargs_method_token (
4809 assembly, parent, name, sig);
4812 g_error ("requested method token for %s\n", klass->name);
4819 * mono_image_create_token:
4820 * @assembly: a dynamic assembly
4822 * @register_token: Whenever to register the token in the assembly->tokens hash.
4824 * Get a token to insert in the IL code stream for the given MemberInfo.
4825 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4826 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4830 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
4831 gboolean create_methodspec, gboolean register_token)
4836 klass = obj->vtable->klass;
4838 /* Check for user defined reflection objects */
4839 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4840 if (klass->image != mono_defaults.corlib || (strcmp (klass->name, "TypeDelegator") == 0))
4841 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4843 if (strcmp (klass->name, "MethodBuilder") == 0) {
4844 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
4845 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4847 if (tb->module->dynamic_image == assembly && !tb->generic_params && !mb->generic_params)
4848 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4850 token = mono_image_get_methodbuilder_token (assembly, mb, create_methodspec);
4851 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4852 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
4853 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
4854 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
4856 if (tb->module->dynamic_image == assembly && !tb->generic_params)
4857 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
4859 token = mono_image_get_ctorbuilder_token (assembly, mb);
4860 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4861 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
4862 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
4863 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)fb->typeb;
4864 if (tb->generic_params) {
4865 token = mono_image_get_generic_field_token (assembly, fb);
4867 token = fb->table_idx | MONO_TOKEN_FIELD_DEF;
4869 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
4870 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
4871 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
4872 } else if (strcmp (klass->name, "MonoType") == 0) {
4873 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4874 MonoClass *mc = mono_class_from_mono_type (type);
4875 token = mono_metadata_token_from_dor (
4876 mono_image_typedef_or_ref_full (assembly, type, mc->generic_container == NULL));
4877 } else if (strcmp (klass->name, "GenericTypeParameterBuilder") == 0) {
4878 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4879 token = mono_metadata_token_from_dor (
4880 mono_image_typedef_or_ref (assembly, type));
4881 } else if (strcmp (klass->name, "MonoGenericClass") == 0) {
4882 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4883 token = mono_metadata_token_from_dor (
4884 mono_image_typedef_or_ref (assembly, type));
4885 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
4886 strcmp (klass->name, "MonoMethod") == 0 ||
4887 strcmp (klass->name, "MonoGenericMethod") == 0 ||
4888 strcmp (klass->name, "MonoGenericCMethod") == 0) {
4889 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
4890 if (m->method->is_inflated) {
4891 if (create_methodspec)
4892 token = mono_image_get_methodspec_token (assembly, m->method);
4894 token = mono_image_get_inflated_method_token (assembly, m->method);
4895 } else if ((m->method->klass->image == &assembly->image) &&
4896 !m->method->klass->generic_class) {
4897 static guint32 method_table_idx = 0xffffff;
4898 if (m->method->klass->wastypebuilder) {
4899 /* we use the same token as the one that was assigned
4900 * to the Methodbuilder.
4901 * FIXME: do the equivalent for Fields.
4903 token = m->method->token;
4906 * Each token should have a unique index, but the indexes are
4907 * assigned by managed code, so we don't know about them. An
4908 * easy solution is to count backwards...
4910 method_table_idx --;
4911 token = MONO_TOKEN_METHOD_DEF | method_table_idx;
4914 token = mono_image_get_methodref_token (assembly, m->method, create_methodspec);
4916 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4917 } else if (strcmp (klass->name, "MonoField") == 0) {
4918 MonoReflectionField *f = (MonoReflectionField *)obj;
4919 if ((f->field->parent->image == &assembly->image) && !is_field_on_inst (f->field)) {
4920 static guint32 field_table_idx = 0xffffff;
4922 token = MONO_TOKEN_FIELD_DEF | field_table_idx;
4924 token = mono_image_get_fieldref_token (assembly, f);
4926 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4927 } else if (strcmp (klass->name, "MonoArrayMethod") == 0) {
4928 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod *)obj;
4929 token = mono_image_get_array_token (assembly, m);
4930 } else if (strcmp (klass->name, "SignatureHelper") == 0) {
4931 MonoReflectionSigHelper *s = (MonoReflectionSigHelper*)obj;
4932 token = MONO_TOKEN_SIGNATURE | mono_image_get_sighelper_token (assembly, s);
4933 } else if (strcmp (klass->name, "EnumBuilder") == 0) {
4934 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
4935 token = mono_metadata_token_from_dor (
4936 mono_image_typedef_or_ref (assembly, type));
4937 } else if (strcmp (klass->name, "FieldOnTypeBuilderInst") == 0) {
4938 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
4939 token = mono_image_get_field_on_inst_token (assembly, f);
4940 } else if (strcmp (klass->name, "ConstructorOnTypeBuilderInst") == 0) {
4941 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
4942 token = mono_image_get_ctor_on_inst_token (assembly, c, create_methodspec);
4943 } else if (strcmp (klass->name, "MethodOnTypeBuilderInst") == 0) {
4944 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
4945 token = mono_image_get_method_on_inst_token (assembly, m, create_methodspec);
4946 } else if (is_sre_array (klass) || is_sre_byref (klass) || is_sre_pointer (klass)) {
4947 MonoReflectionType *type = (MonoReflectionType *)obj;
4948 token = mono_metadata_token_from_dor (
4949 mono_image_typedef_or_ref (assembly, mono_reflection_type_get_handle (type)));
4951 g_error ("requested token for %s\n", klass->name);
4955 mono_image_register_token (assembly, token, obj);
4961 * mono_image_register_token:
4963 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4964 * the Module.ResolveXXXToken () methods to work.
4967 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
4969 MonoObject *prev = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
4971 /* There could be multiple MethodInfo objects with the same token */
4972 //g_assert (prev == obj);
4974 mono_g_hash_table_insert (assembly->tokens, GUINT_TO_POINTER (token), obj);
4978 static MonoDynamicImage*
4979 create_dynamic_mono_image (MonoDynamicAssembly *assembly, char *assembly_name, char *module_name)
4981 static const guchar entrycode [16] = {0xff, 0x25, 0};
4982 MonoDynamicImage *image;
4985 const char *version;
4987 if (!strcmp (mono_get_runtime_info ()->framework_version, "2.1"))
4988 version = "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4990 version = mono_get_runtime_info ()->runtime_version;
4993 image = GC_MALLOC (sizeof (MonoDynamicImage));
4995 image = g_new0 (MonoDynamicImage, 1);
4998 mono_profiler_module_event (&image->image, MONO_PROFILE_START_LOAD);
5000 /*g_print ("created image %p\n", image);*/
5001 /* keep in sync with image.c */
5002 image->image.name = assembly_name;
5003 image->image.assembly_name = image->image.name; /* they may be different */
5004 image->image.module_name = module_name;
5005 image->image.version = g_strdup (version);
5006 image->image.md_version_major = 1;
5007 image->image.md_version_minor = 1;
5008 image->image.dynamic = TRUE;
5010 image->image.references = g_new0 (MonoAssembly*, 1);
5011 image->image.references [0] = NULL;
5013 mono_image_init (&image->image);
5015 image->token_fixups = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5016 image->method_to_table_idx = g_hash_table_new (NULL, NULL);
5017 image->field_to_table_idx = g_hash_table_new (NULL, NULL);
5018 image->method_aux_hash = g_hash_table_new (NULL, NULL);
5019 image->handleref = g_hash_table_new (NULL, NULL);
5020 image->handleref_managed = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5021 image->tokens = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5022 image->generic_def_objects = mono_g_hash_table_new_type (NULL, NULL, MONO_HASH_VALUE_GC);
5023 image->methodspec = mono_g_hash_table_new_type ((GHashFunc)mono_object_hash, NULL, MONO_HASH_KEY_GC);
5024 image->typespec = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5025 image->typeref = g_hash_table_new ((GHashFunc)mono_metadata_type_hash, (GCompareFunc)mono_metadata_type_equal);
5026 image->blob_cache = g_hash_table_new ((GHashFunc)mono_blob_entry_hash, (GCompareFunc)mono_blob_entry_equal);
5027 image->gen_params = g_ptr_array_new ();
5029 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5030 string_heap_init (&image->sheap);
5031 mono_image_add_stream_data (&image->us, "", 1);
5032 add_to_blob_cached (image, (char*) "", 1, NULL, 0);
5033 /* import tables... */
5034 mono_image_add_stream_data (&image->code, (char*)entrycode, sizeof (entrycode));
5035 image->iat_offset = mono_image_add_stream_zero (&image->code, 8); /* two IAT entries */
5036 image->idt_offset = mono_image_add_stream_zero (&image->code, 2 * sizeof (MonoIDT)); /* two IDT entries */
5037 image->imp_names_offset = mono_image_add_stream_zero (&image->code, 2); /* flags for name entry */
5038 mono_image_add_stream_data (&image->code, "_CorExeMain", 12);
5039 mono_image_add_stream_data (&image->code, "mscoree.dll", 12);
5040 image->ilt_offset = mono_image_add_stream_zero (&image->code, 8); /* two ILT entries */
5041 stream_data_align (&image->code);
5043 image->cli_header_offset = mono_image_add_stream_zero (&image->code, sizeof (MonoCLIHeader));
5045 for (i=0; i < MONO_TABLE_NUM; ++i) {
5046 image->tables [i].next_idx = 1;
5047 image->tables [i].columns = table_sizes [i];
5050 image->image.assembly = (MonoAssembly*)assembly;
5051 image->run = assembly->run;
5052 image->save = assembly->save;
5053 image->pe_kind = 0x1; /* ILOnly */
5054 image->machine = 0x14c; /* I386 */
5056 mono_profiler_module_loaded (&image->image, MONO_PROFILE_OK);
5063 free_blob_cache_entry (gpointer key, gpointer val, gpointer user_data)
5069 mono_dynamic_image_free (MonoDynamicImage *image)
5071 MonoDynamicImage *di = image;
5076 mono_g_hash_table_destroy (di->methodspec);
5078 g_hash_table_destroy (di->typespec);
5080 g_hash_table_destroy (di->typeref);
5082 g_hash_table_destroy (di->handleref);
5083 if (di->handleref_managed)
5084 mono_g_hash_table_destroy (di->handleref_managed);
5086 mono_g_hash_table_destroy (di->tokens);
5087 if (di->generic_def_objects)
5088 mono_g_hash_table_destroy (di->generic_def_objects);
5089 if (di->blob_cache) {
5090 g_hash_table_foreach (di->blob_cache, free_blob_cache_entry, NULL);
5091 g_hash_table_destroy (di->blob_cache);
5093 if (di->standalonesig_cache)
5094 g_hash_table_destroy (di->standalonesig_cache);
5095 for (list = di->array_methods; list; list = list->next) {
5096 ArrayMethod *am = (ArrayMethod *)list->data;
5101 g_list_free (di->array_methods);
5102 if (di->gen_params) {
5103 for (i = 0; i < di->gen_params->len; i++) {
5104 GenericParamTableEntry *entry = g_ptr_array_index (di->gen_params, i);
5105 if (entry->gparam->type.type) {
5106 MonoGenericParam *param = entry->gparam->type.type->data.generic_param;
5107 g_free ((char*)mono_generic_param_info (param)->name);
5110 mono_gc_deregister_root ((char*) &entry->gparam);
5113 g_ptr_array_free (di->gen_params, TRUE);
5115 if (di->token_fixups)
5116 mono_g_hash_table_destroy (di->token_fixups);
5117 if (di->method_to_table_idx)
5118 g_hash_table_destroy (di->method_to_table_idx);
5119 if (di->field_to_table_idx)
5120 g_hash_table_destroy (di->field_to_table_idx);
5121 if (di->method_aux_hash)
5122 g_hash_table_destroy (di->method_aux_hash);
5123 g_free (di->strong_name);
5124 g_free (di->win32_res);
5126 g_free (di->public_key);
5128 /*g_print ("string heap destroy for image %p\n", di);*/
5129 mono_dynamic_stream_reset (&di->sheap);
5130 mono_dynamic_stream_reset (&di->code);
5131 mono_dynamic_stream_reset (&di->resources);
5132 mono_dynamic_stream_reset (&di->us);
5133 mono_dynamic_stream_reset (&di->blob);
5134 mono_dynamic_stream_reset (&di->tstream);
5135 mono_dynamic_stream_reset (&di->guid);
5136 for (i = 0; i < MONO_TABLE_NUM; ++i) {
5137 g_free (di->tables [i].values);
5141 #ifndef DISABLE_REFLECTION_EMIT
5144 * mono_image_basic_init:
5145 * @assembly: an assembly builder object
5147 * Create the MonoImage that represents the assembly builder and setup some
5148 * of the helper hash table and the basic metadata streams.
5151 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
5153 MonoDynamicAssembly *assembly;
5154 MonoDynamicImage *image;
5155 MonoDomain *domain = mono_object_domain (assemblyb);
5157 MONO_ARCH_SAVE_REGS;
5159 if (assemblyb->dynamic_assembly)
5163 assembly = assemblyb->dynamic_assembly = GC_MALLOC (sizeof (MonoDynamicAssembly));
5165 assembly = assemblyb->dynamic_assembly = g_new0 (MonoDynamicAssembly, 1);
5168 mono_profiler_assembly_event (&assembly->assembly, MONO_PROFILE_START_LOAD);
5170 assembly->assembly.ref_count = 1;
5171 assembly->assembly.dynamic = TRUE;
5172 assembly->assembly.corlib_internal = assemblyb->corlib_internal;
5173 assemblyb->assembly.assembly = (MonoAssembly*)assembly;
5174 assembly->assembly.basedir = mono_string_to_utf8 (assemblyb->dir);
5175 if (assemblyb->culture)
5176 assembly->assembly.aname.culture = mono_string_to_utf8 (assemblyb->culture);
5178 assembly->assembly.aname.culture = g_strdup ("");
5180 if (assemblyb->version) {
5181 char *vstr = mono_string_to_utf8 (assemblyb->version);
5182 char **version = g_strsplit (vstr, ".", 4);
5183 char **parts = version;
5184 assembly->assembly.aname.major = atoi (*parts++);
5185 assembly->assembly.aname.minor = atoi (*parts++);
5186 assembly->assembly.aname.build = *parts != NULL ? atoi (*parts++) : 0;
5187 assembly->assembly.aname.revision = *parts != NULL ? atoi (*parts) : 0;
5189 g_strfreev (version);
5192 assembly->assembly.aname.major = 0;
5193 assembly->assembly.aname.minor = 0;
5194 assembly->assembly.aname.build = 0;
5195 assembly->assembly.aname.revision = 0;
5198 assembly->run = assemblyb->access != 2;
5199 assembly->save = assemblyb->access != 1;
5200 assembly->domain = domain;
5202 image = create_dynamic_mono_image (assembly, mono_string_to_utf8 (assemblyb->name), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5203 image->initial_image = TRUE;
5204 assembly->assembly.aname.name = image->image.name;
5205 assembly->assembly.image = &image->image;
5206 if (assemblyb->pktoken && assemblyb->pktoken->max_length) {
5207 /* -1 to correct for the trailing NULL byte */
5208 if (assemblyb->pktoken->max_length != MONO_PUBLIC_KEY_TOKEN_LENGTH - 1) {
5209 g_error ("Public key token length invalid for assembly %s: %i", assembly->assembly.aname.name, assemblyb->pktoken->max_length);
5211 memcpy (&assembly->assembly.aname.public_key_token, mono_array_addr (assemblyb->pktoken, guint8, 0), assemblyb->pktoken->max_length);
5214 mono_domain_assemblies_lock (domain);
5215 domain->domain_assemblies = g_slist_prepend (domain->domain_assemblies, assembly);
5216 mono_domain_assemblies_unlock (domain);
5218 register_assembly (mono_object_domain (assemblyb), &assemblyb->assembly, &assembly->assembly);
5220 mono_profiler_assembly_loaded (&assembly->assembly, MONO_PROFILE_OK);
5222 mono_assembly_invoke_load_hook ((MonoAssembly*)assembly);
5225 #endif /* !DISABLE_REFLECTION_EMIT */
5227 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5230 calc_section_size (MonoDynamicImage *assembly)
5234 /* alignment constraints */
5235 mono_image_add_stream_zero (&assembly->code, 4 - (assembly->code.index % 4));
5236 g_assert ((assembly->code.index % 4) == 0);
5237 assembly->meta_size += 3;
5238 assembly->meta_size &= ~3;
5239 mono_image_add_stream_zero (&assembly->resources, 4 - (assembly->resources.index % 4));
5240 g_assert ((assembly->resources.index % 4) == 0);
5242 assembly->sections [MONO_SECTION_TEXT].size = assembly->meta_size + assembly->code.index + assembly->resources.index + assembly->strong_name_size;
5243 assembly->sections [MONO_SECTION_TEXT].attrs = SECT_FLAGS_HAS_CODE | SECT_FLAGS_MEM_EXECUTE | SECT_FLAGS_MEM_READ;
5246 if (assembly->win32_res) {
5247 guint32 res_size = (assembly->win32_res_size + 3) & ~3;
5249 assembly->sections [MONO_SECTION_RSRC].size = res_size;
5250 assembly->sections [MONO_SECTION_RSRC].attrs = SECT_FLAGS_HAS_INITIALIZED_DATA | SECT_FLAGS_MEM_READ;
5254 assembly->sections [MONO_SECTION_RELOC].size = 12;
5255 assembly->sections [MONO_SECTION_RELOC].attrs = SECT_FLAGS_MEM_READ | SECT_FLAGS_MEM_DISCARDABLE | SECT_FLAGS_HAS_INITIALIZED_DATA;
5265 MonoReflectionWin32Resource *win32_res; /* Only for leaf nodes */
5269 resource_tree_compare_by_id (gconstpointer a, gconstpointer b)
5271 ResTreeNode *t1 = (ResTreeNode*)a;
5272 ResTreeNode *t2 = (ResTreeNode*)b;
5274 return t1->id - t2->id;
5278 * resource_tree_create:
5280 * Organize the resources into a resource tree.
5282 static ResTreeNode *
5283 resource_tree_create (MonoArray *win32_resources)
5285 ResTreeNode *tree, *res_node, *type_node, *lang_node;
5289 tree = g_new0 (ResTreeNode, 1);
5291 for (i = 0; i < mono_array_length (win32_resources); ++i) {
5292 MonoReflectionWin32Resource *win32_res =
5293 (MonoReflectionWin32Resource*)mono_array_addr (win32_resources, MonoReflectionWin32Resource, i);
5297 /* FIXME: BUG: this stores managed references in unmanaged memory */
5298 lang_node = g_new0 (ResTreeNode, 1);
5299 lang_node->id = win32_res->lang_id;
5300 lang_node->win32_res = win32_res;
5302 /* Create type node if neccesary */
5304 for (l = tree->children; l; l = l->next)
5305 if (((ResTreeNode*)(l->data))->id == win32_res->res_type) {
5306 type_node = (ResTreeNode*)l->data;
5311 type_node = g_new0 (ResTreeNode, 1);
5312 type_node->id = win32_res->res_type;
5315 * The resource types have to be sorted otherwise
5316 * Windows Explorer can't display the version information.
5318 tree->children = g_slist_insert_sorted (tree->children,
5319 type_node, resource_tree_compare_by_id);
5322 /* Create res node if neccesary */
5324 for (l = type_node->children; l; l = l->next)
5325 if (((ResTreeNode*)(l->data))->id == win32_res->res_id) {
5326 res_node = (ResTreeNode*)l->data;
5331 res_node = g_new0 (ResTreeNode, 1);
5332 res_node->id = win32_res->res_id;
5333 type_node->children = g_slist_append (type_node->children, res_node);
5336 res_node->children = g_slist_append (res_node->children, lang_node);
5343 * resource_tree_encode:
5345 * Encode the resource tree into the format used in the PE file.
5348 resource_tree_encode (ResTreeNode *node, char *begin, char *p, char **endbuf)
5351 MonoPEResourceDir dir;
5352 MonoPEResourceDirEntry dir_entry;
5353 MonoPEResourceDataEntry data_entry;
5355 guint32 res_id_entries;
5358 * For the format of the resource directory, see the article
5359 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5363 memset (&dir, 0, sizeof (dir));
5364 memset (&dir_entry, 0, sizeof (dir_entry));
5365 memset (&data_entry, 0, sizeof (data_entry));
5367 g_assert (sizeof (dir) == 16);
5368 g_assert (sizeof (dir_entry) == 8);
5369 g_assert (sizeof (data_entry) == 16);
5371 node->offset = p - begin;
5373 /* IMAGE_RESOURCE_DIRECTORY */
5374 res_id_entries = g_slist_length (node->children);
5375 dir.res_id_entries = GUINT16_TO_LE (res_id_entries);
5377 memcpy (p, &dir, sizeof (dir));
5380 /* Reserve space for entries */
5382 p += sizeof (dir_entry) * res_id_entries;
5384 /* Write children */
5385 for (l = node->children; l; l = l->next) {
5386 ResTreeNode *child = (ResTreeNode*)l->data;
5388 if (child->win32_res) {
5391 child->offset = p - begin;
5393 /* IMAGE_RESOURCE_DATA_ENTRY */
5394 data_entry.rde_data_offset = GUINT32_TO_LE (p - begin + sizeof (data_entry));
5395 size = mono_array_length (child->win32_res->res_data);
5396 data_entry.rde_size = GUINT32_TO_LE (size);
5398 memcpy (p, &data_entry, sizeof (data_entry));
5399 p += sizeof (data_entry);
5401 memcpy (p, mono_array_addr (child->win32_res->res_data, char, 0), size);
5404 resource_tree_encode (child, begin, p, &p);
5408 /* IMAGE_RESOURCE_ENTRY */
5409 for (l = node->children; l; l = l->next) {
5410 ResTreeNode *child = (ResTreeNode*)l->data;
5412 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry, FALSE, child->id);
5413 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry, !child->win32_res, child->offset);
5415 memcpy (entries, &dir_entry, sizeof (dir_entry));
5416 entries += sizeof (dir_entry);
5423 resource_tree_free (ResTreeNode * node)
5426 for (list = node->children; list; list = list->next)
5427 resource_tree_free ((ResTreeNode*)list->data);
5428 g_slist_free(node->children);
5433 assembly_add_win32_resources (MonoDynamicImage *assembly, MonoReflectionAssemblyBuilder *assemblyb)
5438 MonoReflectionWin32Resource *win32_res;
5441 if (!assemblyb->win32_resources)
5445 * Resources are stored in a three level tree inside the PE file.
5446 * - level one contains a node for each type of resource
5447 * - level two contains a node for each resource
5448 * - level three contains a node for each instance of a resource for a
5449 * specific language.
5452 tree = resource_tree_create (assemblyb->win32_resources);
5454 /* Estimate the size of the encoded tree */
5456 for (i = 0; i < mono_array_length (assemblyb->win32_resources); ++i) {
5457 win32_res = (MonoReflectionWin32Resource*)mono_array_addr (assemblyb->win32_resources, MonoReflectionWin32Resource, i);
5458 size += mono_array_length (win32_res->res_data);
5460 /* Directory structure */
5461 size += mono_array_length (assemblyb->win32_resources) * 256;
5462 p = buf = g_malloc (size);
5464 resource_tree_encode (tree, p, p, &p);
5466 g_assert (p - buf <= size);
5468 assembly->win32_res = g_malloc (p - buf);
5469 assembly->win32_res_size = p - buf;
5470 memcpy (assembly->win32_res, buf, p - buf);
5473 resource_tree_free (tree);
5477 fixup_resource_directory (char *res_section, char *p, guint32 rva)
5479 MonoPEResourceDir *dir = (MonoPEResourceDir*)p;
5482 p += sizeof (MonoPEResourceDir);
5483 for (i = 0; i < GUINT16_FROM_LE (dir->res_named_entries) + GUINT16_FROM_LE (dir->res_id_entries); ++i) {
5484 MonoPEResourceDirEntry *dir_entry = (MonoPEResourceDirEntry*)p;
5485 char *child = res_section + MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry);
5486 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry)) {
5487 fixup_resource_directory (res_section, child, rva);
5489 MonoPEResourceDataEntry *data_entry = (MonoPEResourceDataEntry*)child;
5490 data_entry->rde_data_offset = GUINT32_TO_LE (GUINT32_FROM_LE (data_entry->rde_data_offset) + rva);
5493 p += sizeof (MonoPEResourceDirEntry);
5498 checked_write_file (HANDLE f, gconstpointer buffer, guint32 numbytes)
5501 if (!WriteFile (f, buffer, numbytes, &dummy, NULL))
5502 g_error ("WriteFile returned %d\n", GetLastError ());
5506 * mono_image_create_pefile:
5507 * @mb: a module builder object
5509 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5510 * assembly->pefile where it can be easily retrieved later in chunks.
5513 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5515 MonoMSDOSHeader *msdos;
5516 MonoDotNetHeader *header;
5517 MonoSectionTable *section;
5518 MonoCLIHeader *cli_header;
5519 guint32 size, image_size, virtual_base, text_offset;
5520 guint32 header_start, section_start, file_offset, virtual_offset;
5521 MonoDynamicImage *assembly;
5522 MonoReflectionAssemblyBuilder *assemblyb;
5523 MonoDynamicStream pefile_stream = {0};
5524 MonoDynamicStream *pefile = &pefile_stream;
5526 guint32 *rva, value;
5528 static const unsigned char msheader[] = {
5529 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5530 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5532 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5533 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5534 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5535 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5536 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5539 assemblyb = mb->assemblyb;
5541 mono_image_basic_init (assemblyb);
5542 assembly = mb->dynamic_image;
5544 assembly->pe_kind = assemblyb->pe_kind;
5545 assembly->machine = assemblyb->machine;
5546 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->pe_kind = assemblyb->pe_kind;
5547 ((MonoDynamicImage*)assemblyb->dynamic_assembly->assembly.image)->machine = assemblyb->machine;
5549 mono_image_build_metadata (mb);
5551 if (mb->is_main && assemblyb->resources) {
5552 int len = mono_array_length (assemblyb->resources);
5553 for (i = 0; i < len; ++i)
5554 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (assemblyb->resources, MonoReflectionResource, i));
5557 if (mb->resources) {
5558 int len = mono_array_length (mb->resources);
5559 for (i = 0; i < len; ++i)
5560 assembly_add_resource (mb, assembly, (MonoReflectionResource*)mono_array_addr (mb->resources, MonoReflectionResource, i));
5563 build_compressed_metadata (assembly);
5566 assembly_add_win32_resources (assembly, assemblyb);
5568 nsections = calc_section_size (assembly);
5570 /* The DOS header and stub */
5571 g_assert (sizeof (MonoMSDOSHeader) == sizeof (msheader));
5572 mono_image_add_stream_data (pefile, (char*)msheader, sizeof (msheader));
5574 /* the dotnet header */
5575 header_start = mono_image_add_stream_zero (pefile, sizeof (MonoDotNetHeader));
5577 /* the section tables */
5578 section_start = mono_image_add_stream_zero (pefile, sizeof (MonoSectionTable) * nsections);
5580 file_offset = section_start + sizeof (MonoSectionTable) * nsections;
5581 virtual_offset = VIRT_ALIGN;
5584 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5585 if (!assembly->sections [i].size)
5588 file_offset += FILE_ALIGN - 1;
5589 file_offset &= ~(FILE_ALIGN - 1);
5590 virtual_offset += VIRT_ALIGN - 1;
5591 virtual_offset &= ~(VIRT_ALIGN - 1);
5593 assembly->sections [i].offset = file_offset;
5594 assembly->sections [i].rva = virtual_offset;
5596 file_offset += assembly->sections [i].size;
5597 virtual_offset += assembly->sections [i].size;
5598 image_size += (assembly->sections [i].size + VIRT_ALIGN - 1) & ~(VIRT_ALIGN - 1);
5601 file_offset += FILE_ALIGN - 1;
5602 file_offset &= ~(FILE_ALIGN - 1);
5604 image_size += section_start + sizeof (MonoSectionTable) * nsections;
5606 /* back-patch info */
5607 msdos = (MonoMSDOSHeader*)pefile->data;
5608 msdos->pe_offset = GUINT32_FROM_LE (sizeof (MonoMSDOSHeader));
5610 header = (MonoDotNetHeader*)(pefile->data + header_start);
5611 header->pesig [0] = 'P';
5612 header->pesig [1] = 'E';
5614 header->coff.coff_machine = GUINT16_FROM_LE (assemblyb->machine);
5615 header->coff.coff_sections = GUINT16_FROM_LE (nsections);
5616 header->coff.coff_time = GUINT32_FROM_LE (time (NULL));
5617 header->coff.coff_opt_header_size = GUINT16_FROM_LE (sizeof (MonoDotNetHeader) - sizeof (MonoCOFFHeader) - 4);
5618 if (assemblyb->pekind == 1) {
5620 header->coff.coff_attributes = GUINT16_FROM_LE (0x210e);
5623 header->coff.coff_attributes = GUINT16_FROM_LE (0x010e);
5626 virtual_base = 0x400000; /* FIXME: 0x10000000 if a DLL */
5628 header->pe.pe_magic = GUINT16_FROM_LE (0x10B);
5629 header->pe.pe_major = 6;
5630 header->pe.pe_minor = 0;
5631 size = assembly->sections [MONO_SECTION_TEXT].size;
5632 size += FILE_ALIGN - 1;
5633 size &= ~(FILE_ALIGN - 1);
5634 header->pe.pe_code_size = GUINT32_FROM_LE(size);
5635 size = assembly->sections [MONO_SECTION_RSRC].size;
5636 size += FILE_ALIGN - 1;
5637 size &= ~(FILE_ALIGN - 1);
5638 header->pe.pe_data_size = GUINT32_FROM_LE(size);
5639 g_assert (START_TEXT_RVA == assembly->sections [MONO_SECTION_TEXT].rva);
5640 header->pe.pe_rva_code_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5641 header->pe.pe_rva_data_base = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5642 /* pe_rva_entry_point always at the beginning of the text section */
5643 header->pe.pe_rva_entry_point = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_TEXT].rva);
5645 header->nt.pe_image_base = GUINT32_FROM_LE (virtual_base);
5646 header->nt.pe_section_align = GUINT32_FROM_LE (VIRT_ALIGN);
5647 header->nt.pe_file_alignment = GUINT32_FROM_LE (FILE_ALIGN);
5648 header->nt.pe_os_major = GUINT16_FROM_LE (4);
5649 header->nt.pe_os_minor = GUINT16_FROM_LE (0);
5650 header->nt.pe_subsys_major = GUINT16_FROM_LE (4);
5651 size = section_start;
5652 size += FILE_ALIGN - 1;
5653 size &= ~(FILE_ALIGN - 1);
5654 header->nt.pe_header_size = GUINT32_FROM_LE (size);
5656 size += VIRT_ALIGN - 1;
5657 size &= ~(VIRT_ALIGN - 1);
5658 header->nt.pe_image_size = GUINT32_FROM_LE (size);
5661 // Translate the PEFileKind value to the value expected by the Windows loader
5667 // PEFileKinds.Dll == 1
5668 // PEFileKinds.ConsoleApplication == 2
5669 // PEFileKinds.WindowApplication == 3
5672 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5673 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5675 if (assemblyb->pekind == 3)
5680 header->nt.pe_subsys_required = GUINT16_FROM_LE (kind);
5682 header->nt.pe_stack_reserve = GUINT32_FROM_LE (0x00100000);
5683 header->nt.pe_stack_commit = GUINT32_FROM_LE (0x00001000);
5684 header->nt.pe_heap_reserve = GUINT32_FROM_LE (0x00100000);
5685 header->nt.pe_heap_commit = GUINT32_FROM_LE (0x00001000);
5686 header->nt.pe_loader_flags = GUINT32_FROM_LE (0);
5687 header->nt.pe_data_dir_count = GUINT32_FROM_LE (16);
5689 /* fill data directory entries */
5691 header->datadir.pe_resource_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].size);
5692 header->datadir.pe_resource_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RSRC].rva);
5694 header->datadir.pe_reloc_table.size = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].size);
5695 header->datadir.pe_reloc_table.rva = GUINT32_FROM_LE (assembly->sections [MONO_SECTION_RELOC].rva);
5697 header->datadir.pe_cli_header.size = GUINT32_FROM_LE (72);
5698 header->datadir.pe_cli_header.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->cli_header_offset);
5699 header->datadir.pe_iat.size = GUINT32_FROM_LE (8);
5700 header->datadir.pe_iat.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5701 /* patch entrypoint name */
5702 if (assemblyb->pekind == 1)
5703 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorDllMain", 12);
5705 memcpy (assembly->code.data + assembly->imp_names_offset + 2, "_CorExeMain", 12);
5706 /* patch imported function RVA name */
5707 rva = (guint32*)(assembly->code.data + assembly->iat_offset);
5708 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset);
5710 /* the import table */
5711 header->datadir.pe_import_table.size = GUINT32_FROM_LE (79); /* FIXME: magic number? */
5712 header->datadir.pe_import_table.rva = GUINT32_FROM_LE (assembly->text_rva + assembly->idt_offset);
5713 /* patch imported dll RVA name and other entries in the dir */
5714 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, name_rva));
5715 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->imp_names_offset + 14); /* 14 is hint+strlen+1 of func name */
5716 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_address_table_rva));
5717 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->iat_offset);
5718 rva = (guint32*)(assembly->code.data + assembly->idt_offset + G_STRUCT_OFFSET (MonoIDT, import_lookup_table));
5719 *rva = GUINT32_FROM_LE (assembly->text_rva + assembly->ilt_offset);
5721 p = (guchar*)(assembly->code.data + assembly->ilt_offset);
5722 value = (assembly->text_rva + assembly->imp_names_offset);
5723 *p++ = (value) & 0xff;
5724 *p++ = (value >> 8) & (0xff);
5725 *p++ = (value >> 16) & (0xff);
5726 *p++ = (value >> 24) & (0xff);
5728 /* the CLI header info */
5729 cli_header = (MonoCLIHeader*)(assembly->code.data + assembly->cli_header_offset);
5730 cli_header->ch_size = GUINT32_FROM_LE (72);
5731 cli_header->ch_runtime_major = GUINT16_FROM_LE (2);
5732 cli_header->ch_runtime_minor = GUINT16_FROM_LE (5);
5733 cli_header->ch_flags = GUINT32_FROM_LE (assemblyb->pe_kind);
5734 if (assemblyb->entry_point) {
5735 guint32 table_idx = 0;
5736 if (!strcmp (assemblyb->entry_point->object.vtable->klass->name, "MethodBuilder")) {
5737 MonoReflectionMethodBuilder *methodb = (MonoReflectionMethodBuilder*)assemblyb->entry_point;
5738 table_idx = methodb->table_idx;
5740 table_idx = GPOINTER_TO_UINT (g_hash_table_lookup (assembly->method_to_table_idx, assemblyb->entry_point->method));
5742 cli_header->ch_entry_point = GUINT32_FROM_LE (table_idx | MONO_TOKEN_METHOD_DEF);
5744 cli_header->ch_entry_point = GUINT32_FROM_LE (0);
5746 /* The embedded managed resources */
5747 text_offset = assembly->text_rva + assembly->code.index;
5748 cli_header->ch_resources.rva = GUINT32_FROM_LE (text_offset);
5749 cli_header->ch_resources.size = GUINT32_FROM_LE (assembly->resources.index);
5750 text_offset += assembly->resources.index;
5751 cli_header->ch_metadata.rva = GUINT32_FROM_LE (text_offset);
5752 cli_header->ch_metadata.size = GUINT32_FROM_LE (assembly->meta_size);
5753 text_offset += assembly->meta_size;
5754 if (assembly->strong_name_size) {
5755 cli_header->ch_strong_name.rva = GUINT32_FROM_LE (text_offset);
5756 cli_header->ch_strong_name.size = GUINT32_FROM_LE (assembly->strong_name_size);
5757 text_offset += assembly->strong_name_size;
5760 /* write the section tables and section content */
5761 section = (MonoSectionTable*)(pefile->data + section_start);
5762 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5763 static const char section_names [][7] = {
5764 ".text", ".rsrc", ".reloc"
5766 if (!assembly->sections [i].size)
5768 strcpy (section->st_name, section_names [i]);
5769 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5770 section->st_virtual_address = GUINT32_FROM_LE (assembly->sections [i].rva);
5771 section->st_virtual_size = GUINT32_FROM_LE (assembly->sections [i].size);
5772 section->st_raw_data_size = GUINT32_FROM_LE (GUINT32_TO_LE (section->st_virtual_size) + (FILE_ALIGN - 1));
5773 section->st_raw_data_size &= GUINT32_FROM_LE (~(FILE_ALIGN - 1));
5774 section->st_raw_data_ptr = GUINT32_FROM_LE (assembly->sections [i].offset);
5775 section->st_flags = GUINT32_FROM_LE (assembly->sections [i].attrs);
5779 checked_write_file (file, pefile->data, pefile->index);
5781 mono_dynamic_stream_reset (pefile);
5783 for (i = 0; i < MONO_SECTION_MAX; ++i) {
5784 if (!assembly->sections [i].size)
5787 if (SetFilePointer (file, assembly->sections [i].offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5788 g_error ("SetFilePointer returned %d\n", GetLastError ());
5791 case MONO_SECTION_TEXT:
5792 /* patch entry point */
5793 p = (guchar*)(assembly->code.data + 2);
5794 value = (virtual_base + assembly->text_rva + assembly->iat_offset);
5795 *p++ = (value) & 0xff;
5796 *p++ = (value >> 8) & 0xff;
5797 *p++ = (value >> 16) & 0xff;
5798 *p++ = (value >> 24) & 0xff;
5800 checked_write_file (file, assembly->code.data, assembly->code.index);
5801 checked_write_file (file, assembly->resources.data, assembly->resources.index);
5802 checked_write_file (file, assembly->image.raw_metadata, assembly->meta_size);
5803 checked_write_file (file, assembly->strong_name, assembly->strong_name_size);
5806 g_free (assembly->image.raw_metadata);
5808 case MONO_SECTION_RELOC: {
5812 guint16 type_and_offset;
5816 g_assert (sizeof (reloc) == 12);
5818 reloc.page_rva = GUINT32_FROM_LE (assembly->text_rva);
5819 reloc.block_size = GUINT32_FROM_LE (12);
5822 * the entrypoint is always at the start of the text section
5823 * 3 is IMAGE_REL_BASED_HIGHLOW
5824 * 2 is patch_size_rva - text_rva
5826 reloc.type_and_offset = GUINT16_FROM_LE ((3 << 12) + (2));
5829 checked_write_file (file, &reloc, sizeof (reloc));
5833 case MONO_SECTION_RSRC:
5834 if (assembly->win32_res) {
5836 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5837 fixup_resource_directory (assembly->win32_res, assembly->win32_res, assembly->sections [i].rva);
5838 checked_write_file (file, assembly->win32_res, assembly->win32_res_size);
5842 g_assert_not_reached ();
5846 /* check that the file is properly padded */
5847 if (SetFilePointer (file, file_offset, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER)
5848 g_error ("SetFilePointer returned %d\n", GetLastError ());
5849 if (! SetEndOfFile (file))
5850 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5852 mono_dynamic_stream_reset (&assembly->code);
5853 mono_dynamic_stream_reset (&assembly->us);
5854 mono_dynamic_stream_reset (&assembly->blob);
5855 mono_dynamic_stream_reset (&assembly->guid);
5856 mono_dynamic_stream_reset (&assembly->sheap);
5858 g_hash_table_foreach (assembly->blob_cache, (GHFunc)g_free, NULL);
5859 g_hash_table_destroy (assembly->blob_cache);
5860 assembly->blob_cache = NULL;
5863 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5866 mono_image_create_pefile (MonoReflectionModuleBuilder *mb, HANDLE file)
5868 g_assert_not_reached ();
5871 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5873 #ifndef DISABLE_REFLECTION_EMIT
5875 MonoReflectionModule *
5876 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
5880 MonoImageOpenStatus status;
5881 MonoDynamicAssembly *assembly;
5882 guint32 module_count;
5883 MonoImage **new_modules;
5884 gboolean *new_modules_loaded;
5886 name = mono_string_to_utf8 (fileName);
5888 image = mono_image_open (name, &status);
5891 if (status == MONO_IMAGE_ERROR_ERRNO)
5892 exc = mono_get_exception_file_not_found (fileName);
5894 exc = mono_get_exception_bad_image_format (name);
5896 mono_raise_exception (exc);
5901 assembly = ab->dynamic_assembly;
5902 image->assembly = (MonoAssembly*)assembly;
5904 module_count = image->assembly->image->module_count;
5905 new_modules = g_new0 (MonoImage *, module_count + 1);
5906 new_modules_loaded = g_new0 (gboolean, module_count + 1);
5908 if (image->assembly->image->modules)
5909 memcpy (new_modules, image->assembly->image->modules, module_count * sizeof (MonoImage *));
5910 if (image->assembly->image->modules_loaded)
5911 memcpy (new_modules_loaded, image->assembly->image->modules_loaded, module_count * sizeof (gboolean));
5912 new_modules [module_count] = image;
5913 new_modules_loaded [module_count] = TRUE;
5914 mono_image_addref (image);
5916 g_free (image->assembly->image->modules);
5917 image->assembly->image->modules = new_modules;
5918 image->assembly->image->modules_loaded = new_modules_loaded;
5919 image->assembly->image->module_count ++;
5921 mono_assembly_load_references (image, &status);
5923 mono_image_close (image);
5924 mono_raise_exception (mono_get_exception_file_not_found (fileName));
5927 return mono_module_get_object (mono_domain_get (), image);
5930 #endif /* DISABLE_REFLECTION_EMIT */
5933 * We need to return always the same object for MethodInfo, FieldInfo etc..
5934 * but we need to consider the reflected type.
5935 * type uses a different hash, since it uses custom hash/equal functions.
5940 MonoClass *refclass;
5944 reflected_equal (gconstpointer a, gconstpointer b) {
5945 const ReflectedEntry *ea = a;
5946 const ReflectedEntry *eb = b;
5948 return (ea->item == eb->item) && (ea->refclass == eb->refclass);
5952 reflected_hash (gconstpointer a) {
5953 const ReflectedEntry *ea = a;
5954 return mono_aligned_addr_hash (ea->item);
5957 #define CHECK_OBJECT(t,p,k) \
5963 mono_domain_lock (domain); \
5964 if (!domain->refobject_hash) \
5965 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5966 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5967 mono_domain_unlock (domain); \
5970 mono_domain_unlock (domain); \
5973 #ifdef HAVE_BOEHM_GC
5974 /* ReflectedEntry doesn't need to be GC tracked */
5975 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5976 #define FREE_REFENTRY(entry) g_free ((entry))
5977 #define REFENTRY_REQUIRES_CLEANUP
5979 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5981 #define FREE_REFENTRY(entry)
5984 #define CACHE_OBJECT(t,p,o,k) \
5987 ReflectedEntry pe; \
5989 pe.refclass = (k); \
5990 mono_domain_lock (domain); \
5991 if (!domain->refobject_hash) \
5992 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5993 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5995 ReflectedEntry *e = ALLOC_REFENTRY; \
5997 e->refclass = (k); \
5998 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6001 mono_domain_unlock (domain); \
6006 clear_cached_object (MonoDomain *domain, gpointer o, MonoClass *klass)
6008 mono_domain_lock (domain);
6009 if (domain->refobject_hash) {
6011 gpointer orig_pe, orig_value;
6014 pe.refclass = klass;
6015 if (mono_g_hash_table_lookup_extended (domain->refobject_hash, &pe, &orig_pe, &orig_value)) {
6016 mono_g_hash_table_remove (domain->refobject_hash, &pe);
6017 FREE_REFENTRY (orig_pe);
6020 mono_domain_unlock (domain);
6023 #ifdef REFENTRY_REQUIRES_CLEANUP
6025 cleanup_refobject_hash (gpointer key, gpointer value, gpointer user_data)
6027 FREE_REFENTRY (key);
6032 mono_reflection_cleanup_domain (MonoDomain *domain)
6034 if (domain->refobject_hash) {
6035 /*let's avoid scanning the whole hashtable if not needed*/
6036 #ifdef REFENTRY_REQUIRES_CLEANUP
6037 mono_g_hash_table_foreach (domain->refobject_hash, cleanup_refobject_hash, NULL);
6039 mono_g_hash_table_destroy (domain->refobject_hash);
6040 domain->refobject_hash = NULL;
6044 #ifndef DISABLE_REFLECTION_EMIT
6046 register_assembly (MonoDomain *domain, MonoReflectionAssembly *res, MonoAssembly *assembly)
6048 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6052 register_module (MonoDomain *domain, MonoReflectionModuleBuilder *res, MonoDynamicImage *module)
6054 CACHE_OBJECT (MonoReflectionModuleBuilder *, module, res, NULL);
6058 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
6060 MonoDynamicImage *image = moduleb->dynamic_image;
6061 MonoReflectionAssemblyBuilder *ab = moduleb->assemblyb;
6065 MonoImage **new_modules;
6067 char *name, *fqname;
6069 * FIXME: we already created an image in mono_image_basic_init (), but
6070 * we don't know which module it belongs to, since that is only
6071 * determined at assembly save time.
6073 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6074 name = mono_string_to_utf8 (ab->name);
6075 fqname = mono_string_to_utf8_checked (moduleb->module.fqname, &error);
6076 if (!mono_error_ok (&error)) {
6078 mono_error_raise_exception (&error);
6080 image = create_dynamic_mono_image (ab->dynamic_assembly, name, fqname);
6082 moduleb->module.image = &image->image;
6083 moduleb->dynamic_image = image;
6084 register_module (mono_object_domain (moduleb), moduleb, image);
6086 /* register the module with the assembly */
6087 ass = ab->dynamic_assembly->assembly.image;
6088 module_count = ass->module_count;
6089 new_modules = g_new0 (MonoImage *, module_count + 1);
6092 memcpy (new_modules, ass->modules, module_count * sizeof (MonoImage *));
6093 new_modules [module_count] = &image->image;
6094 mono_image_addref (&image->image);
6096 g_free (ass->modules);
6097 ass->modules = new_modules;
6098 ass->module_count ++;
6103 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
6105 MonoDynamicImage *image = moduleb->dynamic_image;
6107 g_assert (type->type);
6108 image->wrappers_type = mono_class_from_mono_type (type->type);
6114 * mono_assembly_get_object:
6115 * @domain: an app domain
6116 * @assembly: an assembly
6118 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6120 MonoReflectionAssembly*
6121 mono_assembly_get_object (MonoDomain *domain, MonoAssembly *assembly)
6123 static MonoClass *assembly_type;
6124 MonoReflectionAssembly *res;
6126 CHECK_OBJECT (MonoReflectionAssembly *, assembly, NULL);
6127 if (!assembly_type) {
6128 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoAssembly");
6130 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Assembly");
6132 assembly_type = class;
6134 res = (MonoReflectionAssembly *)mono_object_new (domain, assembly_type);
6135 res->assembly = assembly;
6137 CACHE_OBJECT (MonoReflectionAssembly *, assembly, res, NULL);
6142 MonoReflectionModule*
6143 mono_module_get_object (MonoDomain *domain, MonoImage *image)
6145 static MonoClass *module_type;
6146 MonoReflectionModule *res;
6149 CHECK_OBJECT (MonoReflectionModule *, image, NULL);
6151 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6153 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6155 module_type = class;
6157 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6160 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6162 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, image->name));
6163 basename = g_path_get_basename (image->name);
6164 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, basename));
6165 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, image->module_name));
6169 if (image->assembly->image == image) {
6170 res->token = mono_metadata_make_token (MONO_TABLE_MODULE, 1);
6174 if (image->assembly->image->modules) {
6175 for (i = 0; i < image->assembly->image->module_count; i++) {
6176 if (image->assembly->image->modules [i] == image)
6177 res->token = mono_metadata_make_token (MONO_TABLE_MODULEREF, i + 1);
6179 g_assert (res->token);
6183 CACHE_OBJECT (MonoReflectionModule *, image, res, NULL);
6186 MonoReflectionModule*
6187 mono_module_file_get_object (MonoDomain *domain, MonoImage *image, int table_index)
6189 static MonoClass *module_type;
6190 MonoReflectionModule *res;
6191 MonoTableInfo *table;
6192 guint32 cols [MONO_FILE_SIZE];
6194 guint32 i, name_idx;
6198 MonoClass *class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoModule");
6200 class = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
6202 module_type = class;
6204 res = (MonoReflectionModule *)mono_object_new (domain, module_type);
6206 table = &image->tables [MONO_TABLE_FILE];
6207 g_assert (table_index < table->rows);
6208 mono_metadata_decode_row (table, table_index, cols, MONO_FILE_SIZE);
6211 MONO_OBJECT_SETREF (res, assembly, (MonoReflectionAssembly *) mono_assembly_get_object(domain, image->assembly));
6212 name = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
6214 /* Check whenever the row has a corresponding row in the moduleref table */
6215 table = &image->tables [MONO_TABLE_MODULEREF];
6216 for (i = 0; i < table->rows; ++i) {
6217 name_idx = mono_metadata_decode_row_col (table, i, MONO_MODULEREF_NAME);
6218 val = mono_metadata_string_heap (image, name_idx);
6219 if (strcmp (val, name) == 0)
6220 res->image = image->modules [i];
6223 MONO_OBJECT_SETREF (res, fqname, mono_string_new (domain, name));
6224 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, name));
6225 MONO_OBJECT_SETREF (res, scopename, mono_string_new (domain, name));
6226 res->is_resource = cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA;
6227 res->token = mono_metadata_make_token (MONO_TABLE_FILE, table_index + 1);
6233 mymono_metadata_type_equal (MonoType *t1, MonoType *t2)
6235 if ((t1->type != t2->type) ||
6236 (t1->byref != t2->byref))
6240 case MONO_TYPE_VOID:
6241 case MONO_TYPE_BOOLEAN:
6242 case MONO_TYPE_CHAR:
6253 case MONO_TYPE_STRING:
6256 case MONO_TYPE_OBJECT:
6257 case MONO_TYPE_TYPEDBYREF:
6259 case MONO_TYPE_VALUETYPE:
6260 case MONO_TYPE_CLASS:
6261 case MONO_TYPE_SZARRAY:
6262 return t1->data.klass == t2->data.klass;
6264 return mymono_metadata_type_equal (t1->data.type, t2->data.type);
6265 case MONO_TYPE_ARRAY:
6266 if (t1->data.array->rank != t2->data.array->rank)
6268 return t1->data.array->eklass == t2->data.array->eklass;
6269 case MONO_TYPE_GENERICINST: {
6271 MonoGenericInst *i1 = t1->data.generic_class->context.class_inst;
6272 MonoGenericInst *i2 = t2->data.generic_class->context.class_inst;
6273 if (i1->type_argc != i2->type_argc)
6275 if (!mono_metadata_type_equal (&t1->data.generic_class->container_class->byval_arg,
6276 &t2->data.generic_class->container_class->byval_arg))
6278 /* FIXME: we should probably just compare the instance pointers directly. */
6279 for (i = 0; i < i1->type_argc; ++i) {
6280 if (!mono_metadata_type_equal (i1->type_argv [i], i2->type_argv [i]))
6286 case MONO_TYPE_MVAR:
6287 return t1->data.generic_param == t2->data.generic_param;
6289 g_error ("implement type compare for %0x!", t1->type);
6297 mymono_metadata_type_hash (MonoType *t1)
6303 hash |= t1->byref << 6; /* do not collide with t1->type values */
6305 case MONO_TYPE_VALUETYPE:
6306 case MONO_TYPE_CLASS:
6307 case MONO_TYPE_SZARRAY:
6308 /* check if the distribution is good enough */
6309 return ((hash << 5) - hash) ^ g_str_hash (t1->data.klass->name);
6311 return ((hash << 5) - hash) ^ mymono_metadata_type_hash (t1->data.type);
6312 case MONO_TYPE_GENERICINST: {
6314 MonoGenericInst *inst = t1->data.generic_class->context.class_inst;
6315 hash += g_str_hash (t1->data.generic_class->container_class->name);
6317 for (i = 0; i < inst->type_argc; ++i) {
6318 hash += mymono_metadata_type_hash (inst->type_argv [i]);
6327 static MonoReflectionGenericClass*
6328 mono_generic_class_get_object (MonoDomain *domain, MonoType *geninst)
6330 static MonoClass *System_Reflection_MonoGenericClass;
6331 MonoReflectionGenericClass *res;
6332 MonoClass *klass, *gklass;
6333 MonoGenericInst *ginst;
6334 MonoArray *type_args;
6338 g_assert (0); /*This code path should not be taken anymore, all MGC instantiation must happen in managed code*/
6340 if (!System_Reflection_MonoGenericClass) {
6341 System_Reflection_MonoGenericClass = mono_class_from_name (
6342 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
6343 g_assert (System_Reflection_MonoGenericClass);
6346 klass = mono_class_from_mono_type (geninst);
6347 gklass = klass->generic_class->container_class;
6349 mono_class_init (klass);
6352 res = (MonoReflectionGenericClass *) mono_gc_alloc_pinned_obj (mono_class_vtable (domain, System_Reflection_MonoGenericClass), mono_class_instance_size (System_Reflection_MonoGenericClass));
6354 res = (MonoReflectionGenericClass *) mono_object_new (domain, System_Reflection_MonoGenericClass);
6357 res->type.type = geninst;
6358 tb = mono_class_get_ref_info (gklass);
6360 g_assert (!strcmp (tb->vtable->klass->name, "TypeBuilder"));
6361 MONO_OBJECT_SETREF (res, generic_type, tb);
6363 ginst = klass->generic_class->context.class_inst;
6364 type_args = mono_array_new (domain, mono_defaults.systemtype_class, ginst->type_argc);
6365 for (i = 0; i < ginst->type_argc; ++i)
6366 mono_array_setref (type_args, i, mono_type_get_object (domain, ginst->type_argv [i]));
6367 MONO_OBJECT_SETREF (res, type_arguments, type_args);
6373 verify_safe_for_managed_space (MonoType *type)
6375 switch (type->type) {
6377 case MONO_TYPE_ARRAY:
6378 return verify_safe_for_managed_space (&type->data.array->eklass->byval_arg);
6380 return verify_safe_for_managed_space (type->data.type);
6381 case MONO_TYPE_SZARRAY:
6382 return verify_safe_for_managed_space (&type->data.klass->byval_arg);
6383 case MONO_TYPE_GENERICINST: {
6384 MonoGenericInst *inst = type->data.generic_class->inst;
6388 for (i = 0; i < inst->type_argc; ++i)
6389 if (!verify_safe_for_managed_space (inst->type_argv [i]))
6395 case MONO_TYPE_MVAR:
6402 mono_type_normalize (MonoType *type)
6405 MonoGenericClass *gclass;
6406 MonoGenericInst *ginst;
6408 MonoGenericContainer *gcontainer;
6409 MonoType **argv = NULL;
6410 gboolean is_denorm_gtd = TRUE, requires_rebind = FALSE;
6412 if (type->type != MONO_TYPE_GENERICINST)
6415 gclass = type->data.generic_class;
6416 ginst = gclass->context.class_inst;
6417 if (!ginst->is_open)
6420 gtd = gclass->container_class;
6421 gcontainer = gtd->generic_container;
6422 argv = g_newa (MonoType*, ginst->type_argc);
6424 for (i = 0; i < ginst->type_argc; ++i) {
6425 MonoType *t = ginst->type_argv [i], *norm;
6426 if (t->type != MONO_TYPE_VAR || t->data.generic_param->num != i || t->data.generic_param->owner != gcontainer)
6427 is_denorm_gtd = FALSE;
6428 norm = mono_type_normalize (t);
6431 requires_rebind = TRUE;
6435 return type->byref == gtd->byval_arg.byref ? >d->byval_arg : >d->this_arg;
6437 if (requires_rebind) {
6438 MonoClass *klass = mono_class_bind_generic_parameters (gtd, ginst->type_argc, argv, gclass->is_dynamic);
6439 return type->byref == klass->byval_arg.byref ? &klass->byval_arg : &klass->this_arg;
6445 * mono_type_get_object:
6446 * @domain: an app domain
6449 * Return an System.MonoType object representing the type @type.
6452 mono_type_get_object (MonoDomain *domain, MonoType *type)
6454 MonoType *norm_type;
6455 MonoReflectionType *res;
6456 MonoClass *klass = mono_class_from_mono_type (type);
6458 /*we must avoid using @type as it might have come
6459 * from a mono_metadata_type_dup and the caller
6460 * expects that is can be freed.
6461 * Using the right type from
6463 type = klass->byval_arg.byref == type->byref ? &klass->byval_arg : &klass->this_arg;
6465 /* void is very common */
6466 if (type->type == MONO_TYPE_VOID && domain->typeof_void)
6467 return (MonoReflectionType*)domain->typeof_void;
6470 * If the vtable of the given class was already created, we can use
6471 * the MonoType from there and avoid all locking and hash table lookups.
6473 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6474 * that the resulting object is different.
6476 if (type == &klass->byval_arg && !klass->image->dynamic) {
6477 MonoVTable *vtable = mono_class_try_get_vtable (domain, klass);
6478 if (vtable && vtable->type)
6479 return vtable->type;
6482 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6483 mono_domain_lock (domain);
6484 if (!domain->type_hash)
6485 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
6486 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
6487 if ((res = mono_g_hash_table_lookup (domain->type_hash, type))) {
6488 mono_domain_unlock (domain);
6489 mono_loader_unlock ();
6493 /*Types must be normalized so a generic instance of the GTD get's the same inner type.
6494 * For example in: Foo<A,B>; Bar<A> : Foo<A, Bar<A>>
6495 * The second Bar will be encoded a generic instance of Bar with <A> as parameter.
6496 * On all other places, Bar<A> will be encoded as the GTD itself. This is an implementation
6497 * artifact of how generics are encoded and should be transparent to managed code so we
6498 * need to weed out this diference when retrieving managed System.Type objects.
6500 norm_type = mono_type_normalize (type);
6501 if (norm_type != type) {
6502 res = mono_type_get_object (domain, norm_type);
6503 mono_g_hash_table_insert (domain->type_hash, type, res);
6504 mono_domain_unlock (domain);
6505 mono_loader_unlock ();
6509 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6510 if ((type->type == MONO_TYPE_GENERICINST) && type->data.generic_class->is_dynamic && !type->data.generic_class->container_class->wastypebuilder) {
6511 res = (MonoReflectionType *)mono_generic_class_get_object (domain, type);
6512 mono_g_hash_table_insert (domain->type_hash, type, res);
6513 mono_domain_unlock (domain);
6514 mono_loader_unlock ();
6518 if (!verify_safe_for_managed_space (type)) {
6519 mono_domain_unlock (domain);
6520 mono_loader_unlock ();
6521 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6524 if (mono_class_get_ref_info (klass) && !klass->wastypebuilder) {
6525 gboolean is_type_done = TRUE;
6526 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6527 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6528 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6530 if (klass->byval_arg.type == MONO_TYPE_MVAR || klass->byval_arg.type == MONO_TYPE_VAR) {
6531 MonoGenericParam *gparam = klass->byval_arg.data.generic_param;
6533 if (gparam->owner && gparam->owner->is_method) {
6534 MonoMethod *method = gparam->owner->owner.method;
6535 if (method && mono_class_get_generic_type_definition (method->klass)->wastypebuilder)
6536 is_type_done = FALSE;
6537 } else if (gparam->owner && !gparam->owner->is_method) {
6538 MonoClass *klass = gparam->owner->owner.klass;
6539 if (klass && mono_class_get_generic_type_definition (klass)->wastypebuilder)
6540 is_type_done = FALSE;
6544 /* g_assert_not_reached (); */
6545 /* should this be considered an error condition? */
6546 if (is_type_done && !type->byref) {
6547 mono_domain_unlock (domain);
6548 mono_loader_unlock ();
6549 return mono_class_get_ref_info (klass);
6552 // FIXME: Get rid of this, do it in the icalls for Type
6553 mono_class_init (klass);
6555 res = (MonoReflectionType *)mono_gc_alloc_pinned_obj (mono_class_vtable (domain, mono_defaults.monotype_class), mono_class_instance_size (mono_defaults.monotype_class));
6557 res = (MonoReflectionType *)mono_object_new (domain, mono_defaults.monotype_class);
6560 mono_g_hash_table_insert (domain->type_hash, type, res);
6562 if (type->type == MONO_TYPE_VOID)
6563 domain->typeof_void = (MonoObject*)res;
6565 mono_domain_unlock (domain);
6566 mono_loader_unlock ();
6571 * mono_method_get_object:
6572 * @domain: an app domain
6574 * @refclass: the reflected type (can be NULL)
6576 * Return an System.Reflection.MonoMethod object representing the method @method.
6578 MonoReflectionMethod*
6579 mono_method_get_object (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6582 * We use the same C representation for methods and constructors, but the type
6583 * name in C# is different.
6585 static MonoClass *System_Reflection_MonoMethod = NULL;
6586 static MonoClass *System_Reflection_MonoCMethod = NULL;
6587 static MonoClass *System_Reflection_MonoGenericMethod = NULL;
6588 static MonoClass *System_Reflection_MonoGenericCMethod = NULL;
6590 MonoReflectionMethod *ret;
6592 if (method->is_inflated) {
6593 MonoReflectionGenericMethod *gret;
6595 refclass = method->klass;
6596 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6597 if ((*method->name == '.') && (!strcmp (method->name, ".ctor") || !strcmp (method->name, ".cctor"))) {
6598 if (!System_Reflection_MonoGenericCMethod)
6599 System_Reflection_MonoGenericCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericCMethod");
6600 klass = System_Reflection_MonoGenericCMethod;
6602 if (!System_Reflection_MonoGenericMethod)
6603 System_Reflection_MonoGenericMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoGenericMethod");
6604 klass = System_Reflection_MonoGenericMethod;
6606 gret = (MonoReflectionGenericMethod*)mono_object_new (domain, klass);
6607 gret->method.method = method;
6608 MONO_OBJECT_SETREF (gret, method.name, mono_string_new (domain, method->name));
6609 MONO_OBJECT_SETREF (gret, method.reftype, mono_type_get_object (domain, &refclass->byval_arg));
6610 CACHE_OBJECT (MonoReflectionMethod *, method, (MonoReflectionMethod*)gret, refclass);
6614 refclass = method->klass;
6616 CHECK_OBJECT (MonoReflectionMethod *, method, refclass);
6617 if (*method->name == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0)) {
6618 if (!System_Reflection_MonoCMethod)
6619 System_Reflection_MonoCMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoCMethod");
6620 klass = System_Reflection_MonoCMethod;
6623 if (!System_Reflection_MonoMethod)
6624 System_Reflection_MonoMethod = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoMethod");
6625 klass = System_Reflection_MonoMethod;
6627 ret = (MonoReflectionMethod*)mono_object_new (domain, klass);
6628 ret->method = method;
6629 MONO_OBJECT_SETREF (ret, reftype, mono_type_get_object (domain, &refclass->byval_arg));
6630 CACHE_OBJECT (MonoReflectionMethod *, method, ret, refclass);
6634 * mono_method_clear_object:
6636 * Clear the cached reflection objects for the dynamic method METHOD.
6639 mono_method_clear_object (MonoDomain *domain, MonoMethod *method)
6642 g_assert (method->dynamic);
6644 klass = method->klass;
6646 clear_cached_object (domain, method, klass);
6647 klass = klass->parent;
6649 /* Added by mono_param_get_objects () */
6650 clear_cached_object (domain, &(method->signature), NULL);
6651 klass = method->klass;
6653 clear_cached_object (domain, &(method->signature), klass);
6654 klass = klass->parent;
6659 * mono_field_get_object:
6660 * @domain: an app domain
6664 * Return an System.Reflection.MonoField object representing the field @field
6667 MonoReflectionField*
6668 mono_field_get_object (MonoDomain *domain, MonoClass *klass, MonoClassField *field)
6670 MonoReflectionField *res;
6671 static MonoClass *monofield_klass;
6673 CHECK_OBJECT (MonoReflectionField *, field, klass);
6674 if (!monofield_klass)
6675 monofield_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoField");
6676 res = (MonoReflectionField *)mono_object_new (domain, monofield_klass);
6679 MONO_OBJECT_SETREF (res, name, mono_string_new (domain, mono_field_get_name (field)));
6680 if (is_field_on_inst (field))
6681 res->attrs = get_field_on_inst_generic_type (field)->attrs;
6683 res->attrs = field->type->attrs;
6684 MONO_OBJECT_SETREF (res, type, mono_type_get_object (domain, field->type));
6685 CACHE_OBJECT (MonoReflectionField *, field, res, klass);
6689 * mono_property_get_object:
6690 * @domain: an app domain
6692 * @property: a property
6694 * Return an System.Reflection.MonoProperty object representing the property @property
6697 MonoReflectionProperty*
6698 mono_property_get_object (MonoDomain *domain, MonoClass *klass, MonoProperty *property)
6700 MonoReflectionProperty *res;
6701 static MonoClass *monoproperty_klass;
6703 CHECK_OBJECT (MonoReflectionProperty *, property, klass);
6704 if (!monoproperty_klass)
6705 monoproperty_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoProperty");
6706 res = (MonoReflectionProperty *)mono_object_new (domain, monoproperty_klass);
6708 res->property = property;
6709 CACHE_OBJECT (MonoReflectionProperty *, property, res, klass);
6713 * mono_event_get_object:
6714 * @domain: an app domain
6718 * Return an System.Reflection.MonoEvent object representing the event @event
6721 MonoReflectionEvent*
6722 mono_event_get_object (MonoDomain *domain, MonoClass *klass, MonoEvent *event)
6724 MonoReflectionEvent *res;
6725 MonoReflectionMonoEvent *mono_event;
6726 static MonoClass *monoevent_klass;
6728 CHECK_OBJECT (MonoReflectionEvent *, event, klass);
6729 if (!monoevent_klass)
6730 monoevent_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MonoEvent");
6731 mono_event = (MonoReflectionMonoEvent *)mono_object_new (domain, monoevent_klass);
6732 mono_event->klass = klass;
6733 mono_event->event = event;
6734 res = (MonoReflectionEvent*)mono_event;
6735 CACHE_OBJECT (MonoReflectionEvent *, event, res, klass);
6739 * mono_get_reflection_missing_object:
6740 * @domain: Domain where the object lives
6742 * Returns the System.Reflection.Missing.Value singleton object
6743 * (of type System.Reflection.Missing).
6745 * Used as the value for ParameterInfo.DefaultValue when Optional
6749 mono_get_reflection_missing_object (MonoDomain *domain)
6752 static MonoClassField *missing_value_field = NULL;
6754 if (!missing_value_field) {
6755 MonoClass *missing_klass;
6756 missing_klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Missing");
6757 mono_class_init (missing_klass);
6758 missing_value_field = mono_class_get_field_from_name (missing_klass, "Value");
6759 g_assert (missing_value_field);
6761 obj = mono_field_get_value_object (domain, missing_value_field, NULL);
6767 get_dbnull (MonoDomain *domain, MonoObject **dbnull)
6770 *dbnull = mono_get_dbnull_object (domain);
6775 get_reflection_missing (MonoDomain *domain, MonoObject **reflection_missing)
6777 if (!*reflection_missing)
6778 *reflection_missing = mono_get_reflection_missing_object (domain);
6779 return *reflection_missing;
6783 * mono_param_get_objects:
6784 * @domain: an app domain
6787 * Return an System.Reflection.ParameterInfo array object representing the parameters
6788 * in the method @method.
6791 mono_param_get_objects_internal (MonoDomain *domain, MonoMethod *method, MonoClass *refclass)
6793 static MonoClass *System_Reflection_ParameterInfo;
6794 static MonoClass *System_Reflection_ParameterInfo_array;
6795 MonoArray *res = NULL;
6796 MonoReflectionMethod *member = NULL;
6797 MonoReflectionParameter *param = NULL;
6798 char **names, **blobs = NULL;
6799 guint32 *types = NULL;
6800 MonoType *type = NULL;
6801 MonoObject *dbnull = NULL;
6802 MonoObject *missing = NULL;
6803 MonoMarshalSpec **mspecs;
6804 MonoMethodSignature *sig;
6805 MonoVTable *pinfo_vtable;
6808 if (!System_Reflection_ParameterInfo_array) {
6811 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ParameterInfo");
6812 mono_memory_barrier ();
6813 System_Reflection_ParameterInfo = klass;
6815 klass = mono_array_class_get (klass, 1);
6816 mono_memory_barrier ();
6817 System_Reflection_ParameterInfo_array = klass;
6820 if (!mono_method_signature (method)->param_count)
6821 return mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), 0);
6823 /* Note: the cache is based on the address of the signature into the method
6824 * since we already cache MethodInfos with the method as keys.
6826 CHECK_OBJECT (MonoArray*, &(method->signature), refclass);
6828 sig = mono_method_signature (method);
6829 member = mono_method_get_object (domain, method, refclass);
6830 names = g_new (char *, sig->param_count);
6831 mono_method_get_param_names (method, (const char **) names);
6833 mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1);
6834 mono_method_get_marshal_info (method, mspecs);
6836 res = mono_array_new_specific (mono_class_vtable (domain, System_Reflection_ParameterInfo_array), sig->param_count);
6837 pinfo_vtable = mono_class_vtable (domain, System_Reflection_ParameterInfo);
6838 for (i = 0; i < sig->param_count; ++i) {
6839 param = (MonoReflectionParameter *)mono_object_new_specific (pinfo_vtable);
6840 MONO_OBJECT_SETREF (param, ClassImpl, mono_type_get_object (domain, sig->params [i]));
6841 MONO_OBJECT_SETREF (param, MemberImpl, (MonoObject*)member);
6842 MONO_OBJECT_SETREF (param, NameImpl, mono_string_new (domain, names [i]));
6843 param->PositionImpl = i;
6844 param->AttrsImpl = sig->params [i]->attrs;
6846 if (!(param->AttrsImpl & PARAM_ATTRIBUTE_HAS_DEFAULT)) {
6847 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6848 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6850 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6854 blobs = g_new0 (char *, sig->param_count);
6855 types = g_new0 (guint32, sig->param_count);
6856 get_default_param_value_blobs (method, blobs, types);
6859 /* Build MonoType for the type from the Constant Table */
6861 type = g_new0 (MonoType, 1);
6862 type->type = types [i];
6863 type->data.klass = NULL;
6864 if (types [i] == MONO_TYPE_CLASS)
6865 type->data.klass = mono_defaults.object_class;
6866 else if ((sig->params [i]->type == MONO_TYPE_VALUETYPE) && sig->params [i]->data.klass->enumtype) {
6867 /* For enums, types [i] contains the base type */
6869 type->type = MONO_TYPE_VALUETYPE;
6870 type->data.klass = mono_class_from_mono_type (sig->params [i]);
6872 type->data.klass = mono_class_from_mono_type (type);
6874 MONO_OBJECT_SETREF (param, DefaultValueImpl, mono_get_object_from_blob (domain, type, blobs [i]));
6876 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6877 if (types [i] != MONO_TYPE_CLASS && !param->DefaultValueImpl) {
6878 if (param->AttrsImpl & PARAM_ATTRIBUTE_OPTIONAL)
6879 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_reflection_missing (domain, &missing));
6881 MONO_OBJECT_SETREF (param, DefaultValueImpl, get_dbnull (domain, &dbnull));
6887 MONO_OBJECT_SETREF (param, MarshalAsImpl, (MonoObject*)mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [i + 1]));
6889 mono_array_setref (res, i, param);
6896 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
6898 mono_metadata_free_marshal_spec (mspecs [i]);
6901 CACHE_OBJECT (MonoArray *, &(method->signature), res, refclass);
6905 mono_param_get_objects (MonoDomain *domain, MonoMethod *method)
6907 return mono_param_get_objects_internal (domain, method, NULL);
6911 * mono_method_body_get_object:
6912 * @domain: an app domain
6915 * Return an System.Reflection.MethodBody object representing the method @method.
6917 MonoReflectionMethodBody*
6918 mono_method_body_get_object (MonoDomain *domain, MonoMethod *method)
6920 static MonoClass *System_Reflection_MethodBody = NULL;
6921 static MonoClass *System_Reflection_LocalVariableInfo = NULL;
6922 static MonoClass *System_Reflection_ExceptionHandlingClause = NULL;
6923 MonoReflectionMethodBody *ret;
6924 MonoMethodHeader *header;
6925 guint32 method_rva, local_var_sig_token;
6927 unsigned char format, flags;
6930 if (!System_Reflection_MethodBody)
6931 System_Reflection_MethodBody = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "MethodBody");
6932 if (!System_Reflection_LocalVariableInfo)
6933 System_Reflection_LocalVariableInfo = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "LocalVariableInfo");
6934 if (!System_Reflection_ExceptionHandlingClause)
6935 System_Reflection_ExceptionHandlingClause = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "ExceptionHandlingClause");
6937 CHECK_OBJECT (MonoReflectionMethodBody *, method, NULL);
6939 if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) ||
6940 (method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
6941 (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) ||
6942 (method->iflags & METHOD_IMPL_ATTRIBUTE_RUNTIME))
6944 header = mono_method_get_header (method);
6946 /* Obtain local vars signature token */
6947 method_rva = mono_metadata_decode_row_col (&method->klass->image->tables [MONO_TABLE_METHOD], mono_metadata_token_index (method->token) - 1, MONO_METHOD_RVA);
6948 ptr = mono_image_rva_map (method->klass->image, method_rva);
6949 flags = *(const unsigned char *) ptr;
6950 format = flags & METHOD_HEADER_FORMAT_MASK;
6952 case METHOD_HEADER_TINY_FORMAT:
6953 local_var_sig_token = 0;
6955 case METHOD_HEADER_FAT_FORMAT:
6959 local_var_sig_token = read32 (ptr);
6962 g_assert_not_reached ();
6965 ret = (MonoReflectionMethodBody*)mono_object_new (domain, System_Reflection_MethodBody);
6967 ret->init_locals = header->init_locals;
6968 ret->max_stack = header->max_stack;
6969 ret->local_var_sig_token = local_var_sig_token;
6970 MONO_OBJECT_SETREF (ret, il, mono_array_new_cached (domain, mono_defaults.byte_class, header->code_size));
6971 memcpy (mono_array_addr (ret->il, guint8, 0), header->code, header->code_size);
6974 MONO_OBJECT_SETREF (ret, locals, mono_array_new_cached (domain, System_Reflection_LocalVariableInfo, header->num_locals));
6975 for (i = 0; i < header->num_locals; ++i) {
6976 MonoReflectionLocalVariableInfo *info = (MonoReflectionLocalVariableInfo*)mono_object_new (domain, System_Reflection_LocalVariableInfo);
6977 MONO_OBJECT_SETREF (info, local_type, mono_type_get_object (domain, header->locals [i]));
6978 info->is_pinned = header->locals [i]->pinned;
6979 info->local_index = i;
6980 mono_array_setref (ret->locals, i, info);
6984 MONO_OBJECT_SETREF (ret, clauses, mono_array_new_cached (domain, System_Reflection_ExceptionHandlingClause, header->num_clauses));
6985 for (i = 0; i < header->num_clauses; ++i) {
6986 MonoReflectionExceptionHandlingClause *info = (MonoReflectionExceptionHandlingClause*)mono_object_new (domain, System_Reflection_ExceptionHandlingClause);
6987 MonoExceptionClause *clause = &header->clauses [i];
6989 info->flags = clause->flags;
6990 info->try_offset = clause->try_offset;
6991 info->try_length = clause->try_len;
6992 info->handler_offset = clause->handler_offset;
6993 info->handler_length = clause->handler_len;
6994 if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER)
6995 info->filter_offset = clause->data.filter_offset;
6996 else if (clause->data.catch_class)
6997 MONO_OBJECT_SETREF (info, catch_type, mono_type_get_object (mono_domain_get (), &clause->data.catch_class->byval_arg));
6999 mono_array_setref (ret->clauses, i, info);
7002 mono_metadata_free_mh (header);
7003 CACHE_OBJECT (MonoReflectionMethodBody *, method, ret, NULL);
7008 * mono_get_dbnull_object:
7009 * @domain: Domain where the object lives
7011 * Returns the System.DBNull.Value singleton object
7013 * Used as the value for ParameterInfo.DefaultValue
7016 mono_get_dbnull_object (MonoDomain *domain)
7019 static MonoClassField *dbnull_value_field = NULL;
7021 if (!dbnull_value_field) {
7022 MonoClass *dbnull_klass;
7023 dbnull_klass = mono_class_from_name (mono_defaults.corlib, "System", "DBNull");
7024 mono_class_init (dbnull_klass);
7025 dbnull_value_field = mono_class_get_field_from_name (dbnull_klass, "Value");
7026 g_assert (dbnull_value_field);
7028 obj = mono_field_get_value_object (domain, dbnull_value_field, NULL);
7034 get_default_param_value_blobs (MonoMethod *method, char **blobs, guint32 *types)
7036 guint32 param_index, i, lastp, crow = 0;
7037 guint32 param_cols [MONO_PARAM_SIZE], const_cols [MONO_CONSTANT_SIZE];
7040 MonoClass *klass = method->klass;
7041 MonoImage *image = klass->image;
7042 MonoMethodSignature *methodsig = mono_method_signature (method);
7044 MonoTableInfo *constt;
7045 MonoTableInfo *methodt;
7046 MonoTableInfo *paramt;
7048 if (!methodsig->param_count)
7051 mono_class_init (klass);
7053 if (klass->image->dynamic) {
7054 MonoReflectionMethodAux *aux;
7055 if (method->is_inflated)
7056 method = ((MonoMethodInflated*)method)->declaring;
7057 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
7058 if (aux && aux->param_defaults) {
7059 memcpy (blobs, &(aux->param_defaults [1]), methodsig->param_count * sizeof (char*));
7060 memcpy (types, &(aux->param_default_types [1]), methodsig->param_count * sizeof (guint32));
7065 methodt = &klass->image->tables [MONO_TABLE_METHOD];
7066 paramt = &klass->image->tables [MONO_TABLE_PARAM];
7067 constt = &image->tables [MONO_TABLE_CONSTANT];
7069 idx = mono_method_get_index (method) - 1;
7070 g_assert (idx != -1);
7072 param_index = mono_metadata_decode_row_col (methodt, idx, MONO_METHOD_PARAMLIST);
7073 if (idx + 1 < methodt->rows)
7074 lastp = mono_metadata_decode_row_col (methodt, idx + 1, MONO_METHOD_PARAMLIST);
7076 lastp = paramt->rows + 1;
7078 for (i = param_index; i < lastp; ++i) {
7081 mono_metadata_decode_row (paramt, i - 1, param_cols, MONO_PARAM_SIZE);
7082 paramseq = param_cols [MONO_PARAM_SEQUENCE];
7084 if (!(param_cols [MONO_PARAM_FLAGS] & PARAM_ATTRIBUTE_HAS_DEFAULT))
7087 crow = mono_metadata_get_constant_index (image, MONO_TOKEN_PARAM_DEF | i, crow + 1);
7092 mono_metadata_decode_row (constt, crow - 1, const_cols, MONO_CONSTANT_SIZE);
7093 blobs [paramseq - 1] = (gpointer) mono_metadata_blob_heap (image, const_cols [MONO_CONSTANT_VALUE]);
7094 types [paramseq - 1] = const_cols [MONO_CONSTANT_TYPE];
7101 mono_get_object_from_blob (MonoDomain *domain, MonoType *type, const char *blob)
7106 MonoType *basetype = type;
7111 klass = mono_class_from_mono_type (type);
7112 if (klass->valuetype) {
7113 object = mono_object_new (domain, klass);
7114 retval = ((gchar *) object + sizeof (MonoObject));
7115 if (klass->enumtype)
7116 basetype = mono_class_enum_basetype (klass);
7121 if (!mono_get_constant_value_from_blob (domain, basetype->type, blob, retval))
7128 assembly_name_to_aname (MonoAssemblyName *assembly, char *p) {
7132 memset (assembly, 0, sizeof (MonoAssemblyName));
7134 assembly->culture = "";
7135 memset (assembly->public_key_token, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH);
7137 while (*p && (isalnum (*p) || *p == '.' || *p == '-' || *p == '_' || *p == '$' || *p == '@'))
7140 while (g_ascii_isspace (*p) || *p == ',') {
7149 if (*p == 'V' && g_ascii_strncasecmp (p, "Version=", 8) == 0) {
7151 assembly->major = strtoul (p, &s, 10);
7152 if (s == p || *s != '.')
7155 assembly->minor = strtoul (p, &s, 10);
7156 if (s == p || *s != '.')
7159 assembly->build = strtoul (p, &s, 10);
7160 if (s == p || *s != '.')
7163 assembly->revision = strtoul (p, &s, 10);
7167 } else if (*p == 'C' && g_ascii_strncasecmp (p, "Culture=", 8) == 0) {
7169 if (g_ascii_strncasecmp (p, "neutral", 7) == 0) {
7170 assembly->culture = "";
7173 assembly->culture = p;
7174 while (*p && *p != ',') {
7178 } else if (*p == 'P' && g_ascii_strncasecmp (p, "PublicKeyToken=", 15) == 0) {
7180 if (strncmp (p, "null", 4) == 0) {
7185 while (*p && *p != ',') {
7188 len = (p - start + 1);
7189 if (len > MONO_PUBLIC_KEY_TOKEN_LENGTH)
7190 len = MONO_PUBLIC_KEY_TOKEN_LENGTH;
7191 g_strlcpy ((char*)assembly->public_key_token, start, len);
7194 while (*p && *p != ',')
7198 while (g_ascii_isspace (*p) || *p == ',') {
7212 * mono_reflection_parse_type:
7215 * Parse a type name as accepted by the GetType () method and output the info
7216 * extracted in the info structure.
7217 * the name param will be mangled, so, make a copy before passing it to this function.
7218 * The fields in info will be valid until the memory pointed to by name is valid.
7220 * See also mono_type_get_name () below.
7222 * Returns: 0 on parse error.
7225 _mono_reflection_parse_type (char *name, char **endptr, gboolean is_recursed,
7226 MonoTypeNameParse *info)
7228 char *start, *p, *w, *temp, *last_point, *startn;
7229 int in_modifiers = 0;
7230 int isbyref = 0, rank, arity = 0, i;
7232 start = p = w = name;
7234 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7235 memset (&info->assembly, 0, sizeof (MonoAssemblyName));
7236 info->name = info->name_space = NULL;
7237 info->nested = NULL;
7238 info->modifiers = NULL;
7239 info->type_arguments = NULL;
7241 /* last_point separates the namespace from the name */
7244 while (*p == ' ') p++, start++, w++, name++;
7249 *p = 0; /* NULL terminate the name */
7251 info->nested = g_list_append (info->nested, startn);
7252 /* we have parsed the nesting namespace + name */
7256 info->name_space = start;
7258 info->name = last_point + 1;
7260 info->name_space = (char *)"";
7279 i = strtol (p, &temp, 10);
7296 info->name_space = start;
7298 info->name = last_point + 1;
7300 info->name_space = (char *)"";
7307 if (isbyref) /* only one level allowed by the spec */
7310 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (0));
7314 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-1));
7320 info->type_arguments = g_ptr_array_new ();
7321 for (i = 0; i < arity; i++) {
7322 MonoTypeNameParse *subinfo = g_new0 (MonoTypeNameParse, 1);
7323 gboolean fqname = FALSE;
7325 g_ptr_array_add (info->type_arguments, subinfo);
7332 if (!_mono_reflection_parse_type (p, &p, TRUE, subinfo))
7335 /*MS is lenient on [] delimited parameters that aren't fqn - and F# uses them.*/
7336 if (fqname && (*p != ']')) {
7344 while (*p && (*p != ']'))
7352 if (g_ascii_isspace (*aname)) {
7359 !assembly_name_to_aname (&subinfo->assembly, aname))
7361 } else if (fqname && (*p == ']')) {
7365 if (i + 1 < arity) {
7385 else if (*p == '*') /* '*' means unknown lower bound */
7386 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (-2));
7393 info->modifiers = g_list_append (info->modifiers, GUINT_TO_POINTER (rank));
7404 if (g_ascii_isspace (*p)) {
7411 return 0; /* missing assembly name */
7412 if (!assembly_name_to_aname (&info->assembly, p))
7418 if (info->assembly.name)
7421 // *w = 0; /* terminate class name */
7423 if (!info->name || !*info->name)
7427 /* add other consistency checks */
7432 mono_reflection_parse_type (char *name, MonoTypeNameParse *info)
7434 return _mono_reflection_parse_type (name, NULL, FALSE, info);
7438 _mono_reflection_get_type_from_info (MonoTypeNameParse *info, MonoImage *image, gboolean ignorecase)
7440 gboolean type_resolve = FALSE;
7442 MonoImage *rootimage = image;
7444 if (info->assembly.name) {
7445 MonoAssembly *assembly = mono_assembly_loaded (&info->assembly);
7446 if (!assembly && image && image->assembly && mono_assembly_names_equal (&info->assembly, &image->assembly->aname))
7448 * This could happen in the AOT compiler case when the search hook is not
7451 assembly = image->assembly;
7453 /* then we must load the assembly ourselve - see #60439 */
7454 assembly = mono_assembly_load (&info->assembly, NULL, NULL);
7458 image = assembly->image;
7459 } else if (!image) {
7460 image = mono_defaults.corlib;
7463 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7464 if (type == NULL && !info->assembly.name && image != mono_defaults.corlib) {
7465 image = mono_defaults.corlib;
7466 type = mono_reflection_get_type_with_rootimage (rootimage, image, info, ignorecase, &type_resolve);
7473 mono_reflection_get_type_internal (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase)
7478 gboolean bounded = FALSE;
7481 image = mono_defaults.corlib;
7484 klass = mono_class_from_name_case (image, info->name_space, info->name);
7486 klass = mono_class_from_name (image, info->name_space, info->name);
7489 for (mod = info->nested; mod; mod = mod->next) {
7490 gpointer iter = NULL;
7494 mono_class_init (parent);
7496 while ((klass = mono_class_get_nested_types (parent, &iter))) {
7498 if (mono_utf8_strcasecmp (klass->name, mod->data) == 0)
7501 if (strcmp (klass->name, mod->data) == 0)
7510 mono_class_init (klass);
7512 if (info->type_arguments) {
7513 MonoType **type_args = g_new0 (MonoType *, info->type_arguments->len);
7514 MonoReflectionType *the_type;
7518 for (i = 0; i < info->type_arguments->len; i++) {
7519 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7521 type_args [i] = _mono_reflection_get_type_from_info (subinfo, rootimage, ignorecase);
7522 if (!type_args [i]) {
7528 the_type = mono_type_get_object (mono_domain_get (), &klass->byval_arg);
7530 instance = mono_reflection_bind_generic_parameters (
7531 the_type, info->type_arguments->len, type_args);
7537 klass = mono_class_from_mono_type (instance);
7540 for (mod = info->modifiers; mod; mod = mod->next) {
7541 modval = GPOINTER_TO_UINT (mod->data);
7542 if (!modval) { /* byref: must be last modifier */
7543 return &klass->this_arg;
7544 } else if (modval == -1) {
7545 klass = mono_ptr_class_get (&klass->byval_arg);
7546 } else if (modval == -2) {
7548 } else { /* array rank */
7549 klass = mono_bounded_array_class_get (klass, modval, bounded);
7551 mono_class_init (klass);
7554 return &klass->byval_arg;
7558 * mono_reflection_get_type:
7559 * @image: a metadata context
7560 * @info: type description structure
7561 * @ignorecase: flag for case-insensitive string compares
7562 * @type_resolve: whenever type resolve was already tried
7564 * Build a MonoType from the type description in @info.
7569 mono_reflection_get_type (MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve) {
7570 return mono_reflection_get_type_with_rootimage(image, image, info, ignorecase, type_resolve);
7574 mono_reflection_get_type_internal_dynamic (MonoImage *rootimage, MonoAssembly *assembly, MonoTypeNameParse *info, gboolean ignorecase)
7576 MonoReflectionAssemblyBuilder *abuilder;
7580 g_assert (assembly->dynamic);
7581 abuilder = (MonoReflectionAssemblyBuilder*)mono_assembly_get_object (((MonoDynamicAssembly*)assembly)->domain, assembly);
7583 /* Enumerate all modules */
7586 if (abuilder->modules) {
7587 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
7588 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
7589 type = mono_reflection_get_type_internal (rootimage, &mb->dynamic_image->image, info, ignorecase);
7595 if (!type && abuilder->loaded_modules) {
7596 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
7597 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
7598 type = mono_reflection_get_type_internal (rootimage, mod->image, info, ignorecase);
7608 mono_reflection_get_type_with_rootimage (MonoImage *rootimage, MonoImage* image, MonoTypeNameParse *info, gboolean ignorecase, gboolean *type_resolve)
7611 MonoReflectionAssembly *assembly;
7615 if (image && image->dynamic)
7616 type = mono_reflection_get_type_internal_dynamic (rootimage, image->assembly, info, ignorecase);
7618 type = mono_reflection_get_type_internal (rootimage, image, info, ignorecase);
7621 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7628 *type_resolve = TRUE;
7631 /* Reconstruct the type name */
7632 fullName = g_string_new ("");
7633 if (info->name_space && (info->name_space [0] != '\0'))
7634 g_string_printf (fullName, "%s.%s", info->name_space, info->name);
7636 g_string_printf (fullName, "%s", info->name);
7637 for (mod = info->nested; mod; mod = mod->next)
7638 g_string_append_printf (fullName, "+%s", (char*)mod->data);
7640 assembly = mono_domain_try_type_resolve ( mono_domain_get (), fullName->str, NULL);
7642 if (assembly->assembly->dynamic)
7643 type = mono_reflection_get_type_internal_dynamic (rootimage, assembly->assembly, info, ignorecase);
7645 type = mono_reflection_get_type_internal (rootimage, assembly->assembly->image,
7648 g_string_free (fullName, TRUE);
7653 mono_reflection_free_type_info (MonoTypeNameParse *info)
7655 g_list_free (info->modifiers);
7656 g_list_free (info->nested);
7658 if (info->type_arguments) {
7661 for (i = 0; i < info->type_arguments->len; i++) {
7662 MonoTypeNameParse *subinfo = g_ptr_array_index (info->type_arguments, i);
7664 mono_reflection_free_type_info (subinfo);
7665 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7669 g_ptr_array_free (info->type_arguments, TRUE);
7674 * mono_reflection_type_from_name:
7676 * @image: a metadata context (can be NULL).
7678 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7679 * it defaults to get the type from @image or, if @image is NULL or loading
7680 * from it fails, uses corlib.
7684 mono_reflection_type_from_name (char *name, MonoImage *image)
7686 MonoType *type = NULL;
7687 MonoTypeNameParse info;
7690 /* Make a copy since parse_type modifies its argument */
7691 tmp = g_strdup (name);
7693 /*g_print ("requested type %s\n", str);*/
7694 if (mono_reflection_parse_type (tmp, &info)) {
7695 type = _mono_reflection_get_type_from_info (&info, image, FALSE);
7699 mono_reflection_free_type_info (&info);
7704 * mono_reflection_get_token:
7706 * Return the metadata token of OBJ which should be an object
7707 * representing a metadata element.
7710 mono_reflection_get_token (MonoObject *obj)
7715 klass = obj->vtable->klass;
7717 if (strcmp (klass->name, "MethodBuilder") == 0) {
7718 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder *)obj;
7720 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7721 } else if (strcmp (klass->name, "ConstructorBuilder") == 0) {
7722 MonoReflectionCtorBuilder *mb = (MonoReflectionCtorBuilder *)obj;
7724 token = mb->table_idx | MONO_TOKEN_METHOD_DEF;
7725 } else if (strcmp (klass->name, "FieldBuilder") == 0) {
7726 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)obj;
7728 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7729 token = mono_image_create_token (((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image, obj, FALSE, TRUE);
7730 } else if (strcmp (klass->name, "TypeBuilder") == 0) {
7731 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)obj;
7732 token = tb->table_idx | MONO_TOKEN_TYPE_DEF;
7733 } else if (strcmp (klass->name, "MonoType") == 0) {
7734 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
7735 token = mono_class_from_mono_type (type)->type_token;
7736 } else if (strcmp (klass->name, "MonoCMethod") == 0 ||
7737 strcmp (klass->name, "MonoMethod") == 0 ||
7738 strcmp (klass->name, "MonoGenericMethod") == 0 ||
7739 strcmp (klass->name, "MonoGenericCMethod") == 0) {
7740 MonoReflectionMethod *m = (MonoReflectionMethod *)obj;
7741 if (m->method->is_inflated) {
7742 MonoMethodInflated *inflated = (MonoMethodInflated *) m->method;
7743 return inflated->declaring->token;
7745 token = m->method->token;
7747 } else if (strcmp (klass->name, "MonoField") == 0) {
7748 MonoReflectionField *f = (MonoReflectionField*)obj;
7750 if (is_field_on_inst (f->field)) {
7751 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass*)f->field->parent->generic_class;
7752 int field_index = f->field - dgclass->fields;
7755 g_assert (field_index >= 0 && field_index < dgclass->count_fields);
7756 obj = dgclass->field_objects [field_index];
7757 return mono_reflection_get_token (obj);
7759 token = mono_class_get_field_token (f->field);
7760 } else if (strcmp (klass->name, "MonoProperty") == 0) {
7761 MonoReflectionProperty *p = (MonoReflectionProperty*)obj;
7763 token = mono_class_get_property_token (p->property);
7764 } else if (strcmp (klass->name, "MonoEvent") == 0) {
7765 MonoReflectionMonoEvent *p = (MonoReflectionMonoEvent*)obj;
7767 token = mono_class_get_event_token (p->event);
7768 } else if (strcmp (klass->name, "ParameterInfo") == 0) {
7769 MonoReflectionParameter *p = (MonoReflectionParameter*)obj;
7770 MonoClass *member_class = mono_object_class (p->MemberImpl);
7771 g_assert (mono_class_is_reflection_method_or_constructor (member_class));
7773 token = mono_method_get_param_token (((MonoReflectionMethod*)p->MemberImpl)->method, p->PositionImpl);
7774 } else if (strcmp (klass->name, "Module") == 0 || strcmp (klass->name, "MonoModule") == 0) {
7775 MonoReflectionModule *m = (MonoReflectionModule*)obj;
7778 } else if (strcmp (klass->name, "Assembly") == 0 || strcmp (klass->name, "MonoAssembly") == 0) {
7779 token = mono_metadata_make_token (MONO_TABLE_ASSEMBLY, 1);
7781 gchar *msg = g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass->name_space, klass->name);
7782 MonoException *ex = mono_get_exception_not_implemented (msg);
7784 mono_raise_exception (ex);
7791 load_cattr_value (MonoImage *image, MonoType *t, const char *p, const char **end)
7793 int slen, type = t->type;
7794 MonoClass *tklass = t->data.klass;
7800 case MONO_TYPE_BOOLEAN: {
7801 MonoBoolean *bval = g_malloc (sizeof (MonoBoolean));
7806 case MONO_TYPE_CHAR:
7808 case MONO_TYPE_I2: {
7809 guint16 *val = g_malloc (sizeof (guint16));
7814 #if SIZEOF_VOID_P == 4
7820 case MONO_TYPE_I4: {
7821 guint32 *val = g_malloc (sizeof (guint32));
7826 #if SIZEOF_VOID_P == 8
7827 case MONO_TYPE_U: /* error out instead? this should probably not happen */
7831 case MONO_TYPE_I8: {
7832 guint64 *val = g_malloc (sizeof (guint64));
7837 case MONO_TYPE_R8: {
7838 double *val = g_malloc (sizeof (double));
7843 case MONO_TYPE_VALUETYPE:
7844 if (t->data.klass->enumtype) {
7845 type = mono_class_enum_basetype (t->data.klass)->type;
7848 g_error ("generic valutype %s not handled in custom attr value decoding", t->data.klass->name);
7851 case MONO_TYPE_STRING:
7852 if (*p == (char)0xFF) {
7856 slen = mono_metadata_decode_value (p, &p);
7858 return mono_string_new_len (mono_domain_get (), p, slen);
7859 case MONO_TYPE_CLASS: {
7862 if (*p == (char)0xFF) {
7867 slen = mono_metadata_decode_value (p, &p);
7868 n = g_memdup (p, slen + 1);
7870 t = mono_reflection_type_from_name (n, image);
7872 g_warning ("Cannot load type '%s'", n);
7876 return mono_type_get_object (mono_domain_get (), t);
7880 case MONO_TYPE_OBJECT: {
7883 MonoClass *subc = NULL;
7888 } else if (subt == 0x0E) {
7889 type = MONO_TYPE_STRING;
7891 } else if (subt == 0x1D) {
7892 MonoType simple_type = {{0}};
7897 /* See Partition II, Appendix B3 */
7898 etype = MONO_TYPE_OBJECT;
7899 type = MONO_TYPE_SZARRAY;
7900 simple_type.type = etype;
7901 tklass = mono_class_from_mono_type (&simple_type);
7903 } else if (subt == 0x55) {
7906 slen = mono_metadata_decode_value (p, &p);
7907 n = g_memdup (p, slen + 1);
7909 t = mono_reflection_type_from_name (n, image);
7911 g_error ("Cannot load type '%s'", n);
7914 subc = mono_class_from_mono_type (t);
7915 } else if (subt >= MONO_TYPE_BOOLEAN && subt <= MONO_TYPE_R8) {
7916 MonoType simple_type = {{0}};
7917 simple_type.type = subt;
7918 subc = mono_class_from_mono_type (&simple_type);
7920 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt);
7922 val = load_cattr_value (image, &subc->byval_arg, p, end);
7923 obj = mono_object_new (mono_domain_get (), subc);
7924 g_assert (!subc->has_references);
7925 memcpy ((char*)obj + sizeof (MonoObject), val, mono_class_value_size (subc, NULL));
7929 case MONO_TYPE_SZARRAY: {
7931 guint32 i, alen, basetype;
7934 if (alen == 0xffffffff) {
7938 arr = mono_array_new (mono_domain_get(), tklass, alen);
7939 basetype = tklass->byval_arg.type;
7940 if (basetype == MONO_TYPE_VALUETYPE && tklass->enumtype)
7941 basetype = mono_class_enum_basetype (tklass)->type;
7946 case MONO_TYPE_BOOLEAN:
7947 for (i = 0; i < alen; i++) {
7948 MonoBoolean val = *p++;
7949 mono_array_set (arr, MonoBoolean, i, val);
7952 case MONO_TYPE_CHAR:
7955 for (i = 0; i < alen; i++) {
7956 guint16 val = read16 (p);
7957 mono_array_set (arr, guint16, i, val);
7964 for (i = 0; i < alen; i++) {
7965 guint32 val = read32 (p);
7966 mono_array_set (arr, guint32, i, val);
7971 for (i = 0; i < alen; i++) {
7974 mono_array_set (arr, double, i, val);
7980 for (i = 0; i < alen; i++) {
7981 guint64 val = read64 (p);
7982 mono_array_set (arr, guint64, i, val);
7986 case MONO_TYPE_CLASS:
7987 case MONO_TYPE_OBJECT:
7988 case MONO_TYPE_STRING:
7989 for (i = 0; i < alen; i++) {
7990 MonoObject *item = load_cattr_value (image, &tklass->byval_arg, p, &p);
7991 mono_array_setref (arr, i, item);
7995 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype);
8001 g_error ("Type 0x%02x not handled in custom attr value decoding", type);
8007 create_cattr_typed_arg (MonoType *t, MonoObject *val)
8009 static MonoClass *klass;
8010 static MonoMethod *ctor;
8012 void *params [2], *unboxed;
8015 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeTypedArgument");
8017 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8019 params [0] = mono_type_get_object (mono_domain_get (), t);
8021 retval = mono_object_new (mono_domain_get (), klass);
8022 unboxed = mono_object_unbox (retval);
8023 mono_runtime_invoke (ctor, unboxed, params, NULL);
8029 create_cattr_named_arg (void *minfo, MonoObject *typedarg)
8031 static MonoClass *klass;
8032 static MonoMethod *ctor;
8034 void *unboxed, *params [2];
8037 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "CustomAttributeNamedArgument");
8039 ctor = mono_class_get_method_from_name (klass, ".ctor", 2);
8042 params [1] = typedarg;
8043 retval = mono_object_new (mono_domain_get (), klass);
8044 unboxed = mono_object_unbox (retval);
8045 mono_runtime_invoke (ctor, unboxed, params, NULL);
8051 type_is_reference (MonoType *type)
8053 switch (type->type) {
8054 case MONO_TYPE_BOOLEAN:
8055 case MONO_TYPE_CHAR:
8068 case MONO_TYPE_VALUETYPE:
8076 free_param_data (MonoMethodSignature *sig, void **params) {
8078 for (i = 0; i < sig->param_count; ++i) {
8079 if (!type_is_reference (sig->params [i]))
8080 g_free (params [i]);
8085 * Find the field index in the metadata FieldDef table.
8088 find_field_index (MonoClass *klass, MonoClassField *field) {
8091 for (i = 0; i < klass->field.count; ++i) {
8092 if (field == &klass->fields [i])
8093 return klass->field.first + 1 + i;
8099 * Find the property index in the metadata Property table.
8102 find_property_index (MonoClass *klass, MonoProperty *property) {
8105 for (i = 0; i < klass->ext->property.count; ++i) {
8106 if (property == &klass->ext->properties [i])
8107 return klass->ext->property.first + 1 + i;
8113 * Find the event index in the metadata Event table.
8116 find_event_index (MonoClass *klass, MonoEvent *event) {
8119 for (i = 0; i < klass->ext->event.count; ++i) {
8120 if (event == &klass->ext->events [i])
8121 return klass->ext->event.first + 1 + i;
8127 create_custom_attr (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8129 const char *p = (const char*)data;
8131 guint32 i, j, num_named;
8133 void *params_buf [32];
8135 MonoMethodSignature *sig;
8137 mono_class_init (method->klass);
8139 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8143 attr = mono_object_new (mono_domain_get (), method->klass);
8144 mono_runtime_invoke (method, attr, NULL, NULL);
8148 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8151 /*g_print ("got attr %s\n", method->klass->name);*/
8153 sig = mono_method_signature (method);
8154 if (sig->param_count < 32)
8155 params = params_buf;
8157 /* Allocate using GC so it gets GC tracking */
8158 params = mono_gc_alloc_fixed (sig->param_count * sizeof (void*), NULL);
8162 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8163 params [i] = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8167 attr = mono_object_new (mono_domain_get (), method->klass);
8168 mono_runtime_invoke (method, attr, params, NULL);
8169 free_param_data (method->signature, params);
8170 num_named = read16 (named);
8172 for (j = 0; j < num_named; j++) {
8174 char *name, named_type, data_type;
8175 named_type = *named++;
8176 data_type = *named++; /* type of data */
8177 if (data_type == MONO_TYPE_SZARRAY)
8178 data_type = *named++;
8179 if (data_type == MONO_TYPE_ENUM) {
8182 type_len = mono_metadata_decode_blob_size (named, &named);
8183 type_name = g_malloc (type_len + 1);
8184 memcpy (type_name, named, type_len);
8185 type_name [type_len] = 0;
8187 /* FIXME: lookup the type and check type consistency */
8190 name_len = mono_metadata_decode_blob_size (named, &named);
8191 name = g_malloc (name_len + 1);
8192 memcpy (name, named, name_len);
8193 name [name_len] = 0;
8195 if (named_type == 0x53) {
8196 MonoClassField *field = mono_class_get_field_from_name (mono_object_class (attr), name);
8197 void *val = load_cattr_value (image, field->type, named, &named);
8198 mono_field_set_value (attr, field, val);
8199 if (!type_is_reference (field->type))
8201 } else if (named_type == 0x54) {
8204 MonoType *prop_type;
8206 prop = mono_class_get_property_from_name (mono_object_class (attr), name);
8207 /* can we have more that 1 arg in a custom attr named property? */
8208 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8209 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8210 pparams [0] = load_cattr_value (image, prop_type, named, &named);
8211 mono_property_set_value (prop, attr, pparams, NULL);
8212 if (!type_is_reference (prop_type))
8213 g_free (pparams [0]);
8218 if (params != params_buf)
8219 mono_gc_free_fixed (params);
8225 * mono_reflection_create_custom_attr_data_args:
8227 * Create an array of typed and named arguments from the cattr blob given by DATA.
8228 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8229 * NAMED_ARG_INFO will contain information about the named arguments.
8232 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)
8234 MonoArray *typedargs, *namedargs;
8235 MonoClass *attrklass;
8237 const char *p = (const char*)data;
8239 guint32 i, j, num_named;
8240 CattrNamedArg *arginfo = NULL;
8242 if (!mono_verifier_verify_cattr_content (image, method, data, len, NULL))
8245 mono_class_init (method->klass);
8249 *named_arg_info = NULL;
8251 domain = mono_domain_get ();
8253 if (len < 2 || read16 (p) != 0x0001) /* Prolog */
8256 typedargs = mono_array_new (domain, mono_get_object_class (), mono_method_signature (method)->param_count);
8260 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8264 val = load_cattr_value (image, mono_method_signature (method)->params [i], p, &p);
8265 obj = type_is_reference (mono_method_signature (method)->params [i]) ?
8266 val : mono_value_box (domain, mono_class_from_mono_type (mono_method_signature (method)->params [i]), val);
8267 mono_array_setref (typedargs, i, obj);
8269 if (!type_is_reference (mono_method_signature (method)->params [i]))
8274 num_named = read16 (named);
8275 namedargs = mono_array_new (domain, mono_get_object_class (), num_named);
8277 attrklass = method->klass;
8279 arginfo = g_new0 (CattrNamedArg, num_named);
8280 *named_arg_info = arginfo;
8282 for (j = 0; j < num_named; j++) {
8284 char *name, named_type, data_type;
8285 named_type = *named++;
8286 data_type = *named++; /* type of data */
8287 if (data_type == MONO_TYPE_SZARRAY)
8288 data_type = *named++;
8289 if (data_type == MONO_TYPE_ENUM) {
8292 type_len = mono_metadata_decode_blob_size (named, &named);
8293 type_name = g_malloc (type_len + 1);
8294 memcpy (type_name, named, type_len);
8295 type_name [type_len] = 0;
8297 /* FIXME: lookup the type and check type consistency */
8300 name_len = mono_metadata_decode_blob_size (named, &named);
8301 name = g_malloc (name_len + 1);
8302 memcpy (name, named, name_len);
8303 name [name_len] = 0;
8305 if (named_type == 0x53) {
8307 MonoClassField *field = mono_class_get_field_from_name (attrklass, name);
8310 arginfo [j].type = field->type;
8311 arginfo [j].field = field;
8313 val = load_cattr_value (image, field->type, named, &named);
8314 obj = type_is_reference (field->type) ? val : mono_value_box (domain, mono_class_from_mono_type (field->type), val);
8315 mono_array_setref (namedargs, j, obj);
8316 if (!type_is_reference (field->type))
8318 } else if (named_type == 0x54) {
8320 MonoType *prop_type;
8321 MonoProperty *prop = mono_class_get_property_from_name (attrklass, name);
8324 prop_type = prop->get? mono_method_signature (prop->get)->ret :
8325 mono_method_signature (prop->set)->params [mono_method_signature (prop->set)->param_count - 1];
8327 arginfo [j].type = prop_type;
8328 arginfo [j].prop = prop;
8330 val = load_cattr_value (image, prop_type, named, &named);
8331 obj = type_is_reference (prop_type) ? val : mono_value_box (domain, mono_class_from_mono_type (prop_type), val);
8332 mono_array_setref (namedargs, j, obj);
8333 if (!type_is_reference (prop_type))
8339 *typed_args = typedargs;
8340 *named_args = namedargs;
8344 create_custom_attr_data (MonoImage *image, MonoMethod *method, const guchar *data, guint32 len)
8346 MonoArray *typedargs, *namedargs;
8347 static MonoMethod *ctor;
8351 CattrNamedArg *arginfo;
8354 mono_class_init (method->klass);
8357 ctor = mono_class_get_method_from_name (mono_defaults.customattribute_data_class, ".ctor", 3);
8359 domain = mono_domain_get ();
8361 /* This is for Attributes with no parameters */
8362 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8363 params [0] = mono_method_get_object (domain, method, NULL);
8364 params [1] = params [2] = NULL;
8365 mono_runtime_invoke (method, attr, params, NULL);
8369 mono_reflection_create_custom_attr_data_args (image, method, data, len, &typedargs, &namedargs, &arginfo);
8370 if (!typedargs || !namedargs)
8373 for (i = 0; i < mono_method_signature (method)->param_count; ++i) {
8374 MonoObject *obj = mono_array_get (typedargs, MonoObject*, i);
8375 MonoObject *typedarg;
8377 typedarg = create_cattr_typed_arg (mono_method_signature (method)->params [i], obj);
8378 mono_array_setref (typedargs, i, typedarg);
8381 for (i = 0; i < mono_array_length (namedargs); ++i) {
8382 MonoObject *obj = mono_array_get (namedargs, MonoObject*, i);
8383 MonoObject *typedarg, *namedarg, *minfo;
8385 if (arginfo [i].prop)
8386 minfo = (MonoObject*)mono_property_get_object (domain, NULL, arginfo [i].prop);
8388 minfo = (MonoObject*)mono_field_get_object (domain, NULL, arginfo [i].field);
8390 typedarg = create_cattr_typed_arg (arginfo [i].type, obj);
8391 namedarg = create_cattr_named_arg (minfo, typedarg);
8393 mono_array_setref (namedargs, i, namedarg);
8396 attr = mono_object_new (domain, mono_defaults.customattribute_data_class);
8397 params [0] = mono_method_get_object (domain, method, NULL);
8398 params [1] = typedargs;
8399 params [2] = namedargs;
8400 mono_runtime_invoke (ctor, attr, params, NULL);
8405 mono_custom_attrs_construct (MonoCustomAttrInfo *cinfo)
8411 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, cinfo->num_attrs);
8412 for (i = 0; i < cinfo->num_attrs; ++i) {
8413 if (!cinfo->attrs [i].ctor)
8414 /* The cattr type is not finished yet */
8415 /* We should include the type name but cinfo doesn't contain it */
8416 mono_raise_exception (mono_get_exception_type_load (NULL, NULL));
8417 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8418 mono_array_setref (result, i, attr);
8424 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo *cinfo, MonoClass *attr_klass)
8431 for (i = 0; i < cinfo->num_attrs; ++i) {
8432 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass))
8436 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, n);
8438 for (i = 0; i < cinfo->num_attrs; ++i) {
8439 if (mono_class_is_assignable_from (attr_klass, cinfo->attrs [i].ctor->klass)) {
8440 attr = create_custom_attr (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8441 mono_array_setref (result, n, attr);
8449 mono_custom_attrs_data_construct (MonoCustomAttrInfo *cinfo)
8455 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, cinfo->num_attrs);
8456 for (i = 0; i < cinfo->num_attrs; ++i) {
8457 attr = create_custom_attr_data (cinfo->image, cinfo->attrs [i].ctor, cinfo->attrs [i].data, cinfo->attrs [i].data_size);
8458 mono_array_setref (result, i, attr);
8464 * mono_custom_attrs_from_index:
8466 * Returns: NULL if no attributes are found or if a loading error occurs.
8469 mono_custom_attrs_from_index (MonoImage *image, guint32 idx)
8471 guint32 mtoken, i, len;
8472 guint32 cols [MONO_CUSTOM_ATTR_SIZE];
8474 MonoCustomAttrInfo *ainfo;
8475 GList *tmp, *list = NULL;
8478 ca = &image->tables [MONO_TABLE_CUSTOMATTRIBUTE];
8480 i = mono_metadata_custom_attrs_from_index (image, idx);
8484 while (i < ca->rows) {
8485 if (mono_metadata_decode_row_col (ca, i, MONO_CUSTOM_ATTR_PARENT) != idx)
8487 list = g_list_prepend (list, GUINT_TO_POINTER (i));
8490 len = g_list_length (list);
8493 ainfo = g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * len);
8494 ainfo->num_attrs = len;
8495 ainfo->image = image;
8496 for (i = 0, tmp = list; i < len; ++i, tmp = tmp->next) {
8497 mono_metadata_decode_row (ca, GPOINTER_TO_UINT (tmp->data), cols, MONO_CUSTOM_ATTR_SIZE);
8498 mtoken = cols [MONO_CUSTOM_ATTR_TYPE] >> MONO_CUSTOM_ATTR_TYPE_BITS;
8499 switch (cols [MONO_CUSTOM_ATTR_TYPE] & MONO_CUSTOM_ATTR_TYPE_MASK) {
8500 case MONO_CUSTOM_ATTR_TYPE_METHODDEF:
8501 mtoken |= MONO_TOKEN_METHOD_DEF;
8503 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF:
8504 mtoken |= MONO_TOKEN_MEMBER_REF;
8507 g_error ("Unknown table for custom attr type %08x", cols [MONO_CUSTOM_ATTR_TYPE]);
8510 ainfo->attrs [i].ctor = mono_get_method (image, mtoken, NULL);
8511 if (!ainfo->attrs [i].ctor) {
8512 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image->name, mtoken);
8518 if (!mono_verifier_verify_cattr_blob (image, cols [MONO_CUSTOM_ATTR_VALUE], NULL)) {
8519 /*FIXME raising an exception here doesn't make any sense*/
8520 g_warning ("Invalid custom attribute blob on image %s for index %x", image->name, idx);
8525 data = mono_metadata_blob_heap (image, cols [MONO_CUSTOM_ATTR_VALUE]);
8526 ainfo->attrs [i].data_size = mono_metadata_decode_value (data, &data);
8527 ainfo->attrs [i].data = (guchar*)data;
8535 mono_custom_attrs_from_method (MonoMethod *method)
8540 * An instantiated method has the same cattrs as the generic method definition.
8542 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8543 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8545 if (method->is_inflated)
8546 method = ((MonoMethodInflated *) method)->declaring;
8548 if (method->dynamic || method->klass->image->dynamic)
8549 return lookup_custom_attr (method->klass->image, method);
8552 /* Synthetic methods */
8555 idx = mono_method_get_index (method);
8556 idx <<= MONO_CUSTOM_ATTR_BITS;
8557 idx |= MONO_CUSTOM_ATTR_METHODDEF;
8558 return mono_custom_attrs_from_index (method->klass->image, idx);
8562 mono_custom_attrs_from_class (MonoClass *klass)
8566 if (klass->generic_class)
8567 klass = klass->generic_class->container_class;
8569 if (klass->image->dynamic)
8570 return lookup_custom_attr (klass->image, klass);
8572 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) {
8573 idx = mono_metadata_token_index (klass->sizes.generic_param_token);
8574 idx <<= MONO_CUSTOM_ATTR_BITS;
8575 idx |= MONO_CUSTOM_ATTR_GENERICPAR;
8577 idx = mono_metadata_token_index (klass->type_token);
8578 idx <<= MONO_CUSTOM_ATTR_BITS;
8579 idx |= MONO_CUSTOM_ATTR_TYPEDEF;
8581 return mono_custom_attrs_from_index (klass->image, idx);
8585 mono_custom_attrs_from_assembly (MonoAssembly *assembly)
8589 if (assembly->image->dynamic)
8590 return lookup_custom_attr (assembly->image, assembly);
8591 idx = 1; /* there is only one assembly */
8592 idx <<= MONO_CUSTOM_ATTR_BITS;
8593 idx |= MONO_CUSTOM_ATTR_ASSEMBLY;
8594 return mono_custom_attrs_from_index (assembly->image, idx);
8597 static MonoCustomAttrInfo*
8598 mono_custom_attrs_from_module (MonoImage *image)
8603 return lookup_custom_attr (image, image);
8604 idx = 1; /* there is only one module */
8605 idx <<= MONO_CUSTOM_ATTR_BITS;
8606 idx |= MONO_CUSTOM_ATTR_MODULE;
8607 return mono_custom_attrs_from_index (image, idx);
8611 mono_custom_attrs_from_property (MonoClass *klass, MonoProperty *property)
8615 if (klass->image->dynamic) {
8616 property = mono_metadata_get_corresponding_property_from_generic_type_definition (property);
8617 return lookup_custom_attr (klass->image, property);
8619 idx = find_property_index (klass, property);
8620 idx <<= MONO_CUSTOM_ATTR_BITS;
8621 idx |= MONO_CUSTOM_ATTR_PROPERTY;
8622 return mono_custom_attrs_from_index (klass->image, idx);
8626 mono_custom_attrs_from_event (MonoClass *klass, MonoEvent *event)
8630 if (klass->image->dynamic) {
8631 event = mono_metadata_get_corresponding_event_from_generic_type_definition (event);
8632 return lookup_custom_attr (klass->image, event);
8634 idx = find_event_index (klass, event);
8635 idx <<= MONO_CUSTOM_ATTR_BITS;
8636 idx |= MONO_CUSTOM_ATTR_EVENT;
8637 return mono_custom_attrs_from_index (klass->image, idx);
8641 mono_custom_attrs_from_field (MonoClass *klass, MonoClassField *field)
8644 if (klass->image->dynamic) {
8645 field = mono_metadata_get_corresponding_field_from_generic_type_definition (field);
8646 return lookup_custom_attr (klass->image, field);
8648 idx = find_field_index (klass, field);
8649 idx <<= MONO_CUSTOM_ATTR_BITS;
8650 idx |= MONO_CUSTOM_ATTR_FIELDDEF;
8651 return mono_custom_attrs_from_index (klass->image, idx);
8655 mono_custom_attrs_from_param (MonoMethod *method, guint32 param)
8658 guint32 i, idx, method_index;
8659 guint32 param_list, param_last, param_pos, found;
8661 MonoReflectionMethodAux *aux;
8664 * An instantiated method has the same cattrs as the generic method definition.
8666 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8667 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8669 if (method->is_inflated)
8670 method = ((MonoMethodInflated *) method)->declaring;
8672 if (method->klass->image->dynamic) {
8673 MonoCustomAttrInfo *res, *ainfo;
8676 aux = g_hash_table_lookup (((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
8677 if (!aux || !aux->param_cattr)
8680 /* Need to copy since it will be freed later */
8681 ainfo = aux->param_cattr [param];
8684 size = MONO_SIZEOF_CUSTOM_ATTR_INFO + sizeof (MonoCustomAttrEntry) * ainfo->num_attrs;
8685 res = g_malloc0 (size);
8686 memcpy (res, ainfo, size);
8690 image = method->klass->image;
8691 method_index = mono_method_get_index (method);
8692 ca = &image->tables [MONO_TABLE_METHOD];
8694 param_list = mono_metadata_decode_row_col (ca, method_index - 1, MONO_METHOD_PARAMLIST);
8695 if (method_index == ca->rows) {
8696 ca = &image->tables [MONO_TABLE_PARAM];
8697 param_last = ca->rows + 1;
8699 param_last = mono_metadata_decode_row_col (ca, method_index, MONO_METHOD_PARAMLIST);
8700 ca = &image->tables [MONO_TABLE_PARAM];
8703 for (i = param_list; i < param_last; ++i) {
8704 param_pos = mono_metadata_decode_row_col (ca, i - 1, MONO_PARAM_SEQUENCE);
8705 if (param_pos == param) {
8713 idx <<= MONO_CUSTOM_ATTR_BITS;
8714 idx |= MONO_CUSTOM_ATTR_PARAMDEF;
8715 return mono_custom_attrs_from_index (image, idx);
8719 mono_custom_attrs_has_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8723 for (i = 0; i < ainfo->num_attrs; ++i) {
8724 klass = ainfo->attrs [i].ctor->klass;
8725 if (mono_class_has_parent (klass, attr_klass) || (MONO_CLASS_IS_INTERFACE (attr_klass) && mono_class_is_assignable_from (attr_klass, klass)))
8732 mono_custom_attrs_get_attr (MonoCustomAttrInfo *ainfo, MonoClass *attr_klass)
8739 for (i = 0; i < ainfo->num_attrs; ++i) {
8740 klass = ainfo->attrs [i].ctor->klass;
8741 if (mono_class_has_parent (klass, attr_klass)) {
8746 if (attr_index == -1)
8749 attrs = mono_custom_attrs_construct (ainfo);
8751 return mono_array_get (attrs, MonoObject*, attr_index);
8757 * mono_reflection_get_custom_attrs_info:
8758 * @obj: a reflection object handle
8760 * Return the custom attribute info for attributes defined for the
8761 * reflection handle @obj. The objects.
8763 * FIXME this function leaks like a sieve for SRE objects.
8766 mono_reflection_get_custom_attrs_info (MonoObject *obj)
8769 MonoCustomAttrInfo *cinfo = NULL;
8771 klass = obj->vtable->klass;
8772 if (klass == mono_defaults.monotype_class) {
8773 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType *)obj);
8774 klass = mono_class_from_mono_type (type);
8775 cinfo = mono_custom_attrs_from_class (klass);
8776 } else if (strcmp ("Assembly", klass->name) == 0 || strcmp ("MonoAssembly", klass->name) == 0) {
8777 MonoReflectionAssembly *rassembly = (MonoReflectionAssembly*)obj;
8778 cinfo = mono_custom_attrs_from_assembly (rassembly->assembly);
8779 } else if (strcmp ("Module", klass->name) == 0 || strcmp ("MonoModule", klass->name) == 0) {
8780 MonoReflectionModule *module = (MonoReflectionModule*)obj;
8781 cinfo = mono_custom_attrs_from_module (module->image);
8782 } else if (strcmp ("MonoProperty", klass->name) == 0) {
8783 MonoReflectionProperty *rprop = (MonoReflectionProperty*)obj;
8784 cinfo = mono_custom_attrs_from_property (rprop->property->parent, rprop->property);
8785 } else if (strcmp ("MonoEvent", klass->name) == 0) {
8786 MonoReflectionMonoEvent *revent = (MonoReflectionMonoEvent*)obj;
8787 cinfo = mono_custom_attrs_from_event (revent->event->parent, revent->event);
8788 } else if (strcmp ("MonoField", klass->name) == 0) {
8789 MonoReflectionField *rfield = (MonoReflectionField*)obj;
8790 cinfo = mono_custom_attrs_from_field (rfield->field->parent, rfield->field);
8791 } else if ((strcmp ("MonoMethod", klass->name) == 0) || (strcmp ("MonoCMethod", klass->name) == 0)) {
8792 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8793 cinfo = mono_custom_attrs_from_method (rmethod->method);
8794 } else if ((strcmp ("MonoGenericMethod", klass->name) == 0) || (strcmp ("MonoGenericCMethod", klass->name) == 0)) {
8795 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)obj;
8796 cinfo = mono_custom_attrs_from_method (rmethod->method);
8797 } else if (strcmp ("ParameterInfo", klass->name) == 0) {
8798 MonoReflectionParameter *param = (MonoReflectionParameter*)obj;
8799 MonoClass *member_class = mono_object_class (param->MemberImpl);
8800 if (mono_class_is_reflection_method_or_constructor (member_class)) {
8801 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
8802 cinfo = mono_custom_attrs_from_param (rmethod->method, param->PositionImpl + 1);
8803 } else if (is_sr_mono_property (member_class)) {
8804 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
8806 if (!(method = prop->property->get))
8807 method = prop->property->set;
8810 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8812 #ifndef DISABLE_REFLECTION_EMIT
8813 else if (is_sre_method_on_tb_inst (member_class)) {/*XXX This is a workaround for Compiler Context*/
8814 MonoMethod *method = mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst*)param->MemberImpl);
8815 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8816 } else if (is_sre_ctor_on_tb_inst (member_class)) { /*XX This is a workaround for Compiler Context*/
8817 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)param->MemberImpl;
8818 MonoMethod *method = NULL;
8819 if (is_sre_ctor_builder (mono_object_class (c->cb)))
8820 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
8821 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
8822 method = ((MonoReflectionMethod *)c->cb)->method;
8824 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));
8826 cinfo = mono_custom_attrs_from_param (method, param->PositionImpl + 1);
8830 char *type_name = mono_type_get_full_name (member_class);
8831 char *msg = g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name);
8832 MonoException *ex = mono_get_exception_not_supported (msg);
8835 mono_raise_exception (ex);
8837 } else if (strcmp ("AssemblyBuilder", klass->name) == 0) {
8838 MonoReflectionAssemblyBuilder *assemblyb = (MonoReflectionAssemblyBuilder*)obj;
8839 cinfo = mono_custom_attrs_from_builders (NULL, assemblyb->assembly.assembly->image, assemblyb->cattrs);
8840 } else if (strcmp ("TypeBuilder", klass->name) == 0) {
8841 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
8842 cinfo = mono_custom_attrs_from_builders (NULL, &tb->module->dynamic_image->image, tb->cattrs);
8843 } else if (strcmp ("ModuleBuilder", klass->name) == 0) {
8844 MonoReflectionModuleBuilder *mb = (MonoReflectionModuleBuilder*)obj;
8845 cinfo = mono_custom_attrs_from_builders (NULL, &mb->dynamic_image->image, mb->cattrs);
8846 } else if (strcmp ("ConstructorBuilder", klass->name) == 0) {
8847 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
8848 cinfo = mono_custom_attrs_from_builders (NULL, cb->mhandle->klass->image, cb->cattrs);
8849 } else if (strcmp ("MethodBuilder", klass->name) == 0) {
8850 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
8851 cinfo = mono_custom_attrs_from_builders (NULL, mb->mhandle->klass->image, mb->cattrs);
8852 } else if (strcmp ("FieldBuilder", klass->name) == 0) {
8853 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
8854 cinfo = mono_custom_attrs_from_builders (NULL, &((MonoReflectionTypeBuilder*)fb->typeb)->module->dynamic_image->image, fb->cattrs);
8855 } else if (strcmp ("MonoGenericClass", klass->name) == 0) {
8856 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)obj;
8857 cinfo = mono_reflection_get_custom_attrs_info ((MonoObject*)gclass->generic_type);
8858 } else { /* handle other types here... */
8859 g_error ("get custom attrs not yet supported for %s", klass->name);
8866 * mono_reflection_get_custom_attrs_by_type:
8867 * @obj: a reflection object handle
8869 * Return an array with all the custom attributes defined of the
8870 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8871 * of that type are returned. The objects are fully build. Return NULL if a loading error
8875 mono_reflection_get_custom_attrs_by_type (MonoObject *obj, MonoClass *attr_klass)
8878 MonoCustomAttrInfo *cinfo;
8880 cinfo = mono_reflection_get_custom_attrs_info (obj);
8883 result = mono_custom_attrs_construct_by_type (cinfo, attr_klass);
8885 result = mono_custom_attrs_construct (cinfo);
8887 mono_custom_attrs_free (cinfo);
8889 if (mono_loader_get_last_error ())
8891 result = mono_array_new_cached (mono_domain_get (), mono_defaults.attribute_class, 0);
8898 * mono_reflection_get_custom_attrs:
8899 * @obj: a reflection object handle
8901 * Return an array with all the custom attributes defined of the
8902 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8906 mono_reflection_get_custom_attrs (MonoObject *obj)
8908 return mono_reflection_get_custom_attrs_by_type (obj, NULL);
8912 * mono_reflection_get_custom_attrs_data:
8913 * @obj: a reflection obj handle
8915 * Returns an array of System.Reflection.CustomAttributeData,
8916 * which include information about attributes reflected on
8917 * types loaded using the Reflection Only methods
8920 mono_reflection_get_custom_attrs_data (MonoObject *obj)
8923 MonoCustomAttrInfo *cinfo;
8925 cinfo = mono_reflection_get_custom_attrs_info (obj);
8927 result = mono_custom_attrs_data_construct (cinfo);
8929 mono_custom_attrs_free (cinfo);
8931 result = mono_array_new (mono_domain_get (), mono_defaults.customattribute_data_class, 0);
8936 static MonoReflectionType*
8937 mono_reflection_type_get_underlying_system_type (MonoReflectionType* t)
8939 static MonoMethod *method_get_underlying_system_type = NULL;
8940 MonoMethod *usertype_method;
8942 if (!method_get_underlying_system_type)
8943 method_get_underlying_system_type = mono_class_get_method_from_name (mono_defaults.systemtype_class, "get_UnderlyingSystemType", 0);
8944 usertype_method = mono_object_get_virtual_method ((MonoObject *) t, method_get_underlying_system_type);
8945 return (MonoReflectionType *) mono_runtime_invoke (usertype_method, t, NULL, NULL);
8950 is_corlib_type (MonoClass *class)
8952 return class->image == mono_defaults.corlib;
8955 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8956 static MonoClass *cached_class; \
8958 return cached_class == _class; \
8959 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8960 cached_class = _class; \
8967 #ifndef DISABLE_REFLECTION_EMIT
8969 is_sre_array (MonoClass *class)
8971 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8975 is_sre_byref (MonoClass *class)
8977 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8981 is_sre_pointer (MonoClass *class)
8983 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8987 is_sre_generic_instance (MonoClass *class)
8989 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8993 is_sre_type_builder (MonoClass *class)
8995 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8999 is_sre_method_builder (MonoClass *class)
9001 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
9005 is_sre_ctor_builder (MonoClass *class)
9007 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
9011 is_sre_field_builder (MonoClass *class)
9013 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
9017 is_sre_method_on_tb_inst (MonoClass *class)
9019 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
9023 is_sre_ctor_on_tb_inst (MonoClass *class)
9025 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
9029 mono_reflection_type_get_handle (MonoReflectionType* ref)
9037 if (is_usertype (ref)) {
9038 ref = mono_reflection_type_get_underlying_system_type (ref);
9039 if (ref == NULL || is_usertype (ref))
9045 class = mono_object_class (ref);
9047 if (is_sre_array (class)) {
9049 MonoReflectionArrayType *sre_array = (MonoReflectionArrayType*)ref;
9050 MonoType *base = mono_reflection_type_get_handle (sre_array->element_type);
9052 if (sre_array->rank == 0) //single dimentional array
9053 res = &mono_array_class_get (mono_class_from_mono_type (base), 1)->byval_arg;
9055 res = &mono_bounded_array_class_get (mono_class_from_mono_type (base), sre_array->rank, TRUE)->byval_arg;
9056 sre_array->type.type = res;
9058 } else if (is_sre_byref (class)) {
9060 MonoReflectionDerivedType *sre_byref = (MonoReflectionDerivedType*)ref;
9061 MonoType *base = mono_reflection_type_get_handle (sre_byref->element_type);
9063 res = &mono_class_from_mono_type (base)->this_arg;
9064 sre_byref->type.type = res;
9066 } else if (is_sre_pointer (class)) {
9068 MonoReflectionDerivedType *sre_pointer = (MonoReflectionDerivedType*)ref;
9069 MonoType *base = mono_reflection_type_get_handle (sre_pointer->element_type);
9071 res = &mono_ptr_class_get (base)->byval_arg;
9072 sre_pointer->type.type = res;
9074 } else if (is_sre_generic_instance (class)) {
9075 MonoType *res, **types;
9076 MonoReflectionGenericClass *gclass = (MonoReflectionGenericClass*)ref;
9079 count = mono_array_length (gclass->type_arguments);
9080 types = g_new0 (MonoType*, count);
9081 for (i = 0; i < count; ++i) {
9082 MonoReflectionType *t = mono_array_get (gclass->type_arguments, gpointer, i);
9083 types [i] = mono_reflection_type_get_handle (t);
9090 res = mono_reflection_bind_generic_parameters (gclass->generic_type, count, types);
9093 gclass->type.type = res;
9097 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref)->byval_arg));
9104 mono_reflection_create_unmanaged_type (MonoReflectionType *type)
9106 mono_reflection_type_get_handle (type);
9110 mono_reflection_register_with_runtime (MonoReflectionType *type)
9112 MonoType *res = mono_reflection_type_get_handle (type);
9113 MonoDomain *domain = mono_object_domain ((MonoObject*)type);
9117 mono_raise_exception (mono_get_exception_argument (NULL, "Invalid generic instantiation, one or more arguments are not proper user types"));
9119 class = mono_class_from_mono_type (res);
9121 mono_loader_lock (); /*same locking as mono_type_get_object*/
9122 mono_domain_lock (domain);
9124 if (!class->image->dynamic) {
9125 mono_class_setup_supertypes (class);
9127 if (!domain->type_hash)
9128 domain->type_hash = mono_g_hash_table_new_type ((GHashFunc)mymono_metadata_type_hash,
9129 (GCompareFunc)mymono_metadata_type_equal, MONO_HASH_VALUE_GC);
9130 mono_g_hash_table_insert (domain->type_hash, res, type);
9132 mono_domain_unlock (domain);
9133 mono_loader_unlock ();
9137 * LOCKING: Assumes the loader lock is held.
9139 static MonoMethodSignature*
9140 parameters_to_signature (MonoImage *image, MonoArray *parameters) {
9141 MonoMethodSignature *sig;
9144 count = parameters? mono_array_length (parameters): 0;
9146 sig = image_g_malloc0 (image, MONO_SIZEOF_METHOD_SIGNATURE + sizeof (MonoType*) * count);
9147 sig->param_count = count;
9148 sig->sentinelpos = -1; /* FIXME */
9149 for (i = 0; i < count; ++i)
9150 sig->params [i] = mono_type_array_get_and_resolve (parameters, i);
9155 * LOCKING: Assumes the loader lock is held.
9157 static MonoMethodSignature*
9158 ctor_builder_to_signature (MonoImage *image, MonoReflectionCtorBuilder *ctor) {
9159 MonoMethodSignature *sig;
9161 sig = parameters_to_signature (image, ctor->parameters);
9162 sig->hasthis = ctor->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9163 sig->ret = &mono_defaults.void_class->byval_arg;
9168 * LOCKING: Assumes the loader lock is held.
9170 static MonoMethodSignature*
9171 method_builder_to_signature (MonoImage *image, MonoReflectionMethodBuilder *method) {
9172 MonoMethodSignature *sig;
9174 sig = parameters_to_signature (image, method->parameters);
9175 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9176 sig->ret = method->rtype? mono_reflection_type_get_handle ((MonoReflectionType*)method->rtype): &mono_defaults.void_class->byval_arg;
9177 sig->generic_param_count = method->generic_params ? mono_array_length (method->generic_params) : 0;
9181 static MonoMethodSignature*
9182 dynamic_method_to_signature (MonoReflectionDynamicMethod *method) {
9183 MonoMethodSignature *sig;
9185 sig = parameters_to_signature (NULL, method->parameters);
9186 sig->hasthis = method->attrs & METHOD_ATTRIBUTE_STATIC? 0: 1;
9187 sig->ret = method->rtype? mono_reflection_type_get_handle (method->rtype): &mono_defaults.void_class->byval_arg;
9188 sig->generic_param_count = 0;
9193 get_prop_name_and_type (MonoObject *prop, char **name, MonoType **type)
9195 MonoClass *klass = mono_object_class (prop);
9196 if (strcmp (klass->name, "PropertyBuilder") == 0) {
9197 MonoReflectionPropertyBuilder *pb = (MonoReflectionPropertyBuilder *)prop;
9198 *name = mono_string_to_utf8 (pb->name);
9199 *type = mono_reflection_type_get_handle ((MonoReflectionType*)pb->type);
9201 MonoReflectionProperty *p = (MonoReflectionProperty *)prop;
9202 *name = g_strdup (p->property->name);
9203 if (p->property->get)
9204 *type = mono_method_signature (p->property->get)->ret;
9206 *type = mono_method_signature (p->property->set)->params [mono_method_signature (p->property->set)->param_count - 1];
9211 get_field_name_and_type (MonoObject *field, char **name, MonoType **type)
9213 MonoClass *klass = mono_object_class (field);
9214 if (strcmp (klass->name, "FieldBuilder") == 0) {
9215 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder *)field;
9216 *name = mono_string_to_utf8 (fb->name);
9217 *type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
9219 MonoReflectionField *f = (MonoReflectionField *)field;
9220 *name = g_strdup (mono_field_get_name (f->field));
9221 *type = f->field->type;
9225 #else /* DISABLE_REFLECTION_EMIT */
9228 mono_reflection_register_with_runtime (MonoReflectionType *type)
9234 is_sre_type_builder (MonoClass *class)
9240 is_sre_generic_instance (MonoClass *class)
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);
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);
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;
10175 if (klass->generic_container) {
10176 container->parent = klass->generic_container;
10177 container->context.class_inst = klass->generic_container->context.class_inst;
10179 container->context.method_inst = mono_get_shared_generic_inst (container);
10183 MonoMethodWrapper *mw = (MonoMethodWrapper*)m;
10187 m->wrapper_type = MONO_WRAPPER_DYNAMIC_METHOD;
10189 mw->method_data = data = image_g_new (image, gpointer, rmb->nrefs + 1);
10190 data [0] = GUINT_TO_POINTER (rmb->nrefs);
10191 for (i = 0; i < rmb->nrefs; ++i)
10192 data [i + 1] = rmb->refs [i];
10197 /* Parameter info */
10200 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10201 method_aux->param_names = image_g_new0 (image, char *, mono_method_signature (m)->param_count + 1);
10202 for (i = 0; i <= m->signature->param_count; ++i) {
10203 MonoReflectionParamBuilder *pb;
10204 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10205 if ((i > 0) && (pb->attrs)) {
10206 /* Make a copy since it might point to a shared type structure */
10207 m->signature->params [i - 1] = mono_metadata_type_dup (klass->image, m->signature->params [i - 1]);
10208 m->signature->params [i - 1]->attrs = pb->attrs;
10211 if (pb->attrs & PARAM_ATTRIBUTE_HAS_DEFAULT) {
10212 MonoDynamicImage *assembly;
10213 guint32 idx, def_type, len;
10217 if (!method_aux->param_defaults) {
10218 method_aux->param_defaults = image_g_new0 (image, guint8*, m->signature->param_count + 1);
10219 method_aux->param_default_types = image_g_new0 (image, guint32, m->signature->param_count + 1);
10221 assembly = (MonoDynamicImage*)klass->image;
10222 idx = encode_constant (assembly, pb->def_value, &def_type);
10223 /* Copy the data from the blob since it might get realloc-ed */
10224 p = assembly->blob.data + idx;
10225 len = mono_metadata_decode_blob_size (p, &p2);
10227 method_aux->param_defaults [i] = image_g_malloc (image, len);
10228 method_aux->param_default_types [i] = def_type;
10229 memcpy ((gpointer)method_aux->param_defaults [i], p, len);
10233 method_aux->param_names [i] = mono_string_to_utf8_image (image, pb->name, &error);
10234 g_assert (mono_error_ok (&error));
10237 if (!method_aux->param_cattr)
10238 method_aux->param_cattr = image_g_new0 (image, MonoCustomAttrInfo*, m->signature->param_count + 1);
10239 method_aux->param_cattr [i] = mono_custom_attrs_from_builders (image, klass->image, pb->cattrs);
10245 /* Parameter marshalling */
10248 for (i = 0; i < mono_array_length (rmb->pinfo); ++i) {
10249 MonoReflectionParamBuilder *pb;
10250 if ((pb = mono_array_get (rmb->pinfo, MonoReflectionParamBuilder*, i))) {
10251 if (pb->marshal_info) {
10253 specs = image_g_new0 (image, MonoMarshalSpec*, sig->param_count + 1);
10254 specs [pb->position] =
10255 mono_marshal_spec_from_builder (image, klass->image->assembly, pb->marshal_info);
10259 if (specs != NULL) {
10261 method_aux = image_g_new0 (image, MonoReflectionMethodAux, 1);
10262 method_aux->param_marshall = specs;
10265 if (klass->image->dynamic && method_aux)
10266 g_hash_table_insert (((MonoDynamicImage*)klass->image)->method_aux_hash, m, method_aux);
10268 mono_loader_unlock ();
10274 ctorbuilder_to_mono_method (MonoClass *klass, MonoReflectionCtorBuilder* mb)
10276 ReflectionMethodBuilder rmb;
10277 MonoMethodSignature *sig;
10279 mono_loader_lock ();
10280 sig = ctor_builder_to_signature (klass->image, mb);
10281 mono_loader_unlock ();
10283 reflection_methodbuilder_from_ctor_builder (&rmb, mb);
10285 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10286 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10288 /* If we are in a generic class, we might be called multiple times from inflate_method */
10289 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10290 /* ilgen is no longer needed */
10294 return mb->mhandle;
10298 methodbuilder_to_mono_method (MonoClass *klass, MonoReflectionMethodBuilder* mb)
10300 ReflectionMethodBuilder rmb;
10301 MonoMethodSignature *sig;
10303 mono_loader_lock ();
10304 sig = method_builder_to_signature (klass->image, mb);
10305 mono_loader_unlock ();
10307 reflection_methodbuilder_from_method_builder (&rmb, mb);
10309 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
10310 mono_save_custom_attrs (klass->image, mb->mhandle, mb->cattrs);
10312 /* If we are in a generic class, we might be called multiple times from inflate_method */
10313 if (!((MonoDynamicImage*)(MonoDynamicImage*)klass->image)->save && !klass->generic_container) {
10314 /* ilgen is no longer needed */
10317 return mb->mhandle;
10320 static MonoClassField*
10321 fieldbuilder_to_mono_class_field (MonoClass *klass, MonoReflectionFieldBuilder* fb)
10323 MonoClassField *field;
10326 field = g_new0 (MonoClassField, 1);
10328 field->name = mono_string_to_utf8 (fb->name);
10329 if (fb->attrs || fb->modreq || fb->modopt) {
10330 field->type = mono_metadata_type_dup (NULL, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10331 field->type->attrs = fb->attrs;
10333 g_assert (klass->image->dynamic);
10334 custom = add_custom_modifiers ((MonoDynamicImage*)klass->image, field->type, fb->modreq, fb->modopt);
10335 g_free (field->type);
10336 field->type = custom;
10338 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10340 if (fb->offset != -1)
10341 field->offset = fb->offset;
10342 field->parent = klass;
10343 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10345 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10352 mono_reflection_bind_generic_parameters (MonoReflectionType *type, int type_argc, MonoType **types)
10355 MonoReflectionTypeBuilder *tb = NULL;
10356 gboolean is_dynamic = FALSE;
10357 MonoDomain *domain;
10358 MonoClass *geninst;
10360 mono_loader_lock ();
10362 domain = mono_object_domain (type);
10364 if (is_sre_type_builder (mono_object_class (type))) {
10365 tb = (MonoReflectionTypeBuilder *) type;
10368 } else if (is_sre_generic_instance (mono_object_class (type))) {
10369 MonoReflectionGenericClass *rgi = (MonoReflectionGenericClass *) type;
10370 MonoReflectionType *gtd = rgi->generic_type;
10372 if (is_sre_type_builder (mono_object_class (gtd))) {
10373 tb = (MonoReflectionTypeBuilder *)gtd;
10378 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10379 if (tb && tb->generic_container)
10380 mono_reflection_create_generic_class (tb);
10382 klass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10383 if (!klass->generic_container) {
10384 mono_loader_unlock ();
10388 if (klass->wastypebuilder) {
10389 tb = (MonoReflectionTypeBuilder *) mono_class_get_ref_info (klass);
10394 mono_loader_unlock ();
10396 geninst = mono_class_bind_generic_parameters (klass, type_argc, types, is_dynamic);
10398 return &geninst->byval_arg;
10402 mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, gboolean is_dynamic)
10404 MonoGenericClass *gclass;
10405 MonoGenericInst *inst;
10407 g_assert (klass->generic_container);
10409 inst = mono_metadata_get_generic_inst (type_argc, types);
10410 gclass = mono_metadata_lookup_generic_class (klass, inst, is_dynamic);
10412 return mono_generic_class_get_class (gclass);
10415 MonoReflectionMethod*
10416 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod *rmethod, MonoArray *types)
10419 MonoMethod *method, *inflated;
10420 MonoMethodInflated *imethod;
10421 MonoGenericContext tmp_context;
10422 MonoGenericInst *ginst;
10423 MonoType **type_argv;
10426 MONO_ARCH_SAVE_REGS;
10428 /*FIXME but this no longer should happen*/
10429 if (!strcmp (rmethod->object.vtable->klass->name, "MethodBuilder")) {
10430 #ifndef DISABLE_REFLECTION_EMIT
10431 MonoReflectionMethodBuilder *mb = NULL;
10432 MonoReflectionTypeBuilder *tb;
10435 mb = (MonoReflectionMethodBuilder *) rmethod;
10436 tb = (MonoReflectionTypeBuilder *) mb->type;
10437 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10439 method = methodbuilder_to_mono_method (klass, mb);
10441 g_assert_not_reached ();
10445 method = rmethod->method;
10448 klass = method->klass;
10450 if (method->is_inflated)
10451 method = ((MonoMethodInflated *) method)->declaring;
10453 count = mono_method_signature (method)->generic_param_count;
10454 if (count != mono_array_length (types))
10457 type_argv = g_new0 (MonoType *, count);
10458 for (i = 0; i < count; i++) {
10459 MonoReflectionType *garg = mono_array_get (types, gpointer, i);
10460 type_argv [i] = mono_reflection_type_get_handle (garg);
10462 ginst = mono_metadata_get_generic_inst (count, type_argv);
10463 g_free (type_argv);
10465 tmp_context.class_inst = klass->generic_class ? klass->generic_class->context.class_inst : NULL;
10466 tmp_context.method_inst = ginst;
10468 inflated = mono_class_inflate_generic_method (method, &tmp_context);
10469 imethod = (MonoMethodInflated *) inflated;
10471 /*FIXME but I think this is no longer necessary*/
10472 if (method->klass->image->dynamic) {
10473 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10475 * This table maps metadata structures representing inflated methods/fields
10476 * to the reflection objects representing their generic definitions.
10478 mono_loader_lock ();
10479 mono_g_hash_table_insert (image->generic_def_objects, imethod, rmethod);
10480 mono_loader_unlock ();
10483 return mono_method_get_object (mono_object_domain (rmethod), inflated, NULL);
10486 #ifndef DISABLE_REFLECTION_EMIT
10488 static MonoMethod *
10489 inflate_mono_method (MonoClass *klass, MonoMethod *method, MonoObject *obj)
10491 MonoMethodInflated *imethod;
10492 MonoGenericContext *context;
10496 * With generic code sharing the klass might not be inflated.
10497 * This can happen because classes inflated with their own
10498 * type arguments are "normalized" to the uninflated class.
10500 if (!klass->generic_class)
10503 context = mono_class_get_context (klass);
10505 if (klass->method.count) {
10506 /* Find the already created inflated method */
10507 for (i = 0; i < klass->method.count; ++i) {
10508 g_assert (klass->methods [i]->is_inflated);
10509 if (((MonoMethodInflated*)klass->methods [i])->declaring == method)
10512 g_assert (i < klass->method.count);
10513 imethod = (MonoMethodInflated*)klass->methods [i];
10515 imethod = (MonoMethodInflated *) mono_class_inflate_generic_method_full (method, klass, context);
10518 if (method->is_generic && method->klass->image->dynamic) {
10519 MonoDynamicImage *image = (MonoDynamicImage*)method->klass->image;
10521 mono_loader_lock ();
10522 mono_g_hash_table_insert (image->generic_def_objects, imethod, obj);
10523 mono_loader_unlock ();
10525 return (MonoMethod *) imethod;
10528 static MonoMethod *
10529 inflate_method (MonoReflectionType *type, MonoObject *obj)
10531 MonoMethod *method;
10534 MonoClass *type_class = mono_object_class (type);
10536 if (is_sre_generic_instance (type_class)) {
10537 MonoReflectionGenericClass *mgc = (MonoReflectionGenericClass*)type;
10538 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mgc->generic_type));
10539 } else if (is_sre_type_builder (type_class)) {
10540 gklass = mono_class_from_mono_type (mono_reflection_type_get_handle (type));
10541 } else if (type->type) {
10542 gklass = mono_class_from_mono_type (type->type);
10543 gklass = mono_class_get_generic_type_definition (gklass);
10545 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type)));
10548 if (!strcmp (obj->vtable->klass->name, "MethodBuilder"))
10549 if (((MonoReflectionMethodBuilder*)obj)->mhandle)
10550 method = ((MonoReflectionMethodBuilder*)obj)->mhandle;
10552 method = methodbuilder_to_mono_method (gklass, (MonoReflectionMethodBuilder *) obj);
10553 else if (!strcmp (obj->vtable->klass->name, "ConstructorBuilder"))
10554 method = ctorbuilder_to_mono_method (gklass, (MonoReflectionCtorBuilder *) obj);
10555 else if (!strcmp (obj->vtable->klass->name, "MonoMethod") || !strcmp (obj->vtable->klass->name, "MonoCMethod"))
10556 method = ((MonoReflectionMethod *) obj)->method;
10558 method = NULL; /* prevent compiler warning */
10559 g_error ("can't handle type %s", obj->vtable->klass->name);
10562 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)type)), method, obj);
10565 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10567 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
10568 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
10571 MonoGenericClass *gclass;
10572 MonoDynamicGenericClass *dgclass;
10573 MonoClass *klass, *gklass;
10577 MONO_ARCH_SAVE_REGS;
10579 gtype = mono_reflection_type_get_handle ((MonoReflectionType*)type);
10580 klass = mono_class_from_mono_type (gtype);
10581 g_assert (gtype->type == MONO_TYPE_GENERICINST);
10582 gclass = gtype->data.generic_class;
10584 if (!gclass->is_dynamic)
10587 dgclass = (MonoDynamicGenericClass *) gclass;
10589 if (dgclass->initialized)
10592 gklass = gclass->container_class;
10593 mono_class_init (gklass);
10595 dgclass->count_methods = methods ? mono_array_length (methods) : 0;
10596 dgclass->count_ctors = ctors ? mono_array_length (ctors) : 0;
10597 dgclass->count_fields = fields ? mono_array_length (fields) : 0;
10599 dgclass->methods = g_new0 (MonoMethod *, dgclass->count_methods);
10600 dgclass->ctors = g_new0 (MonoMethod *, dgclass->count_ctors);
10601 dgclass->fields = g_new0 (MonoClassField, dgclass->count_fields);
10602 dgclass->field_objects = g_new0 (MonoObject*, dgclass->count_fields);
10603 dgclass->field_generic_types = g_new0 (MonoType*, dgclass->count_fields);
10605 for (i = 0; i < dgclass->count_methods; i++) {
10606 MonoObject *obj = mono_array_get (methods, gpointer, i);
10608 dgclass->methods [i] = inflate_method ((MonoReflectionType*)type, obj);
10611 for (i = 0; i < dgclass->count_ctors; i++) {
10612 MonoObject *obj = mono_array_get (ctors, gpointer, i);
10614 dgclass->ctors [i] = inflate_method ((MonoReflectionType*)type, obj);
10617 for (i = 0; i < dgclass->count_fields; i++) {
10618 MonoObject *obj = mono_array_get (fields, gpointer, i);
10619 MonoClassField *field, *inflated_field = NULL;
10621 if (!strcmp (obj->vtable->klass->name, "FieldBuilder"))
10622 inflated_field = field = fieldbuilder_to_mono_class_field (klass, (MonoReflectionFieldBuilder *) obj);
10623 else if (!strcmp (obj->vtable->klass->name, "MonoField"))
10624 field = ((MonoReflectionField *) obj)->field;
10626 field = NULL; /* prevent compiler warning */
10627 g_assert_not_reached ();
10630 dgclass->fields [i] = *field;
10631 dgclass->fields [i].parent = klass;
10632 dgclass->fields [i].type = mono_class_inflate_generic_type (
10633 field->type, mono_generic_class_get_context ((MonoGenericClass *) dgclass));
10634 dgclass->field_generic_types [i] = field->type;
10635 MOVING_GC_REGISTER (&dgclass->field_objects [i]);
10636 dgclass->field_objects [i] = obj;
10638 if (inflated_field) {
10639 g_free (inflated_field);
10641 dgclass->fields [i].name = g_strdup (dgclass->fields [i].name);
10645 dgclass->initialized = TRUE;
10649 fix_partial_generic_class (MonoClass *klass)
10651 MonoClass *gklass = klass->generic_class->container_class;
10652 MonoDynamicGenericClass *dgclass;
10655 if (klass->wastypebuilder)
10658 dgclass = (MonoDynamicGenericClass *) klass->generic_class;
10660 if (!dgclass->initialized)
10663 if (klass->method.count != gklass->method.count) {
10664 klass->method.count = gklass->method.count;
10665 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * (klass->method.count + 1));
10667 for (i = 0; i < klass->method.count; i++) {
10668 klass->methods [i] = mono_class_inflate_generic_method_full (
10669 gklass->methods [i], klass, mono_class_get_context (klass));
10673 if (klass->interface_count && klass->interface_count != gklass->interface_count) {
10674 klass->interface_count = gklass->interface_count;
10675 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * gklass->interface_count);
10676 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10678 for (i = 0; i < gklass->interface_count; ++i) {
10679 MonoType *iface_type = mono_class_inflate_generic_type (&gklass->interfaces [i]->byval_arg, mono_class_get_context (klass));
10680 klass->interfaces [i] = mono_class_from_mono_type (iface_type);
10681 mono_metadata_free_type (iface_type);
10683 ensure_runtime_vtable (klass->interfaces [i]);
10685 klass->interfaces_inited = 1;
10688 if (klass->field.count != gklass->field.count) {
10689 klass->field.count = gklass->field.count;
10690 klass->fields = image_g_new0 (klass->image, MonoClassField, klass->field.count);
10692 for (i = 0; i < klass->field.count; i++) {
10693 klass->fields [i] = gklass->fields [i];
10694 klass->fields [i].parent = klass;
10695 klass->fields [i].type = mono_class_inflate_generic_type (gklass->fields [i].type, mono_class_get_context (klass));
10699 /*We can only finish with this klass once it's parent has as well*/
10700 if (gklass->wastypebuilder)
10701 klass->wastypebuilder = TRUE;
10706 ensure_generic_class_runtime_vtable (MonoClass *klass)
10708 MonoClass *gklass = klass->generic_class->container_class;
10710 ensure_runtime_vtable (gklass);
10712 fix_partial_generic_class (klass);
10716 ensure_runtime_vtable (MonoClass *klass)
10718 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10721 if (!klass->image->dynamic || (!tb && !klass->generic_class) || klass->wastypebuilder)
10724 ensure_runtime_vtable (klass->parent);
10727 num = tb->ctors? mono_array_length (tb->ctors): 0;
10728 num += tb->num_methods;
10729 klass->method.count = num;
10730 klass->methods = mono_image_alloc (klass->image, sizeof (MonoMethod*) * num);
10731 num = tb->ctors? mono_array_length (tb->ctors): 0;
10732 for (i = 0; i < num; ++i)
10733 klass->methods [i] = ctorbuilder_to_mono_method (klass, mono_array_get (tb->ctors, MonoReflectionCtorBuilder*, i));
10734 num = tb->num_methods;
10736 for (i = 0; i < num; ++i)
10737 klass->methods [j++] = methodbuilder_to_mono_method (klass, mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i));
10739 if (tb->interfaces) {
10740 klass->interface_count = mono_array_length (tb->interfaces);
10741 klass->interfaces = mono_image_alloc (klass->image, sizeof (MonoClass*) * klass->interface_count);
10742 for (i = 0; i < klass->interface_count; ++i) {
10743 MonoType *iface = mono_type_array_get_and_resolve (tb->interfaces, i);
10744 klass->interfaces [i] = mono_class_from_mono_type (iface);
10745 ensure_runtime_vtable (klass->interfaces [i]);
10747 klass->interfaces_inited = 1;
10749 } else if (klass->generic_class){
10750 ensure_generic_class_runtime_vtable (klass);
10753 if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
10754 for (i = 0; i < klass->method.count; ++i)
10755 klass->methods [i]->slot = i;
10757 klass->interfaces_packed = NULL; /*make setup_interface_offsets happy*/
10758 mono_class_setup_interface_offsets (klass);
10759 mono_class_setup_interface_id (klass);
10763 * The generic vtable is needed even if image->run is not set since some
10764 * runtime code like ves_icall_Type_GetMethodsByName depends on
10765 * method->slot being defined.
10769 * tb->methods could not be freed since it is used for determining
10770 * overrides during dynamic vtable construction.
10775 mono_reflection_method_get_handle (MonoObject *method)
10777 MonoClass *class = mono_object_class (method);
10778 if (is_sr_mono_method (class)) {
10779 MonoReflectionMethod *sr_method = (MonoReflectionMethod*)method;
10780 return sr_method->method;
10782 if (is_sre_method_builder (class)) {
10783 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)method;
10784 return mb->mhandle;
10786 if (is_sre_method_on_tb_inst (class)) {
10787 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)method;
10788 MonoMethod *result;
10789 /*FIXME move this to a proper method and unify with resolve_object*/
10790 if (m->method_args) {
10791 result = mono_reflection_method_on_tb_inst_get_handle (m);
10793 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)m->inst);
10794 MonoClass *inflated_klass = mono_class_from_mono_type (type);
10795 MonoMethod *mono_method;
10797 if (is_sre_method_builder (mono_object_class (m->mb)))
10798 mono_method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
10799 else if (is_sr_mono_method (mono_object_class (m->mb)))
10800 mono_method = ((MonoReflectionMethod *)m->mb)->method;
10802 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)));
10804 result = inflate_mono_method (inflated_klass, mono_method, (MonoObject*)m->mb);
10809 g_error ("Can't handle methods of type %s:%s", class->name_space, class->name);
10814 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
10816 MonoReflectionTypeBuilder *tb;
10820 *num_overrides = 0;
10822 g_assert (klass->image->dynamic);
10824 if (!mono_class_get_ref_info (klass))
10827 g_assert (strcmp (((MonoObject*)mono_class_get_ref_info (klass))->vtable->klass->name, "TypeBuilder") == 0);
10829 tb = (MonoReflectionTypeBuilder*)mono_class_get_ref_info (klass);
10833 for (i = 0; i < tb->num_methods; ++i) {
10834 MonoReflectionMethodBuilder *mb =
10835 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10836 if (mb->override_method)
10842 *overrides = g_new0 (MonoMethod*, onum * 2);
10845 for (i = 0; i < tb->num_methods; ++i) {
10846 MonoReflectionMethodBuilder *mb =
10847 mono_array_get (tb->methods, MonoReflectionMethodBuilder*, i);
10848 if (mb->override_method) {
10849 (*overrides) [onum * 2] = mono_reflection_method_get_handle ((MonoObject *)mb->override_method);
10850 (*overrides) [onum * 2 + 1] = mb->mhandle;
10852 g_assert (mb->mhandle);
10859 *num_overrides = onum;
10863 typebuilder_setup_fields (MonoClass *klass, MonoError *error)
10865 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10866 MonoReflectionFieldBuilder *fb;
10867 MonoClassField *field;
10868 MonoImage *image = klass->image;
10869 const char *p, *p2;
10871 guint32 len, idx, real_size = 0;
10873 klass->field.count = tb->num_fields;
10874 klass->field.first = 0;
10876 mono_error_init (error);
10878 if (tb->class_size) {
10879 g_assert ((tb->packing_size & 0xfffffff0) == 0);
10880 klass->packing_size = tb->packing_size;
10881 real_size = klass->instance_size + tb->class_size;
10884 if (!klass->field.count) {
10885 klass->instance_size = MAX (klass->instance_size, real_size);
10889 klass->fields = image_g_new0 (image, MonoClassField, klass->field.count);
10890 mono_class_alloc_ext (klass);
10891 klass->ext->field_def_values = image_g_new0 (image, MonoFieldDefaultValue, klass->field.count);
10893 This is, guess what, a hack.
10894 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10895 On the static path no field class is resolved, only types are built. This is the right thing to do
10897 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10899 klass->size_inited = 1;
10901 for (i = 0; i < klass->field.count; ++i) {
10902 fb = mono_array_get (tb->fields, gpointer, i);
10903 field = &klass->fields [i];
10904 field->name = mono_string_to_utf8_image (image, fb->name, error);
10905 if (!mono_error_ok (error))
10908 field->type = mono_metadata_type_dup (klass->image, mono_reflection_type_get_handle ((MonoReflectionType*)fb->type));
10909 field->type->attrs = fb->attrs;
10911 field->type = mono_reflection_type_get_handle ((MonoReflectionType*)fb->type);
10913 if ((fb->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) && fb->rva_data)
10914 klass->ext->field_def_values [i].data = mono_array_addr (fb->rva_data, char, 0);
10915 if (fb->offset != -1)
10916 field->offset = fb->offset;
10917 field->parent = klass;
10918 fb->handle = field;
10919 mono_save_custom_attrs (klass->image, field, fb->cattrs);
10921 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10922 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
10924 if (fb->def_value) {
10925 MonoDynamicImage *assembly = (MonoDynamicImage*)klass->image;
10926 field->type->attrs |= FIELD_ATTRIBUTE_HAS_DEFAULT;
10927 idx = encode_constant (assembly, fb->def_value, &klass->ext->field_def_values [i].def_type);
10928 /* Copy the data from the blob since it might get realloc-ed */
10929 p = assembly->blob.data + idx;
10930 len = mono_metadata_decode_blob_size (p, &p2);
10932 klass->ext->field_def_values [i].data = mono_image_alloc (image, len);
10933 memcpy ((gpointer)klass->ext->field_def_values [i].data, p, len);
10937 klass->instance_size = MAX (klass->instance_size, real_size);
10938 mono_class_layout_fields (klass);
10942 typebuilder_setup_properties (MonoClass *klass, MonoError *error)
10944 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
10945 MonoReflectionPropertyBuilder *pb;
10946 MonoImage *image = klass->image;
10947 MonoProperty *properties;
10950 mono_error_init (error);
10953 klass->ext = image_g_new0 (image, MonoClassExt, 1);
10955 klass->ext->property.count = tb->properties ? mono_array_length (tb->properties) : 0;
10956 klass->ext->property.first = 0;
10958 properties = image_g_new0 (image, MonoProperty, klass->ext->property.count);
10959 klass->ext->properties = properties;
10960 for (i = 0; i < klass->ext->property.count; ++i) {
10961 pb = mono_array_get (tb->properties, MonoReflectionPropertyBuilder*, i);
10962 properties [i].parent = klass;
10963 properties [i].attrs = pb->attrs;
10964 properties [i].name = mono_string_to_utf8_image (image, pb->name, error);
10965 if (!mono_error_ok (error))
10967 if (pb->get_method)
10968 properties [i].get = pb->get_method->mhandle;
10969 if (pb->set_method)
10970 properties [i].set = pb->set_method->mhandle;
10972 mono_save_custom_attrs (klass->image, &properties [i], pb->cattrs);
10976 MonoReflectionEvent *
10977 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
10979 MonoEvent *event = g_new0 (MonoEvent, 1);
10982 klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
10984 event->parent = klass;
10985 event->attrs = eb->attrs;
10986 event->name = mono_string_to_utf8 (eb->name);
10987 if (eb->add_method)
10988 event->add = eb->add_method->mhandle;
10989 if (eb->remove_method)
10990 event->remove = eb->remove_method->mhandle;
10991 if (eb->raise_method)
10992 event->raise = eb->raise_method->mhandle;
10994 #ifndef MONO_SMALL_CONFIG
10995 if (eb->other_methods) {
10997 event->other = g_new0 (MonoMethod*, mono_array_length (eb->other_methods) + 1);
10998 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
10999 MonoReflectionMethodBuilder *mb =
11000 mono_array_get (eb->other_methods,
11001 MonoReflectionMethodBuilder*, j);
11002 event->other [j] = mb->mhandle;
11007 return mono_event_get_object (mono_object_domain (tb), klass, event);
11011 typebuilder_setup_events (MonoClass *klass, MonoError *error)
11013 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11014 MonoReflectionEventBuilder *eb;
11015 MonoImage *image = klass->image;
11019 mono_error_init (error);
11022 klass->ext = image_g_new0 (image, MonoClassExt, 1);
11024 klass->ext->event.count = tb->events ? mono_array_length (tb->events) : 0;
11025 klass->ext->event.first = 0;
11027 events = image_g_new0 (image, MonoEvent, klass->ext->event.count);
11028 klass->ext->events = events;
11029 for (i = 0; i < klass->ext->event.count; ++i) {
11030 eb = mono_array_get (tb->events, MonoReflectionEventBuilder*, i);
11031 events [i].parent = klass;
11032 events [i].attrs = eb->attrs;
11033 events [i].name = mono_string_to_utf8_image (image, eb->name, error);
11034 if (!mono_error_ok (error))
11036 if (eb->add_method)
11037 events [i].add = eb->add_method->mhandle;
11038 if (eb->remove_method)
11039 events [i].remove = eb->remove_method->mhandle;
11040 if (eb->raise_method)
11041 events [i].raise = eb->raise_method->mhandle;
11043 #ifndef MONO_SMALL_CONFIG
11044 if (eb->other_methods) {
11046 events [i].other = image_g_new0 (image, MonoMethod*, mono_array_length (eb->other_methods) + 1);
11047 for (j = 0; j < mono_array_length (eb->other_methods); ++j) {
11048 MonoReflectionMethodBuilder *mb =
11049 mono_array_get (eb->other_methods,
11050 MonoReflectionMethodBuilder*, j);
11051 events [i].other [j] = mb->mhandle;
11055 mono_save_custom_attrs (klass->image, &events [i], eb->cattrs);
11060 remove_instantiations_of_and_ensure_contents (gpointer key,
11062 gpointer user_data)
11064 MonoType *type = (MonoType*)key;
11065 MonoClass *klass = (MonoClass*)user_data;
11067 if ((type->type == MONO_TYPE_GENERICINST) && (type->data.generic_class->container_class == klass)) {
11068 fix_partial_generic_class (mono_class_from_mono_type (type)); //Ensure it's safe to use it.
11075 check_array_for_usertypes (MonoArray *arr)
11082 for (i = 0; i < mono_array_length (arr); ++i)
11083 RESOLVE_ARRAY_TYPE_ELEMENT (arr, i);
11086 MonoReflectionType*
11087 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11091 MonoDomain* domain;
11092 MonoReflectionType* res;
11095 MONO_ARCH_SAVE_REGS;
11097 domain = mono_object_domain (tb);
11098 klass = mono_class_from_mono_type (tb->type.type);
11101 * Check for user defined Type subclasses.
11103 RESOLVE_TYPE (tb->parent);
11104 check_array_for_usertypes (tb->interfaces);
11106 for (i = 0; i < mono_array_length (tb->fields); ++i) {
11107 MonoReflectionFieldBuilder *fb = mono_array_get (tb->fields, gpointer, i);
11109 RESOLVE_TYPE (fb->type);
11110 check_array_for_usertypes (fb->modreq);
11111 check_array_for_usertypes (fb->modopt);
11112 if (fb->marshal_info && fb->marshal_info->marshaltyperef)
11113 RESOLVE_TYPE (fb->marshal_info->marshaltyperef);
11118 for (i = 0; i < mono_array_length (tb->methods); ++i) {
11119 MonoReflectionMethodBuilder *mb = mono_array_get (tb->methods, gpointer, i);
11121 RESOLVE_TYPE (mb->rtype);
11122 check_array_for_usertypes (mb->return_modreq);
11123 check_array_for_usertypes (mb->return_modopt);
11124 check_array_for_usertypes (mb->parameters);
11125 if (mb->param_modreq)
11126 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11127 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11128 if (mb->param_modopt)
11129 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11130 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11135 for (i = 0; i < mono_array_length (tb->ctors); ++i) {
11136 MonoReflectionCtorBuilder *mb = mono_array_get (tb->ctors, gpointer, i);
11138 check_array_for_usertypes (mb->parameters);
11139 if (mb->param_modreq)
11140 for (j = 0; j < mono_array_length (mb->param_modreq); ++j)
11141 check_array_for_usertypes (mono_array_get (mb->param_modreq, MonoArray*, j));
11142 if (mb->param_modopt)
11143 for (j = 0; j < mono_array_length (mb->param_modopt); ++j)
11144 check_array_for_usertypes (mono_array_get (mb->param_modopt, MonoArray*, j));
11149 mono_save_custom_attrs (klass->image, klass, tb->cattrs);
11152 * we need to lock the domain because the lock will be taken inside
11153 * So, we need to keep the locking order correct.
11155 mono_loader_lock ();
11156 mono_domain_lock (domain);
11157 if (klass->wastypebuilder) {
11158 mono_domain_unlock (domain);
11159 mono_loader_unlock ();
11160 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11163 * Fields to set in klass:
11164 * the various flags: delegate/unicode/contextbound etc.
11166 klass->flags = tb->attrs;
11167 klass->has_cctor = 1;
11168 klass->has_finalize = 1;
11170 /* fool mono_class_setup_parent */
11171 klass->supertypes = NULL;
11172 mono_class_setup_parent (klass, klass->parent);
11173 mono_class_setup_mono_type (klass);
11176 if (!((MonoDynamicImage*)klass->image)->run) {
11177 if (klass->generic_container) {
11178 /* FIXME: The code below can't handle generic classes */
11179 klass->wastypebuilder = TRUE;
11180 mono_loader_unlock ();
11181 mono_domain_unlock (domain);
11182 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11187 /* enums are done right away */
11188 if (!klass->enumtype)
11189 ensure_runtime_vtable (klass);
11191 if (tb->subtypes) {
11192 for (i = 0; i < mono_array_length (tb->subtypes); ++i) {
11193 MonoReflectionTypeBuilder *subtb = mono_array_get (tb->subtypes, MonoReflectionTypeBuilder*, i);
11194 mono_class_alloc_ext (klass);
11195 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)));
11199 klass->nested_classes_inited = TRUE;
11201 /* fields and object layout */
11202 if (klass->parent) {
11203 if (!klass->parent->size_inited)
11204 mono_class_init (klass->parent);
11205 klass->instance_size = klass->parent->instance_size;
11206 klass->sizes.class_size = 0;
11207 klass->min_align = klass->parent->min_align;
11208 /* if the type has no fields we won't call the field_setup
11209 * routine which sets up klass->has_references.
11211 klass->has_references |= klass->parent->has_references;
11213 klass->instance_size = sizeof (MonoObject);
11214 klass->min_align = 1;
11217 /* FIXME: handle packing_size and instance_size */
11218 typebuilder_setup_fields (klass, &error);
11219 if (!mono_error_ok (&error))
11221 typebuilder_setup_properties (klass, &error);
11222 if (!mono_error_ok (&error))
11225 typebuilder_setup_events (klass, &error);
11226 if (!mono_error_ok (&error))
11229 klass->wastypebuilder = TRUE;
11232 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11233 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11234 * we want to return normal System.MonoType objects, so clear these out from the cache.
11236 * Together with this we must ensure the contents of all instances to match the created type.
11238 if (domain->type_hash && klass->generic_container)
11239 mono_g_hash_table_foreach_remove (domain->type_hash, remove_instantiations_of_and_ensure_contents, klass);
11241 mono_domain_unlock (domain);
11242 mono_loader_unlock ();
11244 if (klass->enumtype && !mono_class_is_valid_enum (klass)) {
11245 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11246 mono_raise_exception (mono_get_exception_type_load (tb->name, NULL));
11249 res = mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
11250 g_assert (res != (MonoReflectionType*)tb);
11255 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
11256 klass->wastypebuilder = TRUE;
11257 mono_domain_unlock (domain);
11258 mono_loader_unlock ();
11259 mono_error_raise_exception (&error);
11264 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11266 MonoGenericParamFull *param;
11270 MONO_ARCH_SAVE_REGS;
11272 param = g_new0 (MonoGenericParamFull, 1);
11274 if (gparam->mbuilder) {
11275 if (!gparam->mbuilder->generic_container) {
11276 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)gparam->mbuilder->type;
11277 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)tb));
11278 gparam->mbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11279 gparam->mbuilder->generic_container->is_method = TRUE;
11281 * Cannot set owner.method, since the MonoMethod is not created yet.
11282 * Set the image field instead, so type_in_image () works.
11284 gparam->mbuilder->generic_container->image = klass->image;
11286 param->param.owner = gparam->mbuilder->generic_container;
11287 } else if (gparam->tbuilder) {
11288 if (!gparam->tbuilder->generic_container) {
11289 MonoClass *klass = mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)gparam->tbuilder));
11290 gparam->tbuilder->generic_container = mono_image_alloc0 (klass->image, sizeof (MonoGenericContainer));
11291 gparam->tbuilder->generic_container->owner.klass = klass;
11293 param->param.owner = gparam->tbuilder->generic_container;
11296 param->info.name = mono_string_to_utf8 (gparam->name);
11297 param->param.num = gparam->index;
11299 image = &gparam->tbuilder->module->dynamic_image->image;
11300 pklass = mono_class_from_generic_parameter ((MonoGenericParam *) param, image, gparam->mbuilder != NULL);
11302 gparam->type.type = &pklass->byval_arg;
11304 mono_class_set_ref_info (pklass, gparam);
11305 mono_image_lock (image);
11306 image->reflection_info_unregister_classes = g_slist_prepend (image->reflection_info_unregister_classes, pklass);
11307 mono_image_unlock (image);
11311 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11313 MonoReflectionModuleBuilder *module = sig->module;
11314 MonoDynamicImage *assembly = module != NULL ? module->dynamic_image : NULL;
11315 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11320 check_array_for_usertypes (sig->arguments);
11322 sigbuffer_init (&buf, 32);
11324 sigbuffer_add_value (&buf, 0x07);
11325 sigbuffer_add_value (&buf, na);
11326 if (assembly != NULL){
11327 for (i = 0; i < na; ++i) {
11328 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11329 encode_reflection_type (assembly, type, &buf);
11333 buflen = buf.p - buf.buf;
11334 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11335 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11336 sigbuffer_free (&buf);
11342 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11344 MonoDynamicImage *assembly = sig->module->dynamic_image;
11345 guint32 na = sig->arguments ? mono_array_length (sig->arguments) : 0;
11350 check_array_for_usertypes (sig->arguments);
11352 sigbuffer_init (&buf, 32);
11354 sigbuffer_add_value (&buf, 0x06);
11355 for (i = 0; i < na; ++i) {
11356 MonoReflectionType *type = mono_array_get (sig->arguments, MonoReflectionType*, i);
11357 encode_reflection_type (assembly, type, &buf);
11360 buflen = buf.p - buf.buf;
11361 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, buflen);
11362 memcpy (mono_array_addr (result, char, 0), buf.buf, buflen);
11363 sigbuffer_free (&buf);
11369 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11371 ReflectionMethodBuilder rmb;
11372 MonoMethodSignature *sig;
11377 sig = dynamic_method_to_signature (mb);
11379 reflection_methodbuilder_from_dynamic_method (&rmb, mb);
11382 * Resolve references.
11385 * Every second entry in the refs array is reserved for storing handle_class,
11386 * which is needed by the ldtoken implementation in the JIT.
11388 rmb.nrefs = mb->nrefs;
11389 rmb.refs = g_new0 (gpointer, mb->nrefs + 1);
11390 for (i = 0; i < mb->nrefs; i += 2) {
11391 MonoClass *handle_class;
11393 MonoObject *obj = mono_array_get (mb->refs, MonoObject*, i);
11395 if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11396 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11398 * The referenced DynamicMethod should already be created by the managed
11399 * code, except in the case of circular references. In that case, we store
11400 * method in the refs array, and fix it up later when the referenced
11401 * DynamicMethod is created.
11403 if (method->mhandle) {
11404 ref = method->mhandle;
11406 /* FIXME: GC object stored in unmanaged memory */
11409 /* FIXME: GC object stored in unmanaged memory */
11410 method->referenced_by = g_slist_append (method->referenced_by, mb);
11412 handle_class = mono_defaults.methodhandle_class;
11414 MonoException *ex = NULL;
11415 ref = resolve_object (mb->module->image, obj, &handle_class, NULL);
11417 ex = mono_get_exception_type_load (NULL, NULL);
11418 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
11419 ex = mono_security_core_clr_ensure_dynamic_method_resolved_object (ref, handle_class);
11423 mono_raise_exception (ex);
11428 rmb.refs [i] = ref; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11429 rmb.refs [i + 1] = handle_class;
11432 klass = mb->owner ? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType*)mb->owner)) : mono_defaults.object_class;
11434 mb->mhandle = reflection_methodbuilder_to_mono_method (klass, &rmb, sig);
11436 /* Fix up refs entries pointing at us */
11437 for (l = mb->referenced_by; l; l = l->next) {
11438 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)l->data;
11439 MonoMethodWrapper *wrapper = (MonoMethodWrapper*)method->mhandle;
11442 g_assert (method->mhandle);
11444 data = (gpointer*)wrapper->method_data;
11445 for (i = 0; i < GPOINTER_TO_UINT (data [0]); i += 2) {
11446 if ((data [i + 1] == mb) && (data [i + 1 + 1] == mono_defaults.methodhandle_class))
11447 data [i + 1] = mb->mhandle;
11450 g_slist_free (mb->referenced_by);
11454 /* ilgen is no longer needed */
11458 #endif /* DISABLE_REFLECTION_EMIT */
11461 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod *mb)
11466 mono_runtime_free_method (
11467 mono_object_get_domain ((MonoObject*)mb), mb->mhandle);
11472 * mono_reflection_is_valid_dynamic_token:
11474 * Returns TRUE if token is valid.
11478 mono_reflection_is_valid_dynamic_token (MonoDynamicImage *image, guint32 token)
11480 return mono_g_hash_table_lookup (image->tokens, GUINT_TO_POINTER (token)) != NULL;
11483 #ifndef DISABLE_REFLECTION_EMIT
11486 * mono_reflection_lookup_dynamic_token:
11488 * Finish the Builder object pointed to by TOKEN and return the corresponding
11489 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11490 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11493 * LOCKING: Take the loader lock
11496 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11498 MonoDynamicImage *assembly = (MonoDynamicImage*)image;
11502 mono_loader_lock ();
11503 obj = mono_g_hash_table_lookup (assembly->tokens, GUINT_TO_POINTER (token));
11504 mono_loader_unlock ();
11507 g_error ("Could not find required dynamic token 0x%08x", token);
11513 handle_class = &klass;
11514 return resolve_object (image, obj, handle_class, context);
11518 * ensure_complete_type:
11520 * Ensure that KLASS is completed if it is a dynamic type, or references
11524 ensure_complete_type (MonoClass *klass)
11526 if (klass->image->dynamic && !klass->wastypebuilder && mono_class_get_ref_info (klass)) {
11527 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (klass);
11529 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11531 // Asserting here could break a lot of code
11532 //g_assert (klass->wastypebuilder);
11535 if (klass->generic_class) {
11536 MonoGenericInst *inst = klass->generic_class->context.class_inst;
11539 for (i = 0; i < inst->type_argc; ++i) {
11540 ensure_complete_type (mono_class_from_mono_type (inst->type_argv [i]));
11546 resolve_object (MonoImage *image, MonoObject *obj, MonoClass **handle_class, MonoGenericContext *context)
11548 gpointer result = NULL;
11550 if (strcmp (obj->vtable->klass->name, "String") == 0) {
11551 result = mono_string_intern ((MonoString*)obj);
11552 *handle_class = mono_defaults.string_class;
11554 } else if (strcmp (obj->vtable->klass->name, "MonoType") == 0) {
11555 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11557 MonoType *inflated = mono_class_inflate_generic_type (type, context);
11558 result = mono_class_from_mono_type (inflated);
11559 mono_metadata_free_type (inflated);
11561 result = mono_class_from_mono_type (type);
11563 *handle_class = mono_defaults.typehandle_class;
11565 } else if (strcmp (obj->vtable->klass->name, "MonoMethod") == 0 ||
11566 strcmp (obj->vtable->klass->name, "MonoCMethod") == 0 ||
11567 strcmp (obj->vtable->klass->name, "MonoGenericCMethod") == 0 ||
11568 strcmp (obj->vtable->klass->name, "MonoGenericMethod") == 0) {
11569 result = ((MonoReflectionMethod*)obj)->method;
11571 result = mono_class_inflate_generic_method (result, context);
11572 *handle_class = mono_defaults.methodhandle_class;
11574 } else if (strcmp (obj->vtable->klass->name, "MethodBuilder") == 0) {
11575 MonoReflectionMethodBuilder *mb = (MonoReflectionMethodBuilder*)obj;
11576 result = mb->mhandle;
11578 /* Type is not yet created */
11579 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)mb->type;
11581 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11584 * Hopefully this has been filled in by calling CreateType() on the
11588 * TODO: This won't work if the application finishes another
11589 * TypeBuilder instance instead of this one.
11591 result = mb->mhandle;
11594 result = mono_class_inflate_generic_method (result, context);
11595 *handle_class = mono_defaults.methodhandle_class;
11596 } else if (strcmp (obj->vtable->klass->name, "ConstructorBuilder") == 0) {
11597 MonoReflectionCtorBuilder *cb = (MonoReflectionCtorBuilder*)obj;
11599 result = cb->mhandle;
11601 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)cb->type;
11603 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11604 result = cb->mhandle;
11607 result = mono_class_inflate_generic_method (result, context);
11608 *handle_class = mono_defaults.methodhandle_class;
11609 } else if (strcmp (obj->vtable->klass->name, "MonoField") == 0) {
11610 MonoClassField *field = ((MonoReflectionField*)obj)->field;
11612 ensure_complete_type (field->parent);
11614 MonoType *inflated = mono_class_inflate_generic_type (&field->parent->byval_arg, context);
11615 MonoClass *class = mono_class_from_mono_type (inflated);
11616 MonoClassField *inflated_field;
11617 gpointer iter = NULL;
11618 mono_metadata_free_type (inflated);
11619 while ((inflated_field = mono_class_get_fields (class, &iter))) {
11620 if (!strcmp (field->name, inflated_field->name))
11623 g_assert (inflated_field && !strcmp (field->name, inflated_field->name));
11624 result = inflated_field;
11628 *handle_class = mono_defaults.fieldhandle_class;
11630 } else if (strcmp (obj->vtable->klass->name, "FieldBuilder") == 0) {
11631 MonoReflectionFieldBuilder *fb = (MonoReflectionFieldBuilder*)obj;
11632 result = fb->handle;
11635 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)fb->typeb;
11637 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11638 result = fb->handle;
11641 if (fb->handle && fb->handle->parent->generic_container) {
11642 MonoClass *klass = fb->handle->parent;
11643 MonoType *type = mono_class_inflate_generic_type (&klass->byval_arg, context);
11644 MonoClass *inflated = mono_class_from_mono_type (type);
11646 result = mono_class_get_field_from_name (inflated, mono_field_get_name (fb->handle));
11648 mono_metadata_free_type (type);
11650 *handle_class = mono_defaults.fieldhandle_class;
11651 } else if (strcmp (obj->vtable->klass->name, "TypeBuilder") == 0) {
11652 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)obj;
11653 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)tb);
11656 klass = type->data.klass;
11657 if (klass->wastypebuilder) {
11658 /* Already created */
11662 mono_domain_try_type_resolve (mono_domain_get (), NULL, (MonoObject*)tb);
11663 result = type->data.klass;
11666 *handle_class = mono_defaults.typehandle_class;
11667 } else if (strcmp (obj->vtable->klass->name, "SignatureHelper") == 0) {
11668 MonoReflectionSigHelper *helper = (MonoReflectionSigHelper*)obj;
11669 MonoMethodSignature *sig;
11672 if (helper->arguments)
11673 nargs = mono_array_length (helper->arguments);
11677 sig = mono_metadata_signature_alloc (image, nargs);
11678 sig->explicit_this = helper->call_conv & 64 ? 1 : 0;
11679 sig->hasthis = helper->call_conv & 32 ? 1 : 0;
11681 if (helper->unmanaged_call_conv) { /* unmanaged */
11682 sig->call_convention = helper->unmanaged_call_conv - 1;
11683 sig->pinvoke = TRUE;
11684 } else if (helper->call_conv & 0x02) {
11685 sig->call_convention = MONO_CALL_VARARG;
11687 sig->call_convention = MONO_CALL_DEFAULT;
11690 sig->param_count = nargs;
11691 /* TODO: Copy type ? */
11692 sig->ret = helper->return_type->type;
11693 for (i = 0; i < nargs; ++i)
11694 sig->params [i] = mono_type_array_get_and_resolve (helper->arguments, i);
11697 *handle_class = NULL;
11698 } else if (strcmp (obj->vtable->klass->name, "DynamicMethod") == 0) {
11699 MonoReflectionDynamicMethod *method = (MonoReflectionDynamicMethod*)obj;
11700 /* Already created by the managed code */
11701 g_assert (method->mhandle);
11702 result = method->mhandle;
11703 *handle_class = mono_defaults.methodhandle_class;
11704 } else if (strcmp (obj->vtable->klass->name, "GenericTypeParameterBuilder") == 0) {
11705 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11706 type = mono_class_inflate_generic_type (type, context);
11707 result = mono_class_from_mono_type (type);
11708 *handle_class = mono_defaults.typehandle_class;
11710 mono_metadata_free_type (type);
11711 } else if (strcmp (obj->vtable->klass->name, "MonoGenericClass") == 0) {
11712 MonoType *type = mono_reflection_type_get_handle ((MonoReflectionType*)obj);
11713 type = mono_class_inflate_generic_type (type, context);
11714 result = mono_class_from_mono_type (type);
11715 *handle_class = mono_defaults.typehandle_class;
11717 mono_metadata_free_type (type);
11718 } else if (strcmp (obj->vtable->klass->name, "FieldOnTypeBuilderInst") == 0) {
11719 MonoReflectionFieldOnTypeBuilderInst *f = (MonoReflectionFieldOnTypeBuilderInst*)obj;
11720 MonoClass *inflated;
11722 MonoClassField *field;
11724 if (is_sre_field_builder (mono_object_class (f->fb)))
11725 field = ((MonoReflectionFieldBuilder*)f->fb)->handle;
11726 else if (is_sr_mono_field (mono_object_class (f->fb)))
11727 field = ((MonoReflectionField*)f->fb)->field;
11729 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)));
11731 type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)f->inst), context);
11732 inflated = mono_class_from_mono_type (type);
11734 result = field = mono_class_get_field_from_name (inflated, mono_field_get_name (field));
11735 ensure_complete_type (field->parent);
11737 mono_metadata_free_type (type);
11738 *handle_class = mono_defaults.fieldhandle_class;
11739 } else if (strcmp (obj->vtable->klass->name, "ConstructorOnTypeBuilderInst") == 0) {
11740 MonoReflectionCtorOnTypeBuilderInst *c = (MonoReflectionCtorOnTypeBuilderInst*)obj;
11741 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)c->inst), context);
11742 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11743 MonoMethod *method;
11745 if (is_sre_ctor_builder (mono_object_class (c->cb)))
11746 method = ((MonoReflectionCtorBuilder *)c->cb)->mhandle;
11747 else if (is_sr_mono_cmethod (mono_object_class (c->cb)))
11748 method = ((MonoReflectionMethod *)c->cb)->method;
11750 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)));
11752 result = inflate_mono_method (inflated_klass, method, (MonoObject*)c->cb);
11753 *handle_class = mono_defaults.methodhandle_class;
11754 mono_metadata_free_type (type);
11755 } else if (strcmp (obj->vtable->klass->name, "MethodOnTypeBuilderInst") == 0) {
11756 MonoReflectionMethodOnTypeBuilderInst *m = (MonoReflectionMethodOnTypeBuilderInst*)obj;
11757 if (m->method_args) {
11758 result = mono_reflection_method_on_tb_inst_get_handle (m);
11760 result = mono_class_inflate_generic_method (result, context);
11762 MonoType *type = mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType*)m->inst), context);
11763 MonoClass *inflated_klass = mono_class_from_mono_type (type);
11764 MonoMethod *method;
11766 if (is_sre_method_builder (mono_object_class (m->mb)))
11767 method = ((MonoReflectionMethodBuilder *)m->mb)->mhandle;
11768 else if (is_sr_mono_method (mono_object_class (m->mb)))
11769 method = ((MonoReflectionMethod *)m->mb)->method;
11771 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)));
11773 result = inflate_mono_method (inflated_klass, method, (MonoObject*)m->mb);
11774 mono_metadata_free_type (type);
11776 *handle_class = mono_defaults.methodhandle_class;
11777 } else if (strcmp (obj->vtable->klass->name, "MonoArrayMethod") == 0) {
11778 MonoReflectionArrayMethod *m = (MonoReflectionArrayMethod*)obj;
11781 MonoMethod *method;
11785 mtype = mono_reflection_type_get_handle (m->parent);
11786 klass = mono_class_from_mono_type (mtype);
11788 /* Find the method */
11790 name = mono_string_to_utf8 (m->name);
11792 while ((method = mono_class_get_methods (klass, &iter))) {
11793 if (!strcmp (method->name, name))
11800 // FIXME: Check parameters/return value etc. match
11803 *handle_class = mono_defaults.methodhandle_class;
11804 } else if (is_sre_array (mono_object_get_class(obj)) ||
11805 is_sre_byref (mono_object_get_class(obj)) ||
11806 is_sre_pointer (mono_object_get_class(obj))) {
11807 MonoReflectionType *ref_type = (MonoReflectionType *)obj;
11808 MonoType *type = mono_reflection_type_get_handle (ref_type);
11809 result = mono_class_from_mono_type (type);
11810 *handle_class = mono_defaults.typehandle_class;
11812 g_print ("%s\n", obj->vtable->klass->name);
11813 g_assert_not_reached ();
11818 #else /* DISABLE_REFLECTION_EMIT */
11821 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
11823 g_assert_not_reached ();
11828 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder *tb)
11830 g_assert_not_reached ();
11834 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder *tb)
11836 g_assert_not_reached ();
11840 mono_reflection_create_generic_class (MonoReflectionTypeBuilder *tb)
11842 g_assert_not_reached ();
11846 mono_reflection_create_internal_class (MonoReflectionTypeBuilder *tb)
11848 g_assert_not_reached ();
11852 mono_image_basic_init (MonoReflectionAssemblyBuilder *assemblyb)
11854 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11858 mono_image_module_basic_init (MonoReflectionModuleBuilder *moduleb)
11860 g_assert_not_reached ();
11864 mono_image_set_wrappers_type (MonoReflectionModuleBuilder *moduleb, MonoReflectionType *type)
11866 g_assert_not_reached ();
11869 MonoReflectionModule *
11870 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
11872 g_assert_not_reached ();
11877 mono_image_insert_string (MonoReflectionModuleBuilder *module, MonoString *str)
11879 g_assert_not_reached ();
11884 mono_image_create_method_token (MonoDynamicImage *assembly, MonoObject *obj, MonoArray *opt_param_types)
11886 g_assert_not_reached ();
11891 mono_image_create_token (MonoDynamicImage *assembly, MonoObject *obj,
11892 gboolean create_methodspec, gboolean register_token)
11894 g_assert_not_reached ();
11899 mono_image_register_token (MonoDynamicImage *assembly, guint32 token, MonoObject *obj)
11904 mono_reflection_generic_class_initialize (MonoReflectionGenericClass *type, MonoArray *methods,
11905 MonoArray *ctors, MonoArray *fields, MonoArray *properties,
11908 g_assert_not_reached ();
11912 mono_reflection_get_dynamic_overrides (MonoClass *klass, MonoMethod ***overrides, int *num_overrides)
11915 *num_overrides = 0;
11918 MonoReflectionEvent *
11919 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder *tb, MonoReflectionEventBuilder *eb)
11921 g_assert_not_reached ();
11925 MonoReflectionType*
11926 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder *tb)
11928 g_assert_not_reached ();
11933 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam *gparam)
11935 g_assert_not_reached ();
11939 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper *sig)
11941 g_assert_not_reached ();
11946 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper *sig)
11948 g_assert_not_reached ();
11953 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod *mb)
11958 mono_reflection_lookup_dynamic_token (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
11964 mono_reflection_type_get_handle (MonoReflectionType* ref)
11971 #endif /* DISABLE_REFLECTION_EMIT */
11973 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11974 const static guint32 declsec_flags_map[] = {
11975 0x00000000, /* empty */
11976 MONO_DECLSEC_FLAG_REQUEST, /* SECURITY_ACTION_REQUEST (x01) */
11977 MONO_DECLSEC_FLAG_DEMAND, /* SECURITY_ACTION_DEMAND (x02) */
11978 MONO_DECLSEC_FLAG_ASSERT, /* SECURITY_ACTION_ASSERT (x03) */
11979 MONO_DECLSEC_FLAG_DENY, /* SECURITY_ACTION_DENY (x04) */
11980 MONO_DECLSEC_FLAG_PERMITONLY, /* SECURITY_ACTION_PERMITONLY (x05) */
11981 MONO_DECLSEC_FLAG_LINKDEMAND, /* SECURITY_ACTION_LINKDEMAND (x06) */
11982 MONO_DECLSEC_FLAG_INHERITANCEDEMAND, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11983 MONO_DECLSEC_FLAG_REQUEST_MINIMUM, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11984 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11985 MONO_DECLSEC_FLAG_REQUEST_REFUSE, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11986 MONO_DECLSEC_FLAG_PREJIT_GRANT, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11987 MONO_DECLSEC_FLAG_PREJIT_DENY, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11988 MONO_DECLSEC_FLAG_NONCAS_DEMAND, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11989 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11990 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11991 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11992 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11993 MONO_DECLSEC_FLAG_DEMAND_CHOICE, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11997 * Returns flags that includes all available security action associated to the handle.
11998 * @token: metadata token (either for a class or a method)
11999 * @image: image where resides the metadata.
12002 mono_declsec_get_flags (MonoImage *image, guint32 token)
12004 int index = mono_metadata_declsec_from_index (image, token);
12005 MonoTableInfo *t = &image->tables [MONO_TABLE_DECLSECURITY];
12006 guint32 result = 0;
12010 /* HasSecurity can be present for other, not specially encoded, attributes,
12011 e.g. SuppressUnmanagedCodeSecurityAttribute */
12015 for (i = index; i < t->rows; i++) {
12016 guint32 cols [MONO_DECL_SECURITY_SIZE];
12018 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12019 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12022 action = cols [MONO_DECL_SECURITY_ACTION];
12023 if ((action >= MONO_DECLSEC_ACTION_MIN) && (action <= MONO_DECLSEC_ACTION_MAX)) {
12024 result |= declsec_flags_map [action];
12026 g_assert_not_reached ();
12033 * Get the security actions (in the form of flags) associated with the specified method.
12035 * @method: The method for which we want the declarative security flags.
12036 * Return the declarative security flags for the method (only).
12038 * Note: To keep MonoMethod size down we do not cache the declarative security flags
12039 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
12042 mono_declsec_flags_from_method (MonoMethod *method)
12044 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12045 /* FIXME: No cache (for the moment) */
12046 guint32 idx = mono_method_get_index (method);
12047 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12048 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12049 return mono_declsec_get_flags (method->klass->image, idx);
12055 * Get the security actions (in the form of flags) associated with the specified class.
12057 * @klass: The class for which we want the declarative security flags.
12058 * Return the declarative security flags for the class.
12060 * Note: We cache the flags inside the MonoClass structure as this will get
12061 * called very often (at least for each method).
12064 mono_declsec_flags_from_class (MonoClass *klass)
12066 if (klass->flags & TYPE_ATTRIBUTE_HAS_SECURITY) {
12067 if (!klass->ext || !klass->ext->declsec_flags) {
12070 idx = mono_metadata_token_index (klass->type_token);
12071 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12072 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12073 mono_loader_lock ();
12074 mono_class_alloc_ext (klass);
12075 mono_loader_unlock ();
12076 /* we cache the flags on classes */
12077 klass->ext->declsec_flags = mono_declsec_get_flags (klass->image, idx);
12079 return klass->ext->declsec_flags;
12085 * Get the security actions (in the form of flags) associated with the specified assembly.
12087 * @assembly: The assembly for which we want the declarative security flags.
12088 * Return the declarative security flags for the assembly.
12091 mono_declsec_flags_from_assembly (MonoAssembly *assembly)
12093 guint32 idx = 1; /* there is only one assembly */
12094 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12095 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12096 return mono_declsec_get_flags (assembly->image, idx);
12101 * Fill actions for the specific index (which may either be an encoded class token or
12102 * an encoded method token) from the metadata image.
12103 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
12106 fill_actions_from_index (MonoImage *image, guint32 token, MonoDeclSecurityActions* actions,
12107 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12109 MonoBoolean result = FALSE;
12111 guint32 cols [MONO_DECL_SECURITY_SIZE];
12112 int index = mono_metadata_declsec_from_index (image, token);
12115 t = &image->tables [MONO_TABLE_DECLSECURITY];
12116 for (i = index; i < t->rows; i++) {
12117 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12119 if (cols [MONO_DECL_SECURITY_PARENT] != token)
12122 /* if present only replace (class) permissions with method permissions */
12123 /* if empty accept either class or method permissions */
12124 if (cols [MONO_DECL_SECURITY_ACTION] == id_std) {
12125 if (!actions->demand.blob) {
12126 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12127 actions->demand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12128 actions->demand.blob = (char*) (blob + 2);
12129 actions->demand.size = mono_metadata_decode_blob_size (blob, &blob);
12132 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_noncas) {
12133 if (!actions->noncasdemand.blob) {
12134 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12135 actions->noncasdemand.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12136 actions->noncasdemand.blob = (char*) (blob + 2);
12137 actions->noncasdemand.size = mono_metadata_decode_blob_size (blob, &blob);
12140 } else if (cols [MONO_DECL_SECURITY_ACTION] == id_choice) {
12141 if (!actions->demandchoice.blob) {
12142 const char *blob = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12143 actions->demandchoice.index = cols [MONO_DECL_SECURITY_PERMISSIONSET];
12144 actions->demandchoice.blob = (char*) (blob + 2);
12145 actions->demandchoice.size = mono_metadata_decode_blob_size (blob, &blob);
12155 mono_declsec_get_class_demands_params (MonoClass *klass, MonoDeclSecurityActions* demands,
12156 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12158 guint32 idx = mono_metadata_token_index (klass->type_token);
12159 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12160 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12161 return fill_actions_from_index (klass->image, idx, demands, id_std, id_noncas, id_choice);
12165 mono_declsec_get_method_demands_params (MonoMethod *method, MonoDeclSecurityActions* demands,
12166 guint32 id_std, guint32 id_noncas, guint32 id_choice)
12168 guint32 idx = mono_method_get_index (method);
12169 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12170 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12171 return fill_actions_from_index (method->klass->image, idx, demands, id_std, id_noncas, id_choice);
12175 * Collect all actions (that requires to generate code in mini) assigned for
12176 * the specified method.
12177 * Note: Don't use the content of actions if the function return FALSE.
12180 mono_declsec_get_demands (MonoMethod *method, MonoDeclSecurityActions* demands)
12182 guint32 mask = MONO_DECLSEC_FLAG_DEMAND | MONO_DECLSEC_FLAG_NONCAS_DEMAND |
12183 MONO_DECLSEC_FLAG_DEMAND_CHOICE;
12184 MonoBoolean result = FALSE;
12187 /* quick exit if no declarative security is present in the metadata */
12188 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12191 /* we want the original as the wrapper is "free" of the security informations */
12192 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12193 method = mono_marshal_method_from_wrapper (method);
12198 /* First we look for method-level attributes */
12199 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12200 mono_class_init (method->klass);
12201 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12203 result = mono_declsec_get_method_demands_params (method, demands,
12204 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12207 /* Here we use (or create) the class declarative cache to look for demands */
12208 flags = mono_declsec_flags_from_class (method->klass);
12209 if (flags & mask) {
12211 mono_class_init (method->klass);
12212 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12214 result |= mono_declsec_get_class_demands_params (method->klass, demands,
12215 SECURITY_ACTION_DEMAND, SECURITY_ACTION_NONCASDEMAND, SECURITY_ACTION_DEMANDCHOICE);
12218 /* The boolean return value is used as a shortcut in case nothing needs to
12219 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12225 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12227 * Note: Don't use the content of actions if the function return FALSE.
12230 mono_declsec_get_linkdemands (MonoMethod *method, MonoDeclSecurityActions* klass, MonoDeclSecurityActions *cmethod)
12232 MonoBoolean result = FALSE;
12235 /* quick exit if no declarative security is present in the metadata */
12236 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12239 /* we want the original as the wrapper is "free" of the security informations */
12240 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12241 method = mono_marshal_method_from_wrapper (method);
12246 /* results are independant - zeroize both */
12247 memset (cmethod, 0, sizeof (MonoDeclSecurityActions));
12248 memset (klass, 0, sizeof (MonoDeclSecurityActions));
12250 /* First we look for method-level attributes */
12251 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12252 mono_class_init (method->klass);
12254 result = mono_declsec_get_method_demands_params (method, cmethod,
12255 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12258 /* Here we use (or create) the class declarative cache to look for demands */
12259 flags = mono_declsec_flags_from_class (method->klass);
12260 if (flags & (MONO_DECLSEC_FLAG_LINKDEMAND | MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND | MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE)) {
12261 mono_class_init (method->klass);
12263 result |= mono_declsec_get_class_demands_params (method->klass, klass,
12264 SECURITY_ACTION_LINKDEMAND, SECURITY_ACTION_NONCASLINKDEMAND, SECURITY_ACTION_LINKDEMANDCHOICE);
12271 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12273 * @klass The inherited class - this is the class that provides the security check (attributes)
12275 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12277 * Note: Don't use the content of actions if the function return FALSE.
12280 mono_declsec_get_inheritdemands_class (MonoClass *klass, MonoDeclSecurityActions* demands)
12282 MonoBoolean result = FALSE;
12285 /* quick exit if no declarative security is present in the metadata */
12286 if (!klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12289 /* Here we use (or create) the class declarative cache to look for demands */
12290 flags = mono_declsec_flags_from_class (klass);
12291 if (flags & (MONO_DECLSEC_FLAG_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND | MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE)) {
12292 mono_class_init (klass);
12293 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12295 result |= mono_declsec_get_class_demands_params (klass, demands,
12296 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12303 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12305 * Note: Don't use the content of actions if the function return FALSE.
12308 mono_declsec_get_inheritdemands_method (MonoMethod *method, MonoDeclSecurityActions* demands)
12310 /* quick exit if no declarative security is present in the metadata */
12311 if (!method->klass->image->tables [MONO_TABLE_DECLSECURITY].rows)
12314 /* we want the original as the wrapper is "free" of the security informations */
12315 if (method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE || method->wrapper_type == MONO_WRAPPER_MANAGED_TO_MANAGED) {
12316 method = mono_marshal_method_from_wrapper (method);
12321 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12322 mono_class_init (method->klass);
12323 memset (demands, 0, sizeof (MonoDeclSecurityActions));
12325 return mono_declsec_get_method_demands_params (method, demands,
12326 SECURITY_ACTION_INHERITDEMAND, SECURITY_ACTION_NONCASINHERITANCE, SECURITY_ACTION_INHERITDEMANDCHOICE);
12333 get_declsec_action (MonoImage *image, guint32 token, guint32 action, MonoDeclSecurityEntry *entry)
12335 guint32 cols [MONO_DECL_SECURITY_SIZE];
12339 int index = mono_metadata_declsec_from_index (image, token);
12343 t = &image->tables [MONO_TABLE_DECLSECURITY];
12344 for (i = index; i < t->rows; i++) {
12345 mono_metadata_decode_row (t, i, cols, MONO_DECL_SECURITY_SIZE);
12347 /* shortcut - index are ordered */
12348 if (token != cols [MONO_DECL_SECURITY_PARENT])
12351 if (cols [MONO_DECL_SECURITY_ACTION] == action) {
12352 const char *metadata = mono_metadata_blob_heap (image, cols [MONO_DECL_SECURITY_PERMISSIONSET]);
12353 entry->blob = (char*) (metadata + 2);
12354 entry->size = mono_metadata_decode_blob_size (metadata, &metadata);
12363 mono_declsec_get_method_action (MonoMethod *method, guint32 action, MonoDeclSecurityEntry *entry)
12365 if (method->flags & METHOD_ATTRIBUTE_HAS_SECURITY) {
12366 guint32 idx = mono_method_get_index (method);
12367 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12368 idx |= MONO_HAS_DECL_SECURITY_METHODDEF;
12369 return get_declsec_action (method->klass->image, idx, action, entry);
12375 mono_declsec_get_class_action (MonoClass *klass, guint32 action, MonoDeclSecurityEntry *entry)
12378 guint32 flags = mono_declsec_flags_from_class (klass);
12379 if (declsec_flags_map [action] & flags) {
12380 guint32 idx = mono_metadata_token_index (klass->type_token);
12381 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12382 idx |= MONO_HAS_DECL_SECURITY_TYPEDEF;
12383 return get_declsec_action (klass->image, idx, action, entry);
12389 mono_declsec_get_assembly_action (MonoAssembly *assembly, guint32 action, MonoDeclSecurityEntry *entry)
12391 guint32 idx = 1; /* there is only one assembly */
12392 idx <<= MONO_HAS_DECL_SECURITY_BITS;
12393 idx |= MONO_HAS_DECL_SECURITY_ASSEMBLY;
12395 return get_declsec_action (assembly->image, idx, action, entry);
12399 mono_reflection_call_is_assignable_to (MonoClass *klass, MonoClass *oklass)
12401 MonoObject *res, *exc;
12403 static MonoClass *System_Reflection_Emit_TypeBuilder = NULL;
12404 static MonoMethod *method = NULL;
12406 if (!System_Reflection_Emit_TypeBuilder) {
12407 System_Reflection_Emit_TypeBuilder = mono_class_from_name (mono_defaults.corlib, "System.Reflection.Emit", "TypeBuilder");
12408 g_assert (System_Reflection_Emit_TypeBuilder);
12410 if (method == NULL) {
12411 method = mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder, "IsAssignableTo", 1);
12416 * The result of mono_type_get_object () might be a System.MonoType but we
12417 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12419 g_assert (mono_class_get_ref_info (klass));
12420 g_assert (!strcmp (((MonoObject*)(mono_class_get_ref_info (klass)))->vtable->klass->name, "TypeBuilder"));
12422 params [0] = mono_type_get_object (mono_domain_get (), &oklass->byval_arg);
12424 res = mono_runtime_invoke (method, (MonoObject*)(mono_class_get_ref_info (klass)), params, &exc);
12428 return *(MonoBoolean*)mono_object_unbox (res);