2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
40 #include <mono/metadata/debug-helpers.h>
41 #include <mono/utils/mono-string.h>
42 #include <mono/utils/mono-error-internals.h>
46 static void* reflection_info_desc
= NULL
;
47 #define MOVING_GC_REGISTER(addr) do { \
48 if (!reflection_info_desc) { \
50 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
52 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
55 #define MOVING_GC_REGISTER(addr)
58 static gboolean
is_usertype (MonoReflectionType
*ref
);
59 static MonoReflectionType
*mono_reflection_type_resolve_user_types (MonoReflectionType
*type
);
67 #define TEXT_OFFSET 512
68 #define CLI_H_SIZE 136
69 #define FILE_ALIGN 512
70 #define VIRT_ALIGN 8192
71 #define START_TEXT_RVA 0x00002000
74 MonoReflectionILGen
*ilgen
;
75 MonoReflectionType
*rtype
;
76 MonoArray
*parameters
;
77 MonoArray
*generic_params
;
78 MonoGenericContainer
*generic_container
;
84 guint32
*table_idx
; /* note: it's a pointer */
88 MonoBoolean init_locals
;
89 MonoBoolean skip_visibility
;
90 MonoArray
*return_modreq
;
91 MonoArray
*return_modopt
;
92 MonoArray
*param_modreq
;
93 MonoArray
*param_modopt
;
94 MonoArray
*permissions
;
99 int charset
, extra_flags
, native_cc
;
100 MonoString
*dll
, *dllentry
;
101 } ReflectionMethodBuilder
;
105 MonoReflectionGenericParam
*gparam
;
106 } GenericParamTableEntry
;
108 const unsigned char table_sizes
[MONO_TABLE_NUM
] = {
118 MONO_INTERFACEIMPL_SIZE
,
119 MONO_MEMBERREF_SIZE
, /* 0x0A */
121 MONO_CUSTOM_ATTR_SIZE
,
122 MONO_FIELD_MARSHAL_SIZE
,
123 MONO_DECL_SECURITY_SIZE
,
124 MONO_CLASS_LAYOUT_SIZE
,
125 MONO_FIELD_LAYOUT_SIZE
, /* 0x10 */
126 MONO_STAND_ALONE_SIGNATURE_SIZE
,
130 MONO_PROPERTY_MAP_SIZE
,
133 MONO_METHOD_SEMA_SIZE
,
134 MONO_METHODIMPL_SIZE
,
135 MONO_MODULEREF_SIZE
, /* 0x1A */
141 MONO_ASSEMBLY_SIZE
, /* 0x20 */
142 MONO_ASSEMBLY_PROCESSOR_SIZE
,
143 MONO_ASSEMBLYOS_SIZE
,
144 MONO_ASSEMBLYREF_SIZE
,
145 MONO_ASSEMBLYREFPROC_SIZE
,
146 MONO_ASSEMBLYREFOS_SIZE
,
150 MONO_NESTED_CLASS_SIZE
,
152 MONO_GENERICPARAM_SIZE
, /* 0x2A */
153 MONO_METHODSPEC_SIZE
,
154 MONO_GENPARCONSTRAINT_SIZE
158 #ifndef DISABLE_REFLECTION_EMIT
159 static guint32
mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
);
160 static guint32
mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
);
161 static guint32
mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*cb
);
162 static guint32
mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
);
163 static void ensure_runtime_vtable (MonoClass
*klass
);
164 static gpointer
resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
);
165 static guint32
mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
);
166 static guint32
encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
);
167 static gpointer
register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
);
168 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
);
169 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
);
170 static guint32
create_generic_typespec (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
);
173 static guint32
mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
);
174 static guint32
mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
);
175 static void mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
);
176 static guint32
encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
);
177 static guint32
encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
);
178 static char* type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
);
179 static void encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
);
180 static void get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
);
181 static MonoReflectionType
*mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
);
182 static MonoType
* mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
);
183 static MonoReflectionType
* mono_reflection_type_resolve_user_types (MonoReflectionType
*type
);
184 static gboolean
is_sre_array (MonoClass
*class);
185 static gboolean
is_sre_byref (MonoClass
*class);
186 static gboolean
is_sre_pointer (MonoClass
*class);
187 static gboolean
is_sre_type_builder (MonoClass
*class);
188 static gboolean
is_sre_method_builder (MonoClass
*class);
189 static gboolean
is_sre_ctor_builder (MonoClass
*class);
190 static gboolean
is_sre_field_builder (MonoClass
*class);
191 static gboolean
is_sr_mono_method (MonoClass
*class);
192 static gboolean
is_sr_mono_cmethod (MonoClass
*class);
193 static gboolean
is_sr_mono_generic_method (MonoClass
*class);
194 static gboolean
is_sr_mono_generic_cmethod (MonoClass
*class);
195 static gboolean
is_sr_mono_field (MonoClass
*class);
196 static gboolean
is_sr_mono_property (MonoClass
*class);
197 static gboolean
is_sre_method_on_tb_inst (MonoClass
*class);
198 static gboolean
is_sre_ctor_on_tb_inst (MonoClass
*class);
200 static guint32
mono_image_get_methodspec_token (MonoDynamicImage
*assembly
, MonoMethod
*method
);
201 static guint32
mono_image_get_inflated_method_token (MonoDynamicImage
*assembly
, MonoMethod
*m
);
202 static MonoMethod
* inflate_method (MonoReflectionType
*type
, MonoObject
*obj
);
204 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
205 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
206 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
207 __type = mono_reflection_type_resolve_user_types (__type); \
208 mono_array_set (arr, MonoReflectionType*, index, __type); \
211 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
214 mono_reflection_init (void)
219 sigbuffer_init (SigBuffer
*buf
, int size
)
221 buf
->buf
= g_malloc (size
);
223 buf
->end
= buf
->buf
+ size
;
227 sigbuffer_make_room (SigBuffer
*buf
, int size
)
229 if (buf
->end
- buf
->p
< size
) {
230 int new_size
= buf
->end
- buf
->buf
+ size
+ 32;
231 char *p
= g_realloc (buf
->buf
, new_size
);
232 size
= buf
->p
- buf
->buf
;
235 buf
->end
= buf
->buf
+ new_size
;
240 sigbuffer_add_value (SigBuffer
*buf
, guint32 val
)
242 sigbuffer_make_room (buf
, 6);
243 mono_metadata_encode_value (val
, buf
->p
, &buf
->p
);
247 sigbuffer_add_byte (SigBuffer
*buf
, guint8 val
)
249 sigbuffer_make_room (buf
, 1);
255 sigbuffer_add_mem (SigBuffer
*buf
, char *p
, guint32 size
)
257 sigbuffer_make_room (buf
, size
);
258 memcpy (buf
->p
, p
, size
);
263 sigbuffer_free (SigBuffer
*buf
)
268 #ifndef DISABLE_REFLECTION_EMIT
272 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
276 image_g_malloc (MonoImage
*image
, guint size
)
279 return mono_image_alloc (image
, size
);
281 return g_malloc (size
);
283 #endif /* !DISABLE_REFLECTION_EMIT */
288 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
292 image_g_malloc0 (MonoImage
*image
, guint size
)
295 return mono_image_alloc0 (image
, size
);
297 return g_malloc0 (size
);
300 #ifndef DISABLE_REFLECTION_EMIT
302 image_strdup (MonoImage
*image
, const char *s
)
305 return mono_image_strdup (image
, s
);
311 #define image_g_new(image,struct_type, n_structs) \
312 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
314 #define image_g_new0(image,struct_type, n_structs) \
315 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
319 alloc_table (MonoDynamicTable
*table
, guint nrows
)
322 g_assert (table
->columns
);
323 if (nrows
+ 1 >= table
->alloc_rows
) {
324 while (nrows
+ 1 >= table
->alloc_rows
) {
325 if (table
->alloc_rows
== 0)
326 table
->alloc_rows
= 16;
328 table
->alloc_rows
*= 2;
331 table
->values
= g_renew (guint32
, table
->values
, (table
->alloc_rows
) * table
->columns
);
336 make_room_in_stream (MonoDynamicStream
*stream
, int size
)
338 if (size
<= stream
->alloc_size
)
341 while (stream
->alloc_size
<= size
) {
342 if (stream
->alloc_size
< 4096)
343 stream
->alloc_size
= 4096;
345 stream
->alloc_size
*= 2;
348 stream
->data
= g_realloc (stream
->data
, stream
->alloc_size
);
352 string_heap_insert (MonoDynamicStream
*sh
, const char *str
)
356 gpointer oldkey
, oldval
;
358 if (g_hash_table_lookup_extended (sh
->hash
, str
, &oldkey
, &oldval
))
359 return GPOINTER_TO_UINT (oldval
);
361 len
= strlen (str
) + 1;
364 make_room_in_stream (sh
, idx
+ len
);
367 * We strdup the string even if we already copy them in sh->data
368 * so that the string pointers in the hash remain valid even if
369 * we need to realloc sh->data. We may want to avoid that later.
371 g_hash_table_insert (sh
->hash
, g_strdup (str
), GUINT_TO_POINTER (idx
));
372 memcpy (sh
->data
+ idx
, str
, len
);
378 string_heap_insert_mstring (MonoDynamicStream
*sh
, MonoString
*str
)
380 char *name
= mono_string_to_utf8 (str
);
382 idx
= string_heap_insert (sh
, name
);
387 #ifndef DISABLE_REFLECTION_EMIT
389 string_heap_init (MonoDynamicStream
*sh
)
392 sh
->alloc_size
= 4096;
393 sh
->data
= g_malloc (4096);
394 sh
->hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
395 string_heap_insert (sh
, "");
400 mono_image_add_stream_data (MonoDynamicStream
*stream
, const char *data
, guint32 len
)
404 make_room_in_stream (stream
, stream
->index
+ len
);
405 memcpy (stream
->data
+ stream
->index
, data
, len
);
407 stream
->index
+= len
;
409 * align index? Not without adding an additional param that controls it since
410 * we may store a blob value in pieces.
416 mono_image_add_stream_zero (MonoDynamicStream
*stream
, guint32 len
)
420 make_room_in_stream (stream
, stream
->index
+ len
);
421 memset (stream
->data
+ stream
->index
, 0, len
);
423 stream
->index
+= len
;
428 stream_data_align (MonoDynamicStream
*stream
)
431 guint32 count
= stream
->index
% 4;
433 /* we assume the stream data will be aligned */
435 mono_image_add_stream_data (stream
, buf
, 4 - count
);
438 #ifndef DISABLE_REFLECTION_EMIT
440 mono_blob_entry_hash (const char* str
)
444 len
= mono_metadata_decode_blob_size (str
, &str
);
448 for (str
+= 1; str
< end
; str
++)
449 h
= (h
<< 5) - h
+ *str
;
457 mono_blob_entry_equal (const char *str1
, const char *str2
) {
461 len
= mono_metadata_decode_blob_size (str1
, &end1
);
462 len2
= mono_metadata_decode_blob_size (str2
, &end2
);
465 return memcmp (end1
, end2
, len
) == 0;
469 add_to_blob_cached (MonoDynamicImage
*assembly
, char *b1
, int s1
, char *b2
, int s2
)
473 gpointer oldkey
, oldval
;
475 copy
= g_malloc (s1
+s2
);
476 memcpy (copy
, b1
, s1
);
477 memcpy (copy
+ s1
, b2
, s2
);
478 if (g_hash_table_lookup_extended (assembly
->blob_cache
, copy
, &oldkey
, &oldval
)) {
480 idx
= GPOINTER_TO_UINT (oldval
);
482 idx
= mono_image_add_stream_data (&assembly
->blob
, b1
, s1
);
483 mono_image_add_stream_data (&assembly
->blob
, b2
, s2
);
484 g_hash_table_insert (assembly
->blob_cache
, copy
, GUINT_TO_POINTER (idx
));
490 sigbuffer_add_to_blob_cached (MonoDynamicImage
*assembly
, SigBuffer
*buf
)
494 guint32 size
= buf
->p
- buf
->buf
;
496 g_assert (size
<= (buf
->end
- buf
->buf
));
497 mono_metadata_encode_value (size
, b
, &b
);
498 return add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, buf
->buf
, size
);
502 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
503 * dest may be misaligned.
506 swap_with_size (char *dest
, const char* val
, int len
, int nelem
) {
507 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
510 for (elem
= 0; elem
< nelem
; ++elem
) {
536 g_assert_not_reached ();
542 memcpy (dest
, val
, len
* nelem
);
547 add_mono_string_to_blob_cached (MonoDynamicImage
*assembly
, MonoString
*str
)
551 guint32 idx
= 0, len
;
553 len
= str
->length
* 2;
554 mono_metadata_encode_value (len
, b
, &b
);
555 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
557 char *swapped
= g_malloc (2 * mono_string_length (str
));
558 const char *p
= (const char*)mono_string_chars (str
);
560 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
561 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
565 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
570 #ifndef DISABLE_REFLECTION_EMIT
572 default_class_from_mono_type (MonoType
*type
)
574 switch (type
->type
) {
575 case MONO_TYPE_OBJECT
:
576 return mono_defaults
.object_class
;
578 return mono_defaults
.void_class
;
579 case MONO_TYPE_BOOLEAN
:
580 return mono_defaults
.boolean_class
;
582 return mono_defaults
.char_class
;
584 return mono_defaults
.sbyte_class
;
586 return mono_defaults
.byte_class
;
588 return mono_defaults
.int16_class
;
590 return mono_defaults
.uint16_class
;
592 return mono_defaults
.int32_class
;
594 return mono_defaults
.uint32_class
;
596 return mono_defaults
.int_class
;
598 return mono_defaults
.uint_class
;
600 return mono_defaults
.int64_class
;
602 return mono_defaults
.uint64_class
;
604 return mono_defaults
.single_class
;
606 return mono_defaults
.double_class
;
607 case MONO_TYPE_STRING
:
608 return mono_defaults
.string_class
;
610 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type
->type
);
611 g_assert_not_reached ();
619 * mono_class_get_ref_info:
621 * Return the type builder/generic param builder corresponding to KLASS, if it exists.
624 mono_class_get_ref_info (MonoClass
*klass
)
626 if (klass
->ref_info_handle
== 0)
629 return mono_gchandle_get_target (klass
->ref_info_handle
);
633 mono_class_set_ref_info (MonoClass
*klass
, gpointer obj
)
635 klass
->ref_info_handle
= mono_gchandle_new ((MonoObject
*)obj
, FALSE
);
636 g_assert (klass
->ref_info_handle
!= 0);
640 mono_class_free_ref_info (MonoClass
*klass
)
642 if (klass
->ref_info_handle
) {
643 mono_gchandle_free (klass
->ref_info_handle
);
644 klass
->ref_info_handle
= 0;
649 encode_generic_class (MonoDynamicImage
*assembly
, MonoGenericClass
*gclass
, SigBuffer
*buf
)
652 MonoGenericInst
*class_inst
;
657 class_inst
= gclass
->context
.class_inst
;
659 sigbuffer_add_value (buf
, MONO_TYPE_GENERICINST
);
660 klass
= gclass
->container_class
;
661 sigbuffer_add_value (buf
, klass
->byval_arg
.type
);
662 sigbuffer_add_value (buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
664 sigbuffer_add_value (buf
, class_inst
->type_argc
);
665 for (i
= 0; i
< class_inst
->type_argc
; ++i
)
666 encode_type (assembly
, class_inst
->type_argv
[i
], buf
);
671 encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
)
674 g_assert_not_reached ();
679 sigbuffer_add_value (buf
, MONO_TYPE_BYREF
);
683 case MONO_TYPE_BOOLEAN
:
697 case MONO_TYPE_STRING
:
698 case MONO_TYPE_OBJECT
:
699 case MONO_TYPE_TYPEDBYREF
:
700 sigbuffer_add_value (buf
, type
->type
);
703 sigbuffer_add_value (buf
, type
->type
);
704 encode_type (assembly
, type
->data
.type
, buf
);
706 case MONO_TYPE_SZARRAY
:
707 sigbuffer_add_value (buf
, type
->type
);
708 encode_type (assembly
, &type
->data
.klass
->byval_arg
, buf
);
710 case MONO_TYPE_VALUETYPE
:
711 case MONO_TYPE_CLASS
: {
712 MonoClass
*k
= mono_class_from_mono_type (type
);
714 if (k
->generic_container
) {
715 MonoGenericClass
*gclass
= mono_metadata_lookup_generic_class (k
, k
->generic_container
->context
.class_inst
, TRUE
);
716 encode_generic_class (assembly
, gclass
, buf
);
719 * Make sure we use the correct type.
721 sigbuffer_add_value (buf
, k
->byval_arg
.type
);
723 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
724 * otherwise two typerefs could point to the same type, leading to
725 * verification errors.
727 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, &k
->byval_arg
));
731 case MONO_TYPE_ARRAY
:
732 sigbuffer_add_value (buf
, type
->type
);
733 encode_type (assembly
, &type
->data
.array
->eklass
->byval_arg
, buf
);
734 sigbuffer_add_value (buf
, type
->data
.array
->rank
);
735 sigbuffer_add_value (buf
, 0); /* FIXME: set to 0 for now */
736 sigbuffer_add_value (buf
, 0);
738 case MONO_TYPE_GENERICINST
:
739 encode_generic_class (assembly
, type
->data
.generic_class
, buf
);
743 sigbuffer_add_value (buf
, type
->type
);
744 sigbuffer_add_value (buf
, mono_type_get_generic_param_num (type
));
747 g_error ("need to encode type %x", type
->type
);
752 encode_reflection_type (MonoDynamicImage
*assembly
, MonoReflectionType
*type
, SigBuffer
*buf
)
755 sigbuffer_add_value (buf
, MONO_TYPE_VOID
);
759 encode_type (assembly
, mono_reflection_type_get_handle (type
), buf
);
763 encode_custom_modifiers (MonoDynamicImage
*assembly
, MonoArray
*modreq
, MonoArray
*modopt
, SigBuffer
*buf
)
768 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
769 MonoType
*mod
= mono_type_array_get_and_resolve (modreq
, i
);
770 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_REQD
);
771 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
));
775 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
776 MonoType
*mod
= mono_type_array_get_and_resolve (modopt
, i
);
777 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_OPT
);
778 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
));
783 #ifndef DISABLE_REFLECTION_EMIT
785 method_encode_signature (MonoDynamicImage
*assembly
, MonoMethodSignature
*sig
)
789 guint32 nparams
= sig
->param_count
;
795 sigbuffer_init (&buf
, 32);
797 * FIXME: vararg, explicit_this, differenc call_conv values...
799 idx
= sig
->call_convention
;
801 idx
|= 0x20; /* hasthis */
802 if (sig
->generic_param_count
)
803 idx
|= 0x10; /* generic */
804 sigbuffer_add_byte (&buf
, idx
);
805 if (sig
->generic_param_count
)
806 sigbuffer_add_value (&buf
, sig
->generic_param_count
);
807 sigbuffer_add_value (&buf
, nparams
);
808 encode_type (assembly
, sig
->ret
, &buf
);
809 for (i
= 0; i
< nparams
; ++i
) {
810 if (i
== sig
->sentinelpos
)
811 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
812 encode_type (assembly
, sig
->params
[i
], &buf
);
814 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
815 sigbuffer_free (&buf
);
821 method_builder_encode_signature (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
824 * FIXME: reuse code from method_encode_signature().
828 guint32 nparams
= mb
->parameters
? mono_array_length (mb
->parameters
): 0;
829 guint32 ngparams
= mb
->generic_params
? mono_array_length (mb
->generic_params
): 0;
830 guint32 notypes
= mb
->opt_types
? mono_array_length (mb
->opt_types
): 0;
833 sigbuffer_init (&buf
, 32);
834 /* LAMESPEC: all the call conv spec is foobared */
835 idx
= mb
->call_conv
& 0x60; /* has-this, explicit-this */
836 if (mb
->call_conv
& 2)
837 idx
|= 0x5; /* vararg */
838 if (!(mb
->attrs
& METHOD_ATTRIBUTE_STATIC
))
839 idx
|= 0x20; /* hasthis */
841 idx
|= 0x10; /* generic */
842 sigbuffer_add_byte (&buf
, idx
);
844 sigbuffer_add_value (&buf
, ngparams
);
845 sigbuffer_add_value (&buf
, nparams
+ notypes
);
846 encode_custom_modifiers (assembly
, mb
->return_modreq
, mb
->return_modopt
, &buf
);
847 encode_reflection_type (assembly
, mb
->rtype
, &buf
);
848 for (i
= 0; i
< nparams
; ++i
) {
849 MonoArray
*modreq
= NULL
;
850 MonoArray
*modopt
= NULL
;
851 MonoReflectionType
*pt
;
853 if (mb
->param_modreq
&& (i
< mono_array_length (mb
->param_modreq
)))
854 modreq
= mono_array_get (mb
->param_modreq
, MonoArray
*, i
);
855 if (mb
->param_modopt
&& (i
< mono_array_length (mb
->param_modopt
)))
856 modopt
= mono_array_get (mb
->param_modopt
, MonoArray
*, i
);
857 encode_custom_modifiers (assembly
, modreq
, modopt
, &buf
);
858 pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
859 encode_reflection_type (assembly
, pt
, &buf
);
862 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
863 for (i
= 0; i
< notypes
; ++i
) {
864 MonoReflectionType
*pt
;
866 pt
= mono_array_get (mb
->opt_types
, MonoReflectionType
*, i
);
867 encode_reflection_type (assembly
, pt
, &buf
);
870 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
871 sigbuffer_free (&buf
);
876 encode_locals (MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
)
878 MonoDynamicTable
*table
;
880 guint32 idx
, sig_idx
;
881 guint nl
= mono_array_length (ilgen
->locals
);
885 sigbuffer_init (&buf
, 32);
886 sigbuffer_add_value (&buf
, 0x07);
887 sigbuffer_add_value (&buf
, nl
);
888 for (i
= 0; i
< nl
; ++i
) {
889 MonoReflectionLocalBuilder
*lb
= mono_array_get (ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
892 sigbuffer_add_value (&buf
, MONO_TYPE_PINNED
);
894 encode_reflection_type (assembly
, (MonoReflectionType
*)lb
->type
, &buf
);
896 sig_idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
897 sigbuffer_free (&buf
);
899 if (assembly
->standalonesig_cache
== NULL
)
900 assembly
->standalonesig_cache
= g_hash_table_new (NULL
, NULL
);
901 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
)));
905 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
906 idx
= table
->next_idx
++;
908 alloc_table (table
, table
->rows
);
909 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
911 values
[MONO_STAND_ALONE_SIGNATURE
] = sig_idx
;
913 g_hash_table_insert (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
), GUINT_TO_POINTER (idx
));
919 method_count_clauses (MonoReflectionILGen
*ilgen
)
921 guint32 num_clauses
= 0;
924 MonoILExceptionInfo
*ex_info
;
925 for (i
= 0; i
< mono_array_length (ilgen
->ex_handlers
); ++i
) {
926 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
927 if (ex_info
->handlers
)
928 num_clauses
+= mono_array_length (ex_info
->handlers
);
936 #ifndef DISABLE_REFLECTION_EMIT
937 static MonoExceptionClause
*
938 method_encode_clauses (MonoImage
*image
, MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
, guint32 num_clauses
)
940 MonoExceptionClause
*clauses
;
941 MonoExceptionClause
*clause
;
942 MonoILExceptionInfo
*ex_info
;
943 MonoILExceptionBlock
*ex_block
;
944 guint32 finally_start
;
945 int i
, j
, clause_index
;;
947 clauses
= image_g_new0 (image
, MonoExceptionClause
, num_clauses
);
950 for (i
= mono_array_length (ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
951 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
952 finally_start
= ex_info
->start
+ ex_info
->len
;
953 if (!ex_info
->handlers
)
955 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
956 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
957 clause
= &(clauses
[clause_index
]);
959 clause
->flags
= ex_block
->type
;
960 clause
->try_offset
= ex_info
->start
;
962 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
963 clause
->try_len
= finally_start
- ex_info
->start
;
965 clause
->try_len
= ex_info
->len
;
966 clause
->handler_offset
= ex_block
->start
;
967 clause
->handler_len
= ex_block
->len
;
968 if (ex_block
->extype
) {
969 clause
->data
.catch_class
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)ex_block
->extype
));
971 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
972 clause
->data
.filter_offset
= ex_block
->filter_offset
;
974 clause
->data
.filter_offset
= 0;
976 finally_start
= ex_block
->start
+ ex_block
->len
;
984 #endif /* !DISABLE_REFLECTION_EMIT */
987 method_encode_code (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
993 gint32 num_locals
= 0;
994 gint32 num_exception
= 0;
997 char fat_header
[12];
1000 guint32 local_sig
= 0;
1001 guint32 header_size
= 12;
1004 if ((mb
->attrs
& (METHOD_ATTRIBUTE_PINVOKE_IMPL
| METHOD_ATTRIBUTE_ABSTRACT
)) ||
1005 (mb
->iattrs
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)))
1009 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
1011 code
= mb
->ilgen
->code
;
1012 code_size
= mb
->ilgen
->code_len
;
1013 max_stack
= mb
->ilgen
->max_stack
;
1014 num_locals
= mb
->ilgen
->locals
? mono_array_length (mb
->ilgen
->locals
) : 0;
1015 if (mb
->ilgen
->ex_handlers
)
1016 num_exception
= method_count_clauses (mb
->ilgen
);
1020 char *name
= mono_string_to_utf8 (mb
->name
);
1021 char *str
= g_strdup_printf ("Method %s does not have any IL associated", name
);
1022 MonoException
*exception
= mono_get_exception_argument (NULL
, "a method does not have any IL associated");
1025 mono_raise_exception (exception
);
1028 code_size
= mono_array_length (code
);
1029 max_stack
= 8; /* we probably need to run a verifier on the code... */
1032 stream_data_align (&assembly
->code
);
1034 /* check for exceptions, maxstack, locals */
1035 maybe_small
= (max_stack
<= 8) && (!num_locals
) && (!num_exception
);
1037 if (code_size
< 64 && !(code_size
& 1)) {
1038 flags
= (code_size
<< 2) | 0x2;
1039 } else if (code_size
< 32 && (code_size
& 1)) {
1040 flags
= (code_size
<< 2) | 0x6; /* LAMESPEC: see metadata.c */
1044 idx
= mono_image_add_stream_data (&assembly
->code
, &flags
, 1);
1045 /* add to the fixup todo list */
1046 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1047 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 1));
1048 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1049 return assembly
->text_rva
+ idx
;
1053 local_sig
= MONO_TOKEN_SIGNATURE
| encode_locals (assembly
, mb
->ilgen
);
1055 * FIXME: need to set also the header size in fat_flags.
1056 * (and more sects and init locals flags)
1060 fat_flags
|= METHOD_HEADER_MORE_SECTS
;
1061 if (mb
->init_locals
)
1062 fat_flags
|= METHOD_HEADER_INIT_LOCALS
;
1063 fat_header
[0] = fat_flags
;
1064 fat_header
[1] = (header_size
/ 4 ) << 4;
1065 short_value
= GUINT16_TO_LE (max_stack
);
1066 memcpy (fat_header
+ 2, &short_value
, 2);
1067 int_value
= GUINT32_TO_LE (code_size
);
1068 memcpy (fat_header
+ 4, &int_value
, 4);
1069 int_value
= GUINT32_TO_LE (local_sig
);
1070 memcpy (fat_header
+ 8, &int_value
, 4);
1071 idx
= mono_image_add_stream_data (&assembly
->code
, fat_header
, 12);
1072 /* add to the fixup todo list */
1073 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1074 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 12));
1076 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1077 if (num_exception
) {
1078 unsigned char sheader
[4];
1079 MonoILExceptionInfo
* ex_info
;
1080 MonoILExceptionBlock
* ex_block
;
1083 stream_data_align (&assembly
->code
);
1084 /* always use fat format for now */
1085 sheader
[0] = METHOD_HEADER_SECTION_FAT_FORMAT
| METHOD_HEADER_SECTION_EHTABLE
;
1086 num_exception
*= 6 * sizeof (guint32
);
1087 num_exception
+= 4; /* include the size of the header */
1088 sheader
[1] = num_exception
& 0xff;
1089 sheader
[2] = (num_exception
>> 8) & 0xff;
1090 sheader
[3] = (num_exception
>> 16) & 0xff;
1091 mono_image_add_stream_data (&assembly
->code
, (char*)sheader
, 4);
1092 /* fat header, so we are already aligned */
1094 for (i
= mono_array_length (mb
->ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
1095 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (mb
->ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
1096 if (ex_info
->handlers
) {
1097 int finally_start
= ex_info
->start
+ ex_info
->len
;
1098 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
1100 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
1102 val
= GUINT32_TO_LE (ex_block
->type
);
1103 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1105 val
= GUINT32_TO_LE (ex_info
->start
);
1106 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1107 /* need fault, too, probably */
1108 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
1109 val
= GUINT32_TO_LE (finally_start
- ex_info
->start
);
1111 val
= GUINT32_TO_LE (ex_info
->len
);
1112 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1113 /* handler offset */
1114 val
= GUINT32_TO_LE (ex_block
->start
);
1115 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1117 val
= GUINT32_TO_LE (ex_block
->len
);
1118 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1119 finally_start
= ex_block
->start
+ ex_block
->len
;
1120 if (ex_block
->extype
) {
1121 val
= mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)ex_block
->extype
)));
1123 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
1124 val
= ex_block
->filter_offset
;
1128 val
= GUINT32_TO_LE (val
);
1129 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1130 /*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",
1131 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);*/
1134 g_error ("No clauses for ex info block %d", i
);
1138 return assembly
->text_rva
+ idx
;
1142 find_index_in_table (MonoDynamicImage
*assembly
, int table_idx
, int col
, guint32 token
)
1145 MonoDynamicTable
*table
;
1148 table
= &assembly
->tables
[table_idx
];
1150 g_assert (col
< table
->columns
);
1152 values
= table
->values
+ table
->columns
;
1153 for (i
= 1; i
<= table
->rows
; ++i
) {
1154 if (values
[col
] == token
)
1156 values
+= table
->columns
;
1162 * LOCKING: Acquires the loader lock.
1164 static MonoCustomAttrInfo
*
1165 lookup_custom_attr (MonoImage
*image
, gpointer member
)
1167 MonoCustomAttrInfo
* res
;
1169 res
= mono_image_property_lookup (image
, member
, MONO_PROP_DYNAMIC_CATTR
);
1174 return g_memdup (res
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * res
->num_attrs
);
1178 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttr
*cattr
)
1180 /* FIXME: Need to do more checks */
1181 if (cattr
->ctor
->method
&& (cattr
->ctor
->method
->klass
->image
!= image
)) {
1182 int visibility
= cattr
->ctor
->method
->klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
1184 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
1191 static MonoCustomAttrInfo
*
1192 mono_custom_attrs_from_builders (MonoImage
*alloc_img
, MonoImage
*image
, MonoArray
*cattrs
)
1194 int i
, index
, count
, not_visible
;
1195 MonoCustomAttrInfo
*ainfo
;
1196 MonoReflectionCustomAttr
*cattr
;
1200 /* FIXME: check in assembly the Run flag is set */
1202 count
= mono_array_length (cattrs
);
1204 /* Skip nonpublic attributes since MS.NET seems to do the same */
1205 /* FIXME: This needs to be done more globally */
1207 for (i
= 0; i
< count
; ++i
) {
1208 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1209 if (!custom_attr_visible (image
, cattr
))
1212 count
-= not_visible
;
1214 ainfo
= image_g_malloc0 (alloc_img
, MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * count
);
1216 ainfo
->image
= image
;
1217 ainfo
->num_attrs
= count
;
1218 ainfo
->cached
= alloc_img
!= NULL
;
1220 for (i
= 0; i
< count
; ++i
) {
1221 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1222 if (custom_attr_visible (image
, cattr
)) {
1223 unsigned char *saved
= mono_image_alloc (image
, mono_array_length (cattr
->data
));
1224 memcpy (saved
, mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1225 ainfo
->attrs
[index
].ctor
= cattr
->ctor
->method
;
1226 ainfo
->attrs
[index
].data
= saved
;
1227 ainfo
->attrs
[index
].data_size
= mono_array_length (cattr
->data
);
1235 #ifndef DISABLE_REFLECTION_EMIT
1237 * LOCKING: Acquires the loader lock.
1240 mono_save_custom_attrs (MonoImage
*image
, void *obj
, MonoArray
*cattrs
)
1242 MonoCustomAttrInfo
*ainfo
, *tmp
;
1244 if (!cattrs
|| !mono_array_length (cattrs
))
1247 ainfo
= mono_custom_attrs_from_builders (image
, image
, cattrs
);
1249 mono_loader_lock ();
1250 tmp
= mono_image_property_lookup (image
, obj
, MONO_PROP_DYNAMIC_CATTR
);
1252 mono_custom_attrs_free (tmp
);
1253 mono_image_property_insert (image
, obj
, MONO_PROP_DYNAMIC_CATTR
, ainfo
);
1254 mono_loader_unlock ();
1260 mono_custom_attrs_free (MonoCustomAttrInfo
*ainfo
)
1267 * idx is the table index of the object
1268 * type is one of MONO_CUSTOM_ATTR_*
1271 mono_image_add_cattrs (MonoDynamicImage
*assembly
, guint32 idx
, guint32 type
, MonoArray
*cattrs
)
1273 MonoDynamicTable
*table
;
1274 MonoReflectionCustomAttr
*cattr
;
1276 guint32 count
, i
, token
;
1278 char *p
= blob_size
;
1280 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1283 count
= mono_array_length (cattrs
);
1284 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1285 table
->rows
+= count
;
1286 alloc_table (table
, table
->rows
);
1287 values
= table
->values
+ table
->next_idx
* MONO_CUSTOM_ATTR_SIZE
;
1288 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1290 for (i
= 0; i
< count
; ++i
) {
1291 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1292 values
[MONO_CUSTOM_ATTR_PARENT
] = idx
;
1293 token
= mono_image_create_token (assembly
, (MonoObject
*)cattr
->ctor
, FALSE
, FALSE
);
1294 type
= mono_metadata_token_index (token
);
1295 type
<<= MONO_CUSTOM_ATTR_TYPE_BITS
;
1296 switch (mono_metadata_token_table (token
)) {
1297 case MONO_TABLE_METHOD
:
1298 type
|= MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
1300 case MONO_TABLE_MEMBERREF
:
1301 type
|= MONO_CUSTOM_ATTR_TYPE_MEMBERREF
;
1304 g_warning ("got wrong token in custom attr");
1307 values
[MONO_CUSTOM_ATTR_TYPE
] = type
;
1309 mono_metadata_encode_value (mono_array_length (cattr
->data
), p
, &p
);
1310 values
[MONO_CUSTOM_ATTR_VALUE
] = add_to_blob_cached (assembly
, blob_size
, p
- blob_size
,
1311 mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1312 values
+= MONO_CUSTOM_ATTR_SIZE
;
1318 mono_image_add_decl_security (MonoDynamicImage
*assembly
, guint32 parent_token
, MonoArray
*permissions
)
1320 MonoDynamicTable
*table
;
1322 guint32 count
, i
, idx
;
1323 MonoReflectionPermissionSet
*perm
;
1328 count
= mono_array_length (permissions
);
1329 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
1330 table
->rows
+= count
;
1331 alloc_table (table
, table
->rows
);
1333 for (i
= 0; i
< mono_array_length (permissions
); ++i
) {
1334 perm
= (MonoReflectionPermissionSet
*)mono_array_addr (permissions
, MonoReflectionPermissionSet
, i
);
1336 values
= table
->values
+ table
->next_idx
* MONO_DECL_SECURITY_SIZE
;
1338 idx
= mono_metadata_token_index (parent_token
);
1339 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
1340 switch (mono_metadata_token_table (parent_token
)) {
1341 case MONO_TABLE_TYPEDEF
:
1342 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
1344 case MONO_TABLE_METHOD
:
1345 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
1347 case MONO_TABLE_ASSEMBLY
:
1348 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
1351 g_assert_not_reached ();
1354 values
[MONO_DECL_SECURITY_ACTION
] = perm
->action
;
1355 values
[MONO_DECL_SECURITY_PARENT
] = idx
;
1356 values
[MONO_DECL_SECURITY_PERMISSIONSET
] = add_mono_string_to_blob_cached (assembly
, perm
->pset
);
1363 * Fill in the MethodDef and ParamDef tables for a method.
1364 * This is used for both normal methods and constructors.
1367 mono_image_basic_method (ReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1369 MonoDynamicTable
*table
;
1373 /* room in this table is already allocated */
1374 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
1375 *mb
->table_idx
= table
->next_idx
++;
1376 g_hash_table_insert (assembly
->method_to_table_idx
, mb
->mhandle
, GUINT_TO_POINTER ((*mb
->table_idx
)));
1377 values
= table
->values
+ *mb
->table_idx
* MONO_METHOD_SIZE
;
1378 values
[MONO_METHOD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1379 values
[MONO_METHOD_FLAGS
] = mb
->attrs
;
1380 values
[MONO_METHOD_IMPLFLAGS
] = mb
->iattrs
;
1381 values
[MONO_METHOD_SIGNATURE
] = method_builder_encode_signature (assembly
, mb
);
1382 values
[MONO_METHOD_RVA
] = method_encode_code (assembly
, mb
);
1384 table
= &assembly
->tables
[MONO_TABLE_PARAM
];
1385 values
[MONO_METHOD_PARAMLIST
] = table
->next_idx
;
1387 mono_image_add_decl_security (assembly
,
1388 mono_metadata_make_token (MONO_TABLE_METHOD
, *mb
->table_idx
), mb
->permissions
);
1391 MonoDynamicTable
*mtable
;
1394 mtable
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1395 mvalues
= mtable
->values
+ mtable
->next_idx
* MONO_FIELD_MARSHAL_SIZE
;
1398 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1399 if (mono_array_get (mb
->pinfo
, gpointer
, i
))
1402 table
->rows
+= count
;
1403 alloc_table (table
, table
->rows
);
1404 values
= table
->values
+ table
->next_idx
* MONO_PARAM_SIZE
;
1405 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1406 MonoReflectionParamBuilder
*pb
;
1407 if ((pb
= mono_array_get (mb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
1408 values
[MONO_PARAM_FLAGS
] = pb
->attrs
;
1409 values
[MONO_PARAM_SEQUENCE
] = i
;
1410 if (pb
->name
!= NULL
) {
1411 values
[MONO_PARAM_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1413 values
[MONO_PARAM_NAME
] = 0;
1415 values
+= MONO_PARAM_SIZE
;
1416 if (pb
->marshal_info
) {
1418 alloc_table (mtable
, mtable
->rows
);
1419 mvalues
= mtable
->values
+ mtable
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1420 mvalues
[MONO_FIELD_MARSHAL_PARENT
] = (table
->next_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_PARAMDEF
;
1421 mvalues
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, pb
->marshal_info
);
1423 pb
->table_idx
= table
->next_idx
++;
1424 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
1425 guint32 field_type
= 0;
1426 mtable
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1428 alloc_table (mtable
, mtable
->rows
);
1429 mvalues
= mtable
->values
+ mtable
->rows
* MONO_CONSTANT_SIZE
;
1430 mvalues
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_PARAM
| (pb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1431 mvalues
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, pb
->def_value
, &field_type
);
1432 mvalues
[MONO_CONSTANT_TYPE
] = field_type
;
1433 mvalues
[MONO_CONSTANT_PADDING
] = 0;
1440 #ifndef DISABLE_REFLECTION_EMIT
1442 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
)
1444 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1446 rmb
->ilgen
= mb
->ilgen
;
1447 rmb
->rtype
= mono_reflection_type_resolve_user_types ((MonoReflectionType
*)mb
->rtype
);
1448 rmb
->parameters
= mb
->parameters
;
1449 rmb
->generic_params
= mb
->generic_params
;
1450 rmb
->generic_container
= mb
->generic_container
;
1451 rmb
->opt_types
= NULL
;
1452 rmb
->pinfo
= mb
->pinfo
;
1453 rmb
->attrs
= mb
->attrs
;
1454 rmb
->iattrs
= mb
->iattrs
;
1455 rmb
->call_conv
= mb
->call_conv
;
1456 rmb
->code
= mb
->code
;
1457 rmb
->type
= mb
->type
;
1458 rmb
->name
= mb
->name
;
1459 rmb
->table_idx
= &mb
->table_idx
;
1460 rmb
->init_locals
= mb
->init_locals
;
1461 rmb
->skip_visibility
= FALSE
;
1462 rmb
->return_modreq
= mb
->return_modreq
;
1463 rmb
->return_modopt
= mb
->return_modopt
;
1464 rmb
->param_modreq
= mb
->param_modreq
;
1465 rmb
->param_modopt
= mb
->param_modopt
;
1466 rmb
->permissions
= mb
->permissions
;
1467 rmb
->mhandle
= mb
->mhandle
;
1472 rmb
->charset
= mb
->charset
;
1473 rmb
->extra_flags
= mb
->extra_flags
;
1474 rmb
->native_cc
= mb
->native_cc
;
1475 rmb
->dllentry
= mb
->dllentry
;
1481 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
)
1483 const char *name
= mb
->attrs
& METHOD_ATTRIBUTE_STATIC
? ".cctor": ".ctor";
1485 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1487 rmb
->ilgen
= mb
->ilgen
;
1488 rmb
->rtype
= mono_type_get_object (mono_domain_get (), &mono_defaults
.void_class
->byval_arg
);
1489 rmb
->parameters
= mb
->parameters
;
1490 rmb
->generic_params
= NULL
;
1491 rmb
->generic_container
= NULL
;
1492 rmb
->opt_types
= NULL
;
1493 rmb
->pinfo
= mb
->pinfo
;
1494 rmb
->attrs
= mb
->attrs
;
1495 rmb
->iattrs
= mb
->iattrs
;
1496 rmb
->call_conv
= mb
->call_conv
;
1498 rmb
->type
= mb
->type
;
1499 rmb
->name
= mono_string_new (mono_domain_get (), name
);
1500 rmb
->table_idx
= &mb
->table_idx
;
1501 rmb
->init_locals
= mb
->init_locals
;
1502 rmb
->skip_visibility
= FALSE
;
1503 rmb
->return_modreq
= NULL
;
1504 rmb
->return_modopt
= NULL
;
1505 rmb
->param_modreq
= mb
->param_modreq
;
1506 rmb
->param_modopt
= mb
->param_modopt
;
1507 rmb
->permissions
= mb
->permissions
;
1508 rmb
->mhandle
= mb
->mhandle
;
1514 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder
*rmb
, MonoReflectionDynamicMethod
*mb
)
1516 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1518 rmb
->ilgen
= mb
->ilgen
;
1519 rmb
->rtype
= mb
->rtype
;
1520 rmb
->parameters
= mb
->parameters
;
1521 rmb
->generic_params
= NULL
;
1522 rmb
->generic_container
= NULL
;
1523 rmb
->opt_types
= NULL
;
1525 rmb
->attrs
= mb
->attrs
;
1527 rmb
->call_conv
= mb
->call_conv
;
1529 rmb
->type
= (MonoObject
*) mb
->owner
;
1530 rmb
->name
= mb
->name
;
1531 rmb
->table_idx
= NULL
;
1532 rmb
->init_locals
= mb
->init_locals
;
1533 rmb
->skip_visibility
= mb
->skip_visibility
;
1534 rmb
->return_modreq
= NULL
;
1535 rmb
->return_modopt
= NULL
;
1536 rmb
->param_modreq
= NULL
;
1537 rmb
->param_modopt
= NULL
;
1538 rmb
->permissions
= NULL
;
1539 rmb
->mhandle
= mb
->mhandle
;
1546 mono_image_add_methodimpl (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
1548 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
1549 MonoDynamicTable
*table
;
1553 if (!mb
->override_method
)
1556 table
= &assembly
->tables
[MONO_TABLE_METHODIMPL
];
1558 alloc_table (table
, table
->rows
);
1559 values
= table
->values
+ table
->rows
* MONO_METHODIMPL_SIZE
;
1560 values
[MONO_METHODIMPL_CLASS
] = tb
->table_idx
;
1561 values
[MONO_METHODIMPL_BODY
] = MONO_METHODDEFORREF_METHODDEF
| (mb
->table_idx
<< MONO_METHODDEFORREF_BITS
);
1563 tok
= mono_image_create_token (assembly
, (MonoObject
*)mb
->override_method
, FALSE
, FALSE
);
1564 switch (mono_metadata_token_table (tok
)) {
1565 case MONO_TABLE_MEMBERREF
:
1566 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
1568 case MONO_TABLE_METHOD
:
1569 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
1572 g_assert_not_reached ();
1574 values
[MONO_METHODIMPL_DECLARATION
] = tok
;
1577 #ifndef DISABLE_REFLECTION_EMIT
1579 mono_image_get_method_info (MonoReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1581 MonoDynamicTable
*table
;
1583 ReflectionMethodBuilder rmb
;
1586 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
1588 mono_image_basic_method (&rmb
, assembly
);
1589 mb
->table_idx
= *rmb
.table_idx
;
1591 if (mb
->dll
) { /* It's a P/Invoke method */
1593 /* map CharSet values to on-disk values */
1594 int ncharset
= (mb
->charset
? (mb
->charset
- 1) * 2 : 0);
1595 int extra_flags
= mb
->extra_flags
;
1596 table
= &assembly
->tables
[MONO_TABLE_IMPLMAP
];
1598 alloc_table (table
, table
->rows
);
1599 values
= table
->values
+ table
->rows
* MONO_IMPLMAP_SIZE
;
1601 values
[MONO_IMPLMAP_FLAGS
] = (mb
->native_cc
<< 8) | ncharset
| extra_flags
;
1602 values
[MONO_IMPLMAP_MEMBER
] = (mb
->table_idx
<< 1) | 1; /* memberforwarded: method */
1604 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->dllentry
);
1606 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1607 moduleref
= string_heap_insert_mstring (&assembly
->sheap
, mb
->dll
);
1608 if (!(values
[MONO_IMPLMAP_SCOPE
] = find_index_in_table (assembly
, MONO_TABLE_MODULEREF
, MONO_MODULEREF_NAME
, moduleref
))) {
1609 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
1611 alloc_table (table
, table
->rows
);
1612 table
->values
[table
->rows
* MONO_MODULEREF_SIZE
+ MONO_MODULEREF_NAME
] = moduleref
;
1613 values
[MONO_IMPLMAP_SCOPE
] = table
->rows
;
1617 if (mb
->generic_params
) {
1618 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
1619 table
->rows
+= mono_array_length (mb
->generic_params
);
1620 alloc_table (table
, table
->rows
);
1621 for (i
= 0; i
< mono_array_length (mb
->generic_params
); ++i
) {
1622 guint32 owner
= MONO_TYPEORMETHOD_METHOD
| (mb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
1624 mono_image_get_generic_param_info (
1625 mono_array_get (mb
->generic_params
, gpointer
, i
), owner
, assembly
);
1632 mono_image_get_ctor_info (MonoDomain
*domain
, MonoReflectionCtorBuilder
*mb
, MonoDynamicImage
*assembly
)
1634 ReflectionMethodBuilder rmb
;
1636 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
1638 mono_image_basic_method (&rmb
, assembly
);
1639 mb
->table_idx
= *rmb
.table_idx
;
1644 type_get_fully_qualified_name (MonoType
*type
)
1646 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1650 type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
) {
1654 klass
= mono_class_from_mono_type (type
);
1656 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1657 ta
= klass
->image
->assembly
;
1658 if (ta
->dynamic
|| (ta
== ass
)) {
1659 if (klass
->generic_class
|| klass
->generic_container
)
1660 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1661 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_FULL_NAME
);
1663 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1666 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1669 #ifndef DISABLE_REFLECTION_EMIT
1670 /*field_image is the image to which the eventual custom mods have been encoded against*/
1672 fieldref_encode_signature (MonoDynamicImage
*assembly
, MonoImage
*field_image
, MonoType
*type
)
1675 guint32 idx
, i
, token
;
1677 if (!assembly
->save
)
1680 sigbuffer_init (&buf
, 32);
1682 sigbuffer_add_value (&buf
, 0x06);
1683 /* encode custom attributes before the type */
1684 if (type
->num_mods
) {
1685 for (i
= 0; i
< type
->num_mods
; ++i
) {
1687 MonoClass
*class = mono_class_get (field_image
, type
->modifiers
[i
].token
);
1689 token
= mono_image_typedef_or_ref (assembly
, &class->byval_arg
);
1691 token
= type
->modifiers
[i
].token
;
1694 if (type
->modifiers
[i
].required
)
1695 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_REQD
);
1697 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_OPT
);
1699 sigbuffer_add_value (&buf
, token
);
1702 encode_type (assembly
, type
, &buf
);
1703 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1704 sigbuffer_free (&buf
);
1710 field_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
1715 sigbuffer_init (&buf
, 32);
1717 sigbuffer_add_value (&buf
, 0x06);
1718 encode_custom_modifiers (assembly
, fb
->modreq
, fb
->modopt
, &buf
);
1719 /* encode custom attributes before the type */
1720 encode_reflection_type (assembly
, (MonoReflectionType
*)fb
->type
, &buf
);
1721 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1722 sigbuffer_free (&buf
);
1727 encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
) {
1728 char blob_size
[64];
1729 char *b
= blob_size
;
1732 guint32 idx
= 0, len
= 0, dummy
= 0;
1734 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1735 guint32 fpa_double
[2];
1740 p
= buf
= g_malloc (64);
1742 *ret_type
= MONO_TYPE_CLASS
;
1744 box_val
= (char*)&dummy
;
1746 box_val
= ((char*)val
) + sizeof (MonoObject
);
1747 *ret_type
= val
->vtable
->klass
->byval_arg
.type
;
1750 switch (*ret_type
) {
1751 case MONO_TYPE_BOOLEAN
:
1756 case MONO_TYPE_CHAR
:
1773 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1774 fpa_p
= (guint32
*)box_val
;
1775 fpa_double
[0] = fpa_p
[1];
1776 fpa_double
[1] = fpa_p
[0];
1777 box_val
= (char*)fpa_double
;
1781 case MONO_TYPE_VALUETYPE
:
1782 if (val
->vtable
->klass
->enumtype
) {
1783 *ret_type
= mono_class_enum_basetype (val
->vtable
->klass
)->type
;
1786 g_error ("we can't encode valuetypes");
1787 case MONO_TYPE_CLASS
:
1789 case MONO_TYPE_STRING
: {
1790 MonoString
*str
= (MonoString
*)val
;
1791 /* there is no signature */
1792 len
= str
->length
* 2;
1793 mono_metadata_encode_value (len
, b
, &b
);
1794 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1796 char *swapped
= g_malloc (2 * mono_string_length (str
));
1797 const char *p
= (const char*)mono_string_chars (str
);
1799 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
1800 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
1804 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
1810 case MONO_TYPE_GENERICINST
:
1811 *ret_type
= val
->vtable
->klass
->generic_class
->container_class
->byval_arg
.type
;
1814 g_error ("we don't encode constant type 0x%02x yet", *ret_type
);
1817 /* there is no signature */
1818 mono_metadata_encode_value (len
, b
, &b
);
1819 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1820 idx
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
1821 swap_with_size (blob_size
, box_val
, len
, 1);
1822 mono_image_add_stream_data (&assembly
->blob
, blob_size
, len
);
1824 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, box_val
, len
);
1832 encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
) {
1837 sigbuffer_init (&buf
, 32);
1839 sigbuffer_add_value (&buf
, minfo
->type
);
1841 switch (minfo
->type
) {
1842 case MONO_NATIVE_BYVALTSTR
:
1843 case MONO_NATIVE_BYVALARRAY
:
1844 sigbuffer_add_value (&buf
, minfo
->count
);
1846 case MONO_NATIVE_LPARRAY
:
1847 if (minfo
->eltype
|| minfo
->has_size
) {
1848 sigbuffer_add_value (&buf
, minfo
->eltype
);
1849 if (minfo
->has_size
) {
1850 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? minfo
->param_num
: 0);
1851 sigbuffer_add_value (&buf
, minfo
->count
!= -1? minfo
->count
: 0);
1853 /* LAMESPEC: ElemMult is undocumented */
1854 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? 1: 0);
1858 case MONO_NATIVE_SAFEARRAY
:
1860 sigbuffer_add_value (&buf
, minfo
->eltype
);
1862 case MONO_NATIVE_CUSTOM
:
1864 str
= mono_string_to_utf8 (minfo
->guid
);
1866 sigbuffer_add_value (&buf
, len
);
1867 sigbuffer_add_mem (&buf
, str
, len
);
1870 sigbuffer_add_value (&buf
, 0);
1872 /* native type name */
1873 sigbuffer_add_value (&buf
, 0);
1874 /* custom marshaler type name */
1875 if (minfo
->marshaltype
|| minfo
->marshaltyperef
) {
1876 if (minfo
->marshaltyperef
)
1877 str
= type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType
*)minfo
->marshaltyperef
));
1879 str
= mono_string_to_utf8 (minfo
->marshaltype
);
1881 sigbuffer_add_value (&buf
, len
);
1882 sigbuffer_add_mem (&buf
, str
, len
);
1885 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1886 sigbuffer_add_value (&buf
, 0);
1888 if (minfo
->mcookie
) {
1889 str
= mono_string_to_utf8 (minfo
->mcookie
);
1891 sigbuffer_add_value (&buf
, len
);
1892 sigbuffer_add_mem (&buf
, str
, len
);
1895 sigbuffer_add_value (&buf
, 0);
1901 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1902 sigbuffer_free (&buf
);
1907 mono_image_get_field_info (MonoReflectionFieldBuilder
*fb
, MonoDynamicImage
*assembly
)
1909 MonoDynamicTable
*table
;
1912 /* maybe this fixup should be done in the C# code */
1913 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
)
1914 fb
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
1915 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
1916 fb
->table_idx
= table
->next_idx
++;
1917 g_hash_table_insert (assembly
->field_to_table_idx
, fb
->handle
, GUINT_TO_POINTER (fb
->table_idx
));
1918 values
= table
->values
+ fb
->table_idx
* MONO_FIELD_SIZE
;
1919 values
[MONO_FIELD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, fb
->name
);
1920 values
[MONO_FIELD_FLAGS
] = fb
->attrs
;
1921 values
[MONO_FIELD_SIGNATURE
] = field_encode_signature (assembly
, fb
);
1923 if (fb
->offset
!= -1) {
1924 table
= &assembly
->tables
[MONO_TABLE_FIELDLAYOUT
];
1926 alloc_table (table
, table
->rows
);
1927 values
= table
->values
+ table
->rows
* MONO_FIELD_LAYOUT_SIZE
;
1928 values
[MONO_FIELD_LAYOUT_FIELD
] = fb
->table_idx
;
1929 values
[MONO_FIELD_LAYOUT_OFFSET
] = fb
->offset
;
1931 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
) {
1932 guint32 field_type
= 0;
1933 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1935 alloc_table (table
, table
->rows
);
1936 values
= table
->values
+ table
->rows
* MONO_CONSTANT_SIZE
;
1937 values
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_FIEDDEF
| (fb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1938 values
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, fb
->def_value
, &field_type
);
1939 values
[MONO_CONSTANT_TYPE
] = field_type
;
1940 values
[MONO_CONSTANT_PADDING
] = 0;
1942 if (fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
1944 table
= &assembly
->tables
[MONO_TABLE_FIELDRVA
];
1946 alloc_table (table
, table
->rows
);
1947 values
= table
->values
+ table
->rows
* MONO_FIELD_RVA_SIZE
;
1948 values
[MONO_FIELD_RVA_FIELD
] = fb
->table_idx
;
1950 * We store it in the code section because it's simpler for now.
1953 if (mono_array_length (fb
->rva_data
) >= 10)
1954 stream_data_align (&assembly
->code
);
1955 rva_idx
= mono_image_add_stream_data (&assembly
->code
, mono_array_addr (fb
->rva_data
, char, 0), mono_array_length (fb
->rva_data
));
1957 rva_idx
= mono_image_add_stream_zero (&assembly
->code
, mono_class_value_size (fb
->handle
->parent
, NULL
));
1958 values
[MONO_FIELD_RVA_RVA
] = rva_idx
+ assembly
->text_rva
;
1960 if (fb
->marshal_info
) {
1961 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1963 alloc_table (table
, table
->rows
);
1964 values
= table
->values
+ table
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1965 values
[MONO_FIELD_MARSHAL_PARENT
] = (fb
->table_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_FIELDSREF
;
1966 values
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, fb
->marshal_info
);
1971 property_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionPropertyBuilder
*fb
)
1974 guint32 nparams
= 0;
1975 MonoReflectionMethodBuilder
*mb
= fb
->get_method
;
1976 MonoReflectionMethodBuilder
*smb
= fb
->set_method
;
1979 if (mb
&& mb
->parameters
)
1980 nparams
= mono_array_length (mb
->parameters
);
1981 if (!mb
&& smb
&& smb
->parameters
)
1982 nparams
= mono_array_length (smb
->parameters
) - 1;
1983 sigbuffer_init (&buf
, 32);
1984 sigbuffer_add_byte (&buf
, 0x08);
1985 sigbuffer_add_value (&buf
, nparams
);
1987 encode_reflection_type (assembly
, (MonoReflectionType
*)mb
->rtype
, &buf
);
1988 for (i
= 0; i
< nparams
; ++i
) {
1989 MonoReflectionType
*pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
1990 encode_reflection_type (assembly
, pt
, &buf
);
1992 } else if (smb
&& smb
->parameters
) {
1993 /* the property type is the last param */
1994 encode_reflection_type (assembly
, mono_array_get (smb
->parameters
, MonoReflectionType
*, nparams
), &buf
);
1995 for (i
= 0; i
< nparams
; ++i
) {
1996 MonoReflectionType
*pt
= mono_array_get (smb
->parameters
, MonoReflectionType
*, i
);
1997 encode_reflection_type (assembly
, pt
, &buf
);
2000 encode_reflection_type (assembly
, (MonoReflectionType
*)fb
->type
, &buf
);
2003 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2004 sigbuffer_free (&buf
);
2009 mono_image_get_property_info (MonoReflectionPropertyBuilder
*pb
, MonoDynamicImage
*assembly
)
2011 MonoDynamicTable
*table
;
2013 guint num_methods
= 0;
2017 * we need to set things in the following tables:
2018 * PROPERTYMAP (info already filled in _get_type_info ())
2019 * PROPERTY (rows already preallocated in _get_type_info ())
2020 * METHOD (method info already done with the generic method code)
2024 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
2025 pb
->table_idx
= table
->next_idx
++;
2026 values
= table
->values
+ pb
->table_idx
* MONO_PROPERTY_SIZE
;
2027 values
[MONO_PROPERTY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
2028 values
[MONO_PROPERTY_FLAGS
] = pb
->attrs
;
2029 values
[MONO_PROPERTY_TYPE
] = property_encode_signature (assembly
, pb
);
2031 /* FIXME: we still don't handle 'other' methods */
2032 if (pb
->get_method
) num_methods
++;
2033 if (pb
->set_method
) num_methods
++;
2035 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
2036 table
->rows
+= num_methods
;
2037 alloc_table (table
, table
->rows
);
2039 if (pb
->get_method
) {
2040 semaidx
= table
->next_idx
++;
2041 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2042 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_GETTER
;
2043 values
[MONO_METHOD_SEMA_METHOD
] = pb
->get_method
->table_idx
;
2044 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
2046 if (pb
->set_method
) {
2047 semaidx
= table
->next_idx
++;
2048 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2049 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_SETTER
;
2050 values
[MONO_METHOD_SEMA_METHOD
] = pb
->set_method
->table_idx
;
2051 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
2053 if (pb
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
) {
2054 guint32 field_type
= 0;
2055 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
2057 alloc_table (table
, table
->rows
);
2058 values
= table
->values
+ table
->rows
* MONO_CONSTANT_SIZE
;
2059 values
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_PROPERTY
| (pb
->table_idx
<< MONO_HASCONSTANT_BITS
);
2060 values
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, pb
->def_value
, &field_type
);
2061 values
[MONO_CONSTANT_TYPE
] = field_type
;
2062 values
[MONO_CONSTANT_PADDING
] = 0;
2067 mono_image_get_event_info (MonoReflectionEventBuilder
*eb
, MonoDynamicImage
*assembly
)
2069 MonoDynamicTable
*table
;
2071 guint num_methods
= 0;
2075 * we need to set things in the following tables:
2076 * EVENTMAP (info already filled in _get_type_info ())
2077 * EVENT (rows already preallocated in _get_type_info ())
2078 * METHOD (method info already done with the generic method code)
2081 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
2082 eb
->table_idx
= table
->next_idx
++;
2083 values
= table
->values
+ eb
->table_idx
* MONO_EVENT_SIZE
;
2084 values
[MONO_EVENT_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, eb
->name
);
2085 values
[MONO_EVENT_FLAGS
] = eb
->attrs
;
2086 values
[MONO_EVENT_TYPE
] = mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle (eb
->type
));
2089 * FIXME: we still don't handle 'other' methods
2091 if (eb
->add_method
) num_methods
++;
2092 if (eb
->remove_method
) num_methods
++;
2093 if (eb
->raise_method
) num_methods
++;
2095 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
2096 table
->rows
+= num_methods
;
2097 alloc_table (table
, table
->rows
);
2099 if (eb
->add_method
) {
2100 semaidx
= table
->next_idx
++;
2101 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2102 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_ADD_ON
;
2103 values
[MONO_METHOD_SEMA_METHOD
] = eb
->add_method
->table_idx
;
2104 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2106 if (eb
->remove_method
) {
2107 semaidx
= table
->next_idx
++;
2108 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2109 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_REMOVE_ON
;
2110 values
[MONO_METHOD_SEMA_METHOD
] = eb
->remove_method
->table_idx
;
2111 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2113 if (eb
->raise_method
) {
2114 semaidx
= table
->next_idx
++;
2115 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2116 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_FIRE
;
2117 values
[MONO_METHOD_SEMA_METHOD
] = eb
->raise_method
->table_idx
;
2118 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2123 encode_constraints (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2125 MonoDynamicTable
*table
;
2126 guint32 num_constraints
, i
;
2130 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
2131 num_constraints
= gparam
->iface_constraints
?
2132 mono_array_length (gparam
->iface_constraints
) : 0;
2133 table
->rows
+= num_constraints
;
2134 if (gparam
->base_type
)
2136 alloc_table (table
, table
->rows
);
2138 if (gparam
->base_type
) {
2139 table_idx
= table
->next_idx
++;
2140 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2142 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2143 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2144 assembly
, mono_reflection_type_get_handle (gparam
->base_type
));
2147 for (i
= 0; i
< num_constraints
; i
++) {
2148 MonoReflectionType
*constraint
= mono_array_get (
2149 gparam
->iface_constraints
, gpointer
, i
);
2151 table_idx
= table
->next_idx
++;
2152 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2154 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2155 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2156 assembly
, mono_reflection_type_get_handle (constraint
));
2161 mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2163 GenericParamTableEntry
*entry
;
2166 * The GenericParam table must be sorted according to the `owner' field.
2167 * We need to do this sorting prior to writing the GenericParamConstraint
2168 * table, since we have to use the final GenericParam table indices there
2169 * and they must also be sorted.
2172 entry
= g_new0 (GenericParamTableEntry
, 1);
2173 entry
->owner
= owner
;
2174 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2175 MOVING_GC_REGISTER (&entry
->gparam
);
2176 entry
->gparam
= gparam
;
2178 g_ptr_array_add (assembly
->gen_params
, entry
);
2182 write_generic_param_entry (MonoDynamicImage
*assembly
, GenericParamTableEntry
*entry
)
2184 MonoDynamicTable
*table
;
2185 MonoGenericParam
*param
;
2189 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
2190 table_idx
= table
->next_idx
++;
2191 values
= table
->values
+ table_idx
* MONO_GENERICPARAM_SIZE
;
2193 param
= mono_reflection_type_get_handle ((MonoReflectionType
*)entry
->gparam
)->data
.generic_param
;
2195 values
[MONO_GENERICPARAM_OWNER
] = entry
->owner
;
2196 values
[MONO_GENERICPARAM_FLAGS
] = entry
->gparam
->attrs
;
2197 values
[MONO_GENERICPARAM_NUMBER
] = mono_generic_param_num (param
);
2198 values
[MONO_GENERICPARAM_NAME
] = string_heap_insert (&assembly
->sheap
, mono_generic_param_info (param
)->name
);
2200 mono_image_add_cattrs (assembly
, table_idx
, MONO_CUSTOM_ATTR_GENERICPAR
, entry
->gparam
->cattrs
);
2202 encode_constraints (entry
->gparam
, table_idx
, assembly
);
2206 resolution_scope_from_image (MonoDynamicImage
*assembly
, MonoImage
*image
)
2208 MonoDynamicTable
*table
;
2211 guint32 cols
[MONO_ASSEMBLY_SIZE
];
2215 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, image
))))
2218 if (image
->assembly
->dynamic
&& (image
->assembly
== assembly
->image
.assembly
)) {
2219 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
2220 token
= table
->next_idx
++;
2222 alloc_table (table
, table
->rows
);
2223 values
= table
->values
+ token
* MONO_MODULEREF_SIZE
;
2224 values
[MONO_MODULEREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->module_name
);
2226 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2227 token
|= MONO_RESOLTION_SCOPE_MODULEREF
;
2228 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2233 if (image
->assembly
->dynamic
)
2235 memset (cols
, 0, sizeof (cols
));
2237 /* image->assembly->image is the manifest module */
2238 image
= image
->assembly
->image
;
2239 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_ASSEMBLY
], 0, cols
, MONO_ASSEMBLY_SIZE
);
2242 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLYREF
];
2243 token
= table
->next_idx
++;
2245 alloc_table (table
, table
->rows
);
2246 values
= table
->values
+ token
* MONO_ASSEMBLYREF_SIZE
;
2247 values
[MONO_ASSEMBLYREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->assembly_name
);
2248 values
[MONO_ASSEMBLYREF_MAJOR_VERSION
] = cols
[MONO_ASSEMBLY_MAJOR_VERSION
];
2249 values
[MONO_ASSEMBLYREF_MINOR_VERSION
] = cols
[MONO_ASSEMBLY_MINOR_VERSION
];
2250 values
[MONO_ASSEMBLYREF_BUILD_NUMBER
] = cols
[MONO_ASSEMBLY_BUILD_NUMBER
];
2251 values
[MONO_ASSEMBLYREF_REV_NUMBER
] = cols
[MONO_ASSEMBLY_REV_NUMBER
];
2252 values
[MONO_ASSEMBLYREF_FLAGS
] = 0;
2253 values
[MONO_ASSEMBLYREF_CULTURE
] = 0;
2254 values
[MONO_ASSEMBLYREF_HASH_VALUE
] = 0;
2256 if (strcmp ("", image
->assembly
->aname
.culture
)) {
2257 values
[MONO_ASSEMBLYREF_CULTURE
] = string_heap_insert (&assembly
->sheap
,
2258 image
->assembly
->aname
.culture
);
2261 if ((pubkey
= mono_image_get_public_key (image
, &publen
))) {
2262 guchar pubtoken
[9];
2264 mono_digest_get_public_token (pubtoken
+ 1, (guchar
*)pubkey
, publen
);
2265 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = mono_image_add_stream_data (&assembly
->blob
, (char*)pubtoken
, 9);
2267 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = 0;
2269 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2270 token
|= MONO_RESOLTION_SCOPE_ASSEMBLYREF
;
2271 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2276 create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
)
2278 MonoDynamicTable
*table
;
2283 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
))))
2286 sigbuffer_init (&buf
, 32);
2287 switch (type
->type
) {
2288 case MONO_TYPE_FNPTR
:
2290 case MONO_TYPE_SZARRAY
:
2291 case MONO_TYPE_ARRAY
:
2293 case MONO_TYPE_MVAR
:
2294 case MONO_TYPE_GENERICINST
:
2295 encode_type (assembly
, type
, &buf
);
2297 case MONO_TYPE_CLASS
:
2298 case MONO_TYPE_VALUETYPE
: {
2299 MonoClass
*k
= mono_class_from_mono_type (type
);
2300 if (!k
|| !k
->generic_container
) {
2301 sigbuffer_free (&buf
);
2304 encode_type (assembly
, type
, &buf
);
2308 sigbuffer_free (&buf
);
2312 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2313 if (assembly
->save
) {
2314 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2315 alloc_table (table
, table
->rows
+ 1);
2316 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2317 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2319 sigbuffer_free (&buf
);
2321 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2322 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
2328 mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
)
2330 MonoDynamicTable
*table
;
2332 guint32 token
, scope
, enclosing
;
2335 /* if the type requires a typespec, we must try that first*/
2336 if (try_typespec
&& (token
= create_typespec (assembly
, type
)))
2338 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typeref
, type
));
2341 klass
= mono_class_from_mono_type (type
);
2343 klass
= mono_class_from_mono_type (type
);
2346 * If it's in the same module and not a generic type parameter:
2348 if ((klass
->image
== &assembly
->image
) && (type
->type
!= MONO_TYPE_VAR
) &&
2349 (type
->type
!= MONO_TYPE_MVAR
)) {
2350 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info (klass
);
2351 token
= MONO_TYPEDEFORREF_TYPEDEF
| (tb
->table_idx
<< MONO_TYPEDEFORREF_BITS
);
2352 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), mono_class_get_ref_info (klass
));
2356 if (klass
->nested_in
) {
2357 enclosing
= mono_image_typedef_or_ref_full (assembly
, &klass
->nested_in
->byval_arg
, FALSE
);
2358 /* get the typeref idx of the enclosing type */
2359 enclosing
>>= MONO_TYPEDEFORREF_BITS
;
2360 scope
= (enclosing
<< MONO_RESOLTION_SCOPE_BITS
) | MONO_RESOLTION_SCOPE_TYPEREF
;
2362 scope
= resolution_scope_from_image (assembly
, klass
->image
);
2364 table
= &assembly
->tables
[MONO_TABLE_TYPEREF
];
2365 if (assembly
->save
) {
2366 alloc_table (table
, table
->rows
+ 1);
2367 values
= table
->values
+ table
->next_idx
* MONO_TYPEREF_SIZE
;
2368 values
[MONO_TYPEREF_SCOPE
] = scope
;
2369 values
[MONO_TYPEREF_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
2370 values
[MONO_TYPEREF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
2372 token
= MONO_TYPEDEFORREF_TYPEREF
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
); /* typeref */
2373 g_hash_table_insert (assembly
->typeref
, type
, GUINT_TO_POINTER(token
));
2375 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), mono_class_get_ref_info (klass
));
2380 * Despite the name, we handle also TypeSpec (with the above helper).
2383 mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
)
2385 return mono_image_typedef_or_ref_full (assembly
, type
, TRUE
);
2388 #ifndef DISABLE_REFLECTION_EMIT
2390 mono_image_add_memberef_row (MonoDynamicImage
*assembly
, guint32 parent
, const char *name
, guint32 sig
)
2392 MonoDynamicTable
*table
;
2394 guint32 token
, pclass
;
2396 switch (parent
& MONO_TYPEDEFORREF_MASK
) {
2397 case MONO_TYPEDEFORREF_TYPEREF
:
2398 pclass
= MONO_MEMBERREF_PARENT_TYPEREF
;
2400 case MONO_TYPEDEFORREF_TYPESPEC
:
2401 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2403 case MONO_TYPEDEFORREF_TYPEDEF
:
2404 pclass
= MONO_MEMBERREF_PARENT_TYPEDEF
;
2407 g_warning ("unknown typeref or def token 0x%08x for %s", parent
, name
);
2410 /* extract the index */
2411 parent
>>= MONO_TYPEDEFORREF_BITS
;
2413 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2415 if (assembly
->save
) {
2416 alloc_table (table
, table
->rows
+ 1);
2417 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2418 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2419 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2420 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2423 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2430 * Insert a memberef row into the metadata: the token that point to the memberref
2431 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2432 * mono_image_get_fieldref_token()).
2433 * The sig param is an index to an already built signature.
2436 mono_image_get_memberref_token (MonoDynamicImage
*assembly
, MonoType
*type
, const char *name
, guint32 sig
)
2438 guint32 parent
= mono_image_typedef_or_ref (assembly
, type
);
2439 return mono_image_add_memberef_row (assembly
, parent
, name
, sig
);
2444 mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
)
2447 MonoMethodSignature
*sig
;
2449 create_typespec
= create_typespec
&& method
->is_generic
&& method
->klass
->image
!= &assembly
->image
;
2451 if (create_typespec
) {
2452 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1)));
2457 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2458 if (token
&& !create_typespec
)
2461 g_assert (!method
->is_inflated
);
2464 * A methodref signature can't contain an unmanaged calling convention.
2466 sig
= mono_metadata_signature_dup (mono_method_signature (method
));
2467 if ((sig
->call_convention
!= MONO_CALL_DEFAULT
) && (sig
->call_convention
!= MONO_CALL_VARARG
))
2468 sig
->call_convention
= MONO_CALL_DEFAULT
;
2469 token
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
,
2470 method
->name
, method_encode_signature (assembly
, sig
));
2472 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2475 if (create_typespec
) {
2476 MonoDynamicTable
*table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2477 g_assert (mono_metadata_token_table (token
) == MONO_TABLE_MEMBERREF
);
2478 token
= (mono_metadata_token_index (token
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2480 if (assembly
->save
) {
2483 alloc_table (table
, table
->rows
+ 1);
2484 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2485 values
[MONO_METHODSPEC_METHOD
] = token
;
2486 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_sig (assembly
, &mono_method_get_generic_container (method
)->context
);
2489 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2491 /*methodspec and memberef tokens are diferent, */
2492 g_hash_table_insert (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1), GUINT_TO_POINTER (token
));
2499 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
)
2501 guint32 token
, parent
, sig
;
2502 ReflectionMethodBuilder rmb
;
2504 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)method
->type
;
2506 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2510 name
= mono_string_to_utf8 (method
->name
);
2511 reflection_methodbuilder_from_method_builder (&rmb
, method
);
2514 * A methodref signature can't contain an unmanaged calling convention.
2515 * Since some flags are encoded as part of call_conv, we need to check against it.
2517 if ((rmb
.call_conv
& ~0x60) != MONO_CALL_DEFAULT
&& (rmb
.call_conv
& ~0x60) != MONO_CALL_VARARG
)
2518 rmb
.call_conv
= (rmb
.call_conv
& 0x60) | MONO_CALL_DEFAULT
;
2520 sig
= method_builder_encode_signature (assembly
, &rmb
);
2522 if (tb
->generic_params
)
2523 parent
= create_generic_typespec (assembly
, tb
);
2525 parent
= mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)rmb
.type
));
2527 token
= mono_image_add_memberef_row (assembly
, parent
, name
, sig
);
2530 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2535 mono_image_get_varargs_method_token (MonoDynamicImage
*assembly
, guint32 original
,
2536 const gchar
*name
, guint32 sig
)
2538 MonoDynamicTable
*table
;
2542 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2544 if (assembly
->save
) {
2545 alloc_table (table
, table
->rows
+ 1);
2546 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2547 values
[MONO_MEMBERREF_CLASS
] = original
;
2548 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2549 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2552 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2559 encode_generic_method_definition_sig (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2563 guint32 nparams
= mono_array_length (mb
->generic_params
);
2566 if (!assembly
->save
)
2569 sigbuffer_init (&buf
, 32);
2571 sigbuffer_add_value (&buf
, 0xa);
2572 sigbuffer_add_value (&buf
, nparams
);
2574 for (i
= 0; i
< nparams
; i
++) {
2575 sigbuffer_add_value (&buf
, MONO_TYPE_MVAR
);
2576 sigbuffer_add_value (&buf
, i
);
2579 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2580 sigbuffer_free (&buf
);
2585 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2587 MonoDynamicTable
*table
;
2589 guint32 token
, mtoken
= 0;
2591 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->methodspec
, mb
));
2595 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2597 mtoken
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2598 switch (mono_metadata_token_table (mtoken
)) {
2599 case MONO_TABLE_MEMBERREF
:
2600 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2602 case MONO_TABLE_METHOD
:
2603 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2606 g_assert_not_reached ();
2609 if (assembly
->save
) {
2610 alloc_table (table
, table
->rows
+ 1);
2611 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2612 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2613 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_definition_sig (assembly
, mb
);
2616 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2619 mono_g_hash_table_insert (assembly
->methodspec
, mb
, GUINT_TO_POINTER(token
));
2624 mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
)
2628 if (mb
->generic_params
&& create_methodspec
)
2629 return mono_image_get_methodspec_token_for_generic_method_definition (assembly
, mb
);
2631 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, mb
));
2635 token
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2636 mono_g_hash_table_insert (assembly
->handleref_managed
, mb
, GUINT_TO_POINTER(token
));
2641 mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*mb
)
2643 guint32 token
, parent
, sig
;
2644 ReflectionMethodBuilder rmb
;
2646 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
2648 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, mb
));
2652 g_assert (tb
->generic_params
);
2654 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
2656 parent
= create_generic_typespec (assembly
, tb
);
2657 name
= mono_string_to_utf8 (rmb
.name
);
2658 sig
= method_builder_encode_signature (assembly
, &rmb
);
2660 token
= mono_image_add_memberef_row (assembly
, parent
, name
, sig
);
2663 mono_g_hash_table_insert (assembly
->handleref_managed
, mb
, GUINT_TO_POINTER(token
));
2669 is_field_on_inst (MonoClassField
*field
)
2671 return (field
->parent
->generic_class
&& field
->parent
->generic_class
->is_dynamic
&& ((MonoDynamicGenericClass
*)field
->parent
->generic_class
)->fields
);
2675 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2678 get_field_on_inst_generic_type (MonoClassField
*field
)
2680 MonoClass
*class, *gtd
;
2681 MonoDynamicGenericClass
*dgclass
;
2684 g_assert (is_field_on_inst (field
));
2686 dgclass
= (MonoDynamicGenericClass
*)field
->parent
->generic_class
;
2688 if (field
>= dgclass
->fields
&& field
- dgclass
->fields
< dgclass
->count_fields
) {
2689 field_index
= field
- dgclass
->fields
;
2690 return dgclass
->field_generic_types
[field_index
];
2693 class = field
->parent
;
2694 gtd
= class->generic_class
->container_class
;
2696 if (field
>= class->fields
&& field
- class->fields
< class->field
.count
) {
2697 field_index
= field
- class->fields
;
2698 return gtd
->fields
[field_index
].type
;
2701 g_assert_not_reached ();
2705 #ifndef DISABLE_REFLECTION_EMIT
2707 mono_image_get_fieldref_token (MonoDynamicImage
*assembly
, MonoReflectionField
*f
)
2711 MonoClassField
*field
;
2713 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, f
));
2716 g_assert (f
->field
->parent
);
2719 if (field
->parent
->generic_class
&& field
->parent
->generic_class
->container_class
&& field
->parent
->generic_class
->container_class
->fields
) {
2720 int index
= field
- field
->parent
->fields
;
2721 type
= field
->parent
->generic_class
->container_class
->fields
[index
].type
;
2723 if (is_field_on_inst (f
->field
))
2724 type
= get_field_on_inst_generic_type (f
->field
);
2726 type
= f
->field
->type
;
2728 token
= mono_image_get_memberref_token (assembly
, &f
->field
->parent
->byval_arg
,
2729 mono_field_get_name (f
->field
),
2730 fieldref_encode_signature (assembly
, field
->parent
->image
, type
));
2731 mono_g_hash_table_insert (assembly
->handleref_managed
, f
, GUINT_TO_POINTER(token
));
2736 mono_image_get_field_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionFieldOnTypeBuilderInst
*f
)
2740 MonoGenericClass
*gclass
;
2741 MonoDynamicGenericClass
*dgclass
;
2745 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, f
));
2748 if (is_sre_field_builder (mono_object_class (f
->fb
))) {
2749 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)f
->fb
;
2750 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)f
->inst
);
2751 klass
= mono_class_from_mono_type (type
);
2752 gclass
= type
->data
.generic_class
;
2753 g_assert (gclass
->is_dynamic
);
2754 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2756 name
= mono_string_to_utf8 (fb
->name
);
2757 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
,
2758 field_encode_signature (assembly
, fb
));
2760 } else if (is_sr_mono_field (mono_object_class (f
->fb
))) {
2762 MonoClassField
*field
= ((MonoReflectionField
*)f
->fb
)->field
;
2764 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)f
->inst
);
2765 klass
= mono_class_from_mono_type (type
);
2767 sig
= fieldref_encode_signature (assembly
, field
->parent
->image
, field
->type
);
2768 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, field
->name
, sig
);
2770 char *name
= mono_type_get_full_name (mono_object_class (f
->fb
));
2771 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name
);
2774 mono_g_hash_table_insert (assembly
->handleref_managed
, f
, GUINT_TO_POINTER (token
));
2779 mono_image_get_ctor_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionCtorOnTypeBuilderInst
*c
, gboolean create_methodspec
)
2783 MonoGenericClass
*gclass
;
2786 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2788 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, c
));
2792 if (is_sre_ctor_builder (mono_object_class (c
->cb
))) {
2793 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)c
->cb
;
2794 MonoDynamicGenericClass
*dgclass
;
2795 ReflectionMethodBuilder rmb
;
2798 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)c
->inst
);
2799 klass
= mono_class_from_mono_type (type
);
2801 gclass
= type
->data
.generic_class
;
2802 g_assert (gclass
->is_dynamic
);
2803 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2805 reflection_methodbuilder_from_ctor_builder (&rmb
, cb
);
2807 name
= mono_string_to_utf8 (rmb
.name
);
2809 sig
= method_builder_encode_signature (assembly
, &rmb
);
2811 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2813 } else if (is_sr_mono_cmethod (mono_object_class (c
->cb
))) {
2814 MonoMethod
*mm
= ((MonoReflectionMethod
*)c
->cb
)->method
;
2816 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)c
->inst
);
2817 klass
= mono_class_from_mono_type (type
);
2819 sig
= method_encode_signature (assembly
, mono_method_signature (mm
));
2820 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, mm
->name
, sig
);
2822 char *name
= mono_type_get_full_name (mono_object_class (c
->cb
));
2823 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name
);
2827 mono_g_hash_table_insert (assembly
->handleref_managed
, c
, GUINT_TO_POINTER (token
));
2832 mono_reflection_method_on_tb_inst_get_handle (MonoReflectionMethodOnTypeBuilderInst
*m
)
2835 MonoGenericContext tmp_context
;
2836 MonoType
**type_argv
;
2837 MonoGenericInst
*ginst
;
2838 MonoMethod
*method
, *inflated
;
2841 method
= inflate_method (m
->inst
, (MonoObject
*)m
->mb
);
2843 klass
= method
->klass
;
2845 if (m
->method_args
== NULL
)
2848 if (method
->is_inflated
)
2849 method
= ((MonoMethodInflated
*) method
)->declaring
;
2851 count
= mono_array_length (m
->method_args
);
2853 type_argv
= g_new0 (MonoType
*, count
);
2854 for (i
= 0; i
< count
; i
++) {
2855 MonoReflectionType
*garg
= mono_array_get (m
->method_args
, gpointer
, i
);
2856 type_argv
[i
] = mono_reflection_type_get_handle (garg
);
2858 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
2861 tmp_context
.class_inst
= klass
->generic_class
? klass
->generic_class
->context
.class_inst
: NULL
;
2862 tmp_context
.method_inst
= ginst
;
2864 inflated
= mono_class_inflate_generic_method (method
, &tmp_context
);
2869 mono_image_get_method_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionMethodOnTypeBuilderInst
*m
, gboolean create_methodspec
)
2871 guint32 sig
, token
= 0;
2875 if (m
->method_args
) {
2876 MonoMethod
*inflated
;
2878 inflated
= mono_reflection_method_on_tb_inst_get_handle (m
);
2879 if (create_methodspec
)
2880 token
= mono_image_get_methodspec_token (assembly
, inflated
);
2882 token
= mono_image_get_inflated_method_token (assembly
, inflated
);
2886 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, m
));
2890 if (is_sre_method_builder (mono_object_class (m
->mb
))) {
2891 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)m
->mb
;
2892 MonoGenericClass
*gclass
;
2893 ReflectionMethodBuilder rmb
;
2896 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
);
2897 klass
= mono_class_from_mono_type (type
);
2898 gclass
= type
->data
.generic_class
;
2899 g_assert (gclass
->is_dynamic
);
2901 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
2903 name
= mono_string_to_utf8 (rmb
.name
);
2905 sig
= method_builder_encode_signature (assembly
, &rmb
);
2907 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2909 } else if (is_sr_mono_method (mono_object_class (m
->mb
))) {
2910 MonoMethod
*mm
= ((MonoReflectionMethod
*)m
->mb
)->method
;
2912 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
);
2913 klass
= mono_class_from_mono_type (type
);
2915 sig
= method_encode_signature (assembly
, mono_method_signature (mm
));
2916 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, mm
->name
, sig
);
2918 char *name
= mono_type_get_full_name (mono_object_class (m
->mb
));
2919 g_error ("mono_image_get_method_on_inst_token: don't know how to handle %s", name
);
2922 mono_g_hash_table_insert (assembly
->handleref_managed
, m
, GUINT_TO_POINTER (token
));
2927 encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
)
2931 guint32 nparams
= context
->method_inst
->type_argc
;
2934 if (!assembly
->save
)
2937 sigbuffer_init (&buf
, 32);
2939 * FIXME: vararg, explicit_this, differenc call_conv values...
2941 sigbuffer_add_value (&buf
, 0xa); /* FIXME FIXME FIXME */
2942 sigbuffer_add_value (&buf
, nparams
);
2944 for (i
= 0; i
< nparams
; i
++)
2945 encode_type (assembly
, context
->method_inst
->type_argv
[i
], &buf
);
2947 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2948 sigbuffer_free (&buf
);
2953 method_encode_methodspec (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2955 MonoDynamicTable
*table
;
2957 guint32 token
, mtoken
= 0, sig
;
2958 MonoMethodInflated
*imethod
;
2959 MonoMethod
*declaring
;
2961 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2963 g_assert (method
->is_inflated
);
2964 imethod
= (MonoMethodInflated
*) method
;
2965 declaring
= imethod
->declaring
;
2967 sig
= method_encode_signature (assembly
, mono_method_signature (declaring
));
2968 mtoken
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
, declaring
->name
, sig
);
2970 if (!mono_method_signature (declaring
)->generic_param_count
)
2973 switch (mono_metadata_token_table (mtoken
)) {
2974 case MONO_TABLE_MEMBERREF
:
2975 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2977 case MONO_TABLE_METHOD
:
2978 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2981 g_assert_not_reached ();
2984 sig
= encode_generic_method_sig (assembly
, mono_method_get_context (method
));
2986 if (assembly
->save
) {
2987 alloc_table (table
, table
->rows
+ 1);
2988 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2989 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2990 values
[MONO_METHODSPEC_SIGNATURE
] = sig
;
2993 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
3000 mono_image_get_methodspec_token (MonoDynamicImage
*assembly
, MonoMethod
*method
)
3002 MonoMethodInflated
*imethod
;
3005 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
3009 g_assert (method
->is_inflated
);
3010 imethod
= (MonoMethodInflated
*) method
;
3012 if (mono_method_signature (imethod
->declaring
)->generic_param_count
) {
3013 token
= method_encode_methodspec (assembly
, method
);
3015 guint32 sig
= method_encode_signature (
3016 assembly
, mono_method_signature (imethod
->declaring
));
3017 token
= mono_image_get_memberref_token (
3018 assembly
, &method
->klass
->byval_arg
, method
->name
, sig
);
3021 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
3026 mono_image_get_inflated_method_token (MonoDynamicImage
*assembly
, MonoMethod
*m
)
3028 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) m
;
3031 sig
= method_encode_signature (assembly
, mono_method_signature (imethod
->declaring
));
3032 token
= mono_image_get_memberref_token (
3033 assembly
, &m
->klass
->byval_arg
, m
->name
, sig
);
3039 create_generic_typespec (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
)
3041 MonoDynamicTable
*table
;
3050 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
3051 * ie. what we'd normally use as the generic type in a TypeSpec signature.
3052 * Because of this, we must not insert it into the `typeref' hash table.
3054 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
);
3055 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
));
3059 sigbuffer_init (&buf
, 32);
3061 g_assert (tb
->generic_params
);
3062 klass
= mono_class_from_mono_type (type
);
3064 if (tb
->generic_container
)
3065 mono_reflection_create_generic_class (tb
);
3067 sigbuffer_add_value (&buf
, MONO_TYPE_GENERICINST
);
3068 g_assert (klass
->generic_container
);
3069 sigbuffer_add_value (&buf
, klass
->byval_arg
.type
);
3070 sigbuffer_add_value (&buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
3072 count
= mono_array_length (tb
->generic_params
);
3073 sigbuffer_add_value (&buf
, count
);
3074 for (i
= 0; i
< count
; i
++) {
3075 MonoReflectionGenericParam
*gparam
;
3077 gparam
= mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
);
3079 encode_type (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
), &buf
);
3082 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
3084 if (assembly
->save
) {
3085 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3086 alloc_table (table
, table
->rows
+ 1);
3087 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
3088 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
3090 sigbuffer_free (&buf
);
3092 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
3093 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
3099 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
3102 add_custom_modifiers (MonoDynamicImage
*assembly
, MonoType
*type
, MonoArray
*modreq
, MonoArray
*modopt
)
3104 int i
, count
, len
, pos
;
3109 count
+= mono_array_length (modreq
);
3111 count
+= mono_array_length (modopt
);
3114 return mono_metadata_type_dup (NULL
, type
);
3116 len
= MONO_SIZEOF_TYPE
+ ((gint32
)count
) * sizeof (MonoCustomMod
);
3118 memcpy (t
, type
, MONO_SIZEOF_TYPE
);
3120 t
->num_mods
= count
;
3123 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
3124 MonoType
*mod
= mono_type_array_get_and_resolve (modreq
, i
);
3125 t
->modifiers
[pos
].required
= 1;
3126 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
);
3131 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
3132 MonoType
*mod
= mono_type_array_get_and_resolve (modopt
, i
);
3133 t
->modifiers
[pos
].required
= 0;
3134 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
);
3143 mono_image_get_generic_field_token (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
3145 MonoDynamicTable
*table
;
3147 MonoType
*custom
= NULL
;
3149 guint32 token
, pclass
, parent
, sig
;
3152 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->handleref_managed
, fb
));
3156 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle (fb
->typeb
));
3157 name
= mono_string_to_utf8 (fb
->name
);
3159 /* fb->type does not include the custom modifiers */
3160 /* FIXME: We should do this in one place when a fieldbuilder is created */
3161 if (fb
->modreq
|| fb
->modopt
) {
3162 custom
= add_custom_modifiers (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
), fb
->modreq
, fb
->modopt
);
3163 sig
= fieldref_encode_signature (assembly
, NULL
, custom
);
3166 sig
= fieldref_encode_signature (assembly
, NULL
, mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
));
3169 parent
= create_generic_typespec (assembly
, (MonoReflectionTypeBuilder
*) fb
->typeb
);
3170 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_TYPEDEFORREF_TYPESPEC
);
3172 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
3173 parent
>>= MONO_TYPEDEFORREF_BITS
;
3175 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
3177 if (assembly
->save
) {
3178 alloc_table (table
, table
->rows
+ 1);
3179 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
3180 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
3181 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
3182 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
3185 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
3187 mono_g_hash_table_insert (assembly
->handleref_managed
, fb
, GUINT_TO_POINTER(token
));
3193 mono_reflection_encode_sighelper (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
3200 if (!assembly
->save
)
3203 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3204 g_assert (helper
->type
== 2);
3206 if (helper
->arguments
)
3207 nargs
= mono_array_length (helper
->arguments
);
3211 size
= 10 + (nargs
* 10);
3213 sigbuffer_init (&buf
, 32);
3215 /* Encode calling convention */
3216 /* Change Any to Standard */
3217 if ((helper
->call_conv
& 0x03) == 0x03)
3218 helper
->call_conv
= 0x01;
3219 /* explicit_this implies has_this */
3220 if (helper
->call_conv
& 0x40)
3221 helper
->call_conv
&= 0x20;
3223 if (helper
->call_conv
== 0) { /* Unmanaged */
3224 idx
= helper
->unmanaged_call_conv
- 1;
3227 idx
= helper
->call_conv
& 0x60; /* has_this + explicit_this */
3228 if (helper
->call_conv
& 0x02) /* varargs */
3232 sigbuffer_add_byte (&buf
, idx
);
3233 sigbuffer_add_value (&buf
, nargs
);
3234 encode_reflection_type (assembly
, helper
->return_type
, &buf
);
3235 for (i
= 0; i
< nargs
; ++i
) {
3236 MonoArray
*modreqs
= NULL
;
3237 MonoArray
*modopts
= NULL
;
3238 MonoReflectionType
*pt
;
3240 if (helper
->modreqs
&& (i
< mono_array_length (helper
->modreqs
)))
3241 modreqs
= mono_array_get (helper
->modreqs
, MonoArray
*, i
);
3242 if (helper
->modopts
&& (i
< mono_array_length (helper
->modopts
)))
3243 modopts
= mono_array_get (helper
->modopts
, MonoArray
*, i
);
3245 encode_custom_modifiers (assembly
, modreqs
, modopts
, &buf
);
3246 pt
= mono_array_get (helper
->arguments
, MonoReflectionType
*, i
);
3247 encode_reflection_type (assembly
, pt
, &buf
);
3249 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3250 sigbuffer_free (&buf
);
3256 mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
3259 MonoDynamicTable
*table
;
3262 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
3263 idx
= table
->next_idx
++;
3265 alloc_table (table
, table
->rows
);
3266 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
3268 values
[MONO_STAND_ALONE_SIGNATURE
] =
3269 mono_reflection_encode_sighelper (assembly
, helper
);
3275 reflection_cc_to_file (int call_conv
) {
3276 switch (call_conv
& 0x3) {
3278 case 1: return MONO_CALL_DEFAULT
;
3279 case 2: return MONO_CALL_VARARG
;
3281 g_assert_not_reached ();
3285 #endif /* !DISABLE_REFLECTION_EMIT */
3289 MonoMethodSignature
*sig
;
3294 #ifndef DISABLE_REFLECTION_EMIT
3296 mono_image_get_array_token (MonoDynamicImage
*assembly
, MonoReflectionArrayMethod
*m
)
3301 MonoMethodSignature
*sig
;
3305 name
= mono_string_to_utf8 (m
->name
);
3306 nparams
= mono_array_length (m
->parameters
);
3307 sig
= g_malloc0 (MONO_SIZEOF_METHOD_SIGNATURE
+ sizeof (MonoType
*) * nparams
);
3309 sig
->sentinelpos
= -1;
3310 sig
->call_convention
= reflection_cc_to_file (m
->call_conv
);
3311 sig
->param_count
= nparams
;
3312 sig
->ret
= m
->ret
? mono_reflection_type_get_handle (m
->ret
): &mono_defaults
.void_class
->byval_arg
;
3313 mtype
= mono_reflection_type_get_handle (m
->parent
);
3314 for (i
= 0; i
< nparams
; ++i
)
3315 sig
->params
[i
] = mono_type_array_get_and_resolve (m
->parameters
, i
);
3317 for (tmp
= assembly
->array_methods
; tmp
; tmp
= tmp
->next
) {
3319 if (strcmp (name
, am
->name
) == 0 &&
3320 mono_metadata_type_equal (am
->parent
, mtype
) &&
3321 mono_metadata_signature_equal (am
->sig
, sig
)) {
3324 m
->table_idx
= am
->token
& 0xffffff;
3328 am
= g_new0 (ArrayMethod
, 1);
3332 am
->token
= mono_image_get_memberref_token (assembly
, am
->parent
, name
,
3333 method_encode_signature (assembly
, sig
));
3334 assembly
->array_methods
= g_list_prepend (assembly
->array_methods
, am
);
3335 m
->table_idx
= am
->token
& 0xffffff;
3340 * Insert into the metadata tables all the info about the TypeBuilder tb.
3341 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3344 mono_image_get_type_info (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
, MonoDynamicImage
*assembly
)
3346 MonoDynamicTable
*table
;
3348 int i
, is_object
= 0, is_system
= 0;
3351 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
3352 values
= table
->values
+ tb
->table_idx
* MONO_TYPEDEF_SIZE
;
3353 values
[MONO_TYPEDEF_FLAGS
] = tb
->attrs
;
3354 n
= mono_string_to_utf8 (tb
->name
);
3355 if (strcmp (n
, "Object") == 0)
3357 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, n
);
3359 n
= mono_string_to_utf8 (tb
->nspace
);
3360 if (strcmp (n
, "System") == 0)
3362 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, n
);
3364 if (tb
->parent
&& !(is_system
&& is_object
) &&
3365 !(tb
->attrs
& TYPE_ATTRIBUTE_INTERFACE
)) { /* interfaces don't have a parent */
3366 values
[MONO_TYPEDEF_EXTENDS
] = mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)tb
->parent
));
3368 values
[MONO_TYPEDEF_EXTENDS
] = 0;
3370 values
[MONO_TYPEDEF_FIELD_LIST
] = assembly
->tables
[MONO_TABLE_FIELD
].next_idx
;
3371 values
[MONO_TYPEDEF_METHOD_LIST
] = assembly
->tables
[MONO_TABLE_METHOD
].next_idx
;
3374 * if we have explicitlayout or sequentiallayouts, output data in the
3375 * ClassLayout table.
3377 if (((tb
->attrs
& TYPE_ATTRIBUTE_LAYOUT_MASK
) != TYPE_ATTRIBUTE_AUTO_LAYOUT
) &&
3378 ((tb
->class_size
> 0) || (tb
->packing_size
> 0))) {
3379 table
= &assembly
->tables
[MONO_TABLE_CLASSLAYOUT
];
3381 alloc_table (table
, table
->rows
);
3382 values
= table
->values
+ table
->rows
* MONO_CLASS_LAYOUT_SIZE
;
3383 values
[MONO_CLASS_LAYOUT_PARENT
] = tb
->table_idx
;
3384 values
[MONO_CLASS_LAYOUT_CLASS_SIZE
] = tb
->class_size
;
3385 values
[MONO_CLASS_LAYOUT_PACKING_SIZE
] = tb
->packing_size
;
3388 /* handle interfaces */
3389 if (tb
->interfaces
) {
3390 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3392 table
->rows
+= mono_array_length (tb
->interfaces
);
3393 alloc_table (table
, table
->rows
);
3394 values
= table
->values
+ (i
+ 1) * MONO_INTERFACEIMPL_SIZE
;
3395 for (i
= 0; i
< mono_array_length (tb
->interfaces
); ++i
) {
3396 MonoReflectionType
* iface
= (MonoReflectionType
*) mono_array_get (tb
->interfaces
, gpointer
, i
);
3397 values
[MONO_INTERFACEIMPL_CLASS
] = tb
->table_idx
;
3398 values
[MONO_INTERFACEIMPL_INTERFACE
] = mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle (iface
));
3399 values
+= MONO_INTERFACEIMPL_SIZE
;
3405 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
3406 table
->rows
+= tb
->num_fields
;
3407 alloc_table (table
, table
->rows
);
3408 for (i
= 0; i
< tb
->num_fields
; ++i
)
3409 mono_image_get_field_info (
3410 mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
3413 /* handle constructors */
3415 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3416 table
->rows
+= mono_array_length (tb
->ctors
);
3417 alloc_table (table
, table
->rows
);
3418 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
)
3419 mono_image_get_ctor_info (domain
,
3420 mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
), assembly
);
3423 /* handle methods */
3425 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3426 table
->rows
+= tb
->num_methods
;
3427 alloc_table (table
, table
->rows
);
3428 for (i
= 0; i
< tb
->num_methods
; ++i
)
3429 mono_image_get_method_info (
3430 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
3433 /* Do the same with properties etc.. */
3434 if (tb
->events
&& mono_array_length (tb
->events
)) {
3435 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
3436 table
->rows
+= mono_array_length (tb
->events
);
3437 alloc_table (table
, table
->rows
);
3438 table
= &assembly
->tables
[MONO_TABLE_EVENTMAP
];
3440 alloc_table (table
, table
->rows
);
3441 values
= table
->values
+ table
->rows
* MONO_EVENT_MAP_SIZE
;
3442 values
[MONO_EVENT_MAP_PARENT
] = tb
->table_idx
;
3443 values
[MONO_EVENT_MAP_EVENTLIST
] = assembly
->tables
[MONO_TABLE_EVENT
].next_idx
;
3444 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
)
3445 mono_image_get_event_info (
3446 mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
), assembly
);
3448 if (tb
->properties
&& mono_array_length (tb
->properties
)) {
3449 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
3450 table
->rows
+= mono_array_length (tb
->properties
);
3451 alloc_table (table
, table
->rows
);
3452 table
= &assembly
->tables
[MONO_TABLE_PROPERTYMAP
];
3454 alloc_table (table
, table
->rows
);
3455 values
= table
->values
+ table
->rows
* MONO_PROPERTY_MAP_SIZE
;
3456 values
[MONO_PROPERTY_MAP_PARENT
] = tb
->table_idx
;
3457 values
[MONO_PROPERTY_MAP_PROPERTY_LIST
] = assembly
->tables
[MONO_TABLE_PROPERTY
].next_idx
;
3458 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
)
3459 mono_image_get_property_info (
3460 mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
), assembly
);
3463 /* handle generic parameters */
3464 if (tb
->generic_params
) {
3465 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
3466 table
->rows
+= mono_array_length (tb
->generic_params
);
3467 alloc_table (table
, table
->rows
);
3468 for (i
= 0; i
< mono_array_length (tb
->generic_params
); ++i
) {
3469 guint32 owner
= MONO_TYPEORMETHOD_TYPE
| (tb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
3471 mono_image_get_generic_param_info (
3472 mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
), owner
, assembly
);
3476 mono_image_add_decl_security (assembly
,
3477 mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
), tb
->permissions
);
3480 MonoDynamicTable
*ntable
;
3482 ntable
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3483 ntable
->rows
+= mono_array_length (tb
->subtypes
);
3484 alloc_table (ntable
, ntable
->rows
);
3485 values
= ntable
->values
+ ntable
->next_idx
* MONO_NESTED_CLASS_SIZE
;
3487 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
3488 MonoReflectionTypeBuilder
*subtype
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3490 values
[MONO_NESTED_CLASS_NESTED
] = subtype
->table_idx
;
3491 values
[MONO_NESTED_CLASS_ENCLOSING
] = tb
->table_idx
;
3492 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3493 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3494 mono_string_to_utf8 (tb->name), tb->table_idx,
3495 ntable->next_idx, ntable->rows);*/
3496 values
+= MONO_NESTED_CLASS_SIZE
;
3504 collect_types (GPtrArray
*types
, MonoReflectionTypeBuilder
*type
)
3508 g_ptr_array_add (types
, type
); /* FIXME: GC object added to unmanaged memory */
3510 if (!type
->subtypes
)
3513 for (i
= 0; i
< mono_array_length (type
->subtypes
); ++i
) {
3514 MonoReflectionTypeBuilder
*subtype
= mono_array_get (type
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3515 collect_types (types
, subtype
);
3520 compare_types_by_table_idx (MonoReflectionTypeBuilder
**type1
, MonoReflectionTypeBuilder
**type2
)
3522 if ((*type1
)->table_idx
< (*type2
)->table_idx
)
3525 if ((*type1
)->table_idx
> (*type2
)->table_idx
)
3532 params_add_cattrs (MonoDynamicImage
*assembly
, MonoArray
*pinfo
) {
3537 for (i
= 0; i
< mono_array_length (pinfo
); ++i
) {
3538 MonoReflectionParamBuilder
*pb
;
3539 pb
= mono_array_get (pinfo
, MonoReflectionParamBuilder
*, i
);
3542 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PARAMDEF
, pb
->cattrs
);
3547 type_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
) {
3550 mono_image_add_cattrs (assembly
, tb
->table_idx
, MONO_CUSTOM_ATTR_TYPEDEF
, tb
->cattrs
);
3552 for (i
= 0; i
< tb
->num_fields
; ++i
) {
3553 MonoReflectionFieldBuilder
* fb
;
3554 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
);
3555 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3559 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
) {
3560 MonoReflectionEventBuilder
* eb
;
3561 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
3562 mono_image_add_cattrs (assembly
, eb
->table_idx
, MONO_CUSTOM_ATTR_EVENT
, eb
->cattrs
);
3565 if (tb
->properties
) {
3566 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
) {
3567 MonoReflectionPropertyBuilder
* pb
;
3568 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
3569 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PROPERTY
, pb
->cattrs
);
3573 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
3574 MonoReflectionCtorBuilder
* cb
;
3575 cb
= mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
);
3576 mono_image_add_cattrs (assembly
, cb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, cb
->cattrs
);
3577 params_add_cattrs (assembly
, cb
->pinfo
);
3582 for (i
= 0; i
< tb
->num_methods
; ++i
) {
3583 MonoReflectionMethodBuilder
* mb
;
3584 mb
= mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
3585 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3586 params_add_cattrs (assembly
, mb
->pinfo
);
3591 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3592 type_add_cattrs (assembly
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
));
3597 module_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionModuleBuilder
*moduleb
)
3601 mono_image_add_cattrs (assembly
, moduleb
->table_idx
, MONO_CUSTOM_ATTR_MODULE
, moduleb
->cattrs
);
3603 if (moduleb
->global_methods
) {
3604 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
3605 MonoReflectionMethodBuilder
* mb
= mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
3606 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3607 params_add_cattrs (assembly
, mb
->pinfo
);
3611 if (moduleb
->global_fields
) {
3612 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
) {
3613 MonoReflectionFieldBuilder
*fb
= mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
);
3614 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3618 if (moduleb
->types
) {
3619 for (i
= 0; i
< moduleb
->num_types
; ++i
)
3620 type_add_cattrs (assembly
, mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
));
3625 mono_image_fill_file_table (MonoDomain
*domain
, MonoReflectionModule
*module
, MonoDynamicImage
*assembly
)
3627 MonoDynamicTable
*table
;
3631 char *b
= blob_size
;
3634 table
= &assembly
->tables
[MONO_TABLE_FILE
];
3636 alloc_table (table
, table
->rows
);
3637 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
3638 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_METADATA
;
3639 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, module
->image
->module_name
);
3640 if (module
->image
->dynamic
) {
3641 /* This depends on the fact that the main module is emitted last */
3642 dir
= mono_string_to_utf8 (((MonoReflectionModuleBuilder
*)module
)->assemblyb
->dir
);
3643 path
= g_strdup_printf ("%s%c%s", dir
, G_DIR_SEPARATOR
, module
->image
->module_name
);
3646 path
= g_strdup (module
->image
->name
);
3648 mono_sha1_get_digest_from_file (path
, hash
);
3651 mono_metadata_encode_value (20, b
, &b
);
3652 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
3653 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
3658 mono_image_fill_module_table (MonoDomain
*domain
, MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
)
3660 MonoDynamicTable
*table
;
3663 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
3664 mb
->table_idx
= table
->next_idx
++;
3665 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->module
.name
);
3666 i
= mono_image_add_stream_data (&assembly
->guid
, mono_array_addr (mb
->guid
, char, 0), 16);
3669 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_GENERATION
] = 0;
3670 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_MVID
] = i
;
3671 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENC
] = 0;
3672 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENCBASE
] = 0;
3676 mono_image_fill_export_table_from_class (MonoDomain
*domain
, MonoClass
*klass
,
3677 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3679 MonoDynamicTable
*table
;
3683 visib
= klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
3684 if (! ((visib
& TYPE_ATTRIBUTE_PUBLIC
) || (visib
& TYPE_ATTRIBUTE_NESTED_PUBLIC
)))
3687 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3689 alloc_table (table
, table
->rows
);
3690 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3692 values
[MONO_EXP_TYPE_FLAGS
] = klass
->flags
;
3693 values
[MONO_EXP_TYPE_TYPEDEF
] = klass
->type_token
;
3694 if (klass
->nested_in
)
3695 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (parent_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
3697 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (module_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_FILE
;
3698 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3699 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3701 res
= table
->next_idx
;
3705 /* Emit nested types */
3706 if (klass
->ext
&& klass
->ext
->nested_classes
) {
3709 for (tmp
= klass
->ext
->nested_classes
; tmp
; tmp
= tmp
->next
)
3710 mono_image_fill_export_table_from_class (domain
, tmp
->data
, module_index
, table
->next_idx
- 1, assembly
);
3717 mono_image_fill_export_table (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
,
3718 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3723 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
));
3725 klass
->type_token
= mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
);
3727 idx
= mono_image_fill_export_table_from_class (domain
, klass
, module_index
,
3728 parent_index
, assembly
);
3732 * We need to do this ourselves since klass->nested_classes is not set up.
3735 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3736 mono_image_fill_export_table (domain
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
), module_index
, idx
, assembly
);
3741 mono_image_fill_export_table_from_module (MonoDomain
*domain
, MonoReflectionModule
*module
,
3742 guint32 module_index
, MonoDynamicImage
*assembly
)
3744 MonoImage
*image
= module
->image
;
3748 t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
3750 for (i
= 0; i
< t
->rows
; ++i
) {
3751 MonoClass
*klass
= mono_class_get (image
, mono_metadata_make_token (MONO_TABLE_TYPEDEF
, i
+ 1));
3753 if (klass
->flags
& TYPE_ATTRIBUTE_PUBLIC
)
3754 mono_image_fill_export_table_from_class (domain
, klass
, module_index
, 0, assembly
);
3759 add_exported_type (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
, MonoClass
*klass
, guint32 parent_index
)
3761 MonoDynamicTable
*table
;
3763 guint32 scope
, scope_idx
, impl
, current_idx
;
3764 gboolean forwarder
= TRUE
;
3765 gpointer iter
= NULL
;
3768 if (klass
->nested_in
) {
3769 impl
= (parent_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
3772 scope
= resolution_scope_from_image (assembly
, klass
->image
);
3773 g_assert ((scope
& MONO_RESOLTION_SCOPE_MASK
) == MONO_RESOLTION_SCOPE_ASSEMBLYREF
);
3774 scope_idx
= scope
>> MONO_RESOLTION_SCOPE_BITS
;
3775 impl
= (scope_idx
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_ASSEMBLYREF
;
3778 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3781 alloc_table (table
, table
->rows
);
3782 current_idx
= table
->next_idx
;
3783 values
= table
->values
+ current_idx
* MONO_EXP_TYPE_SIZE
;
3785 values
[MONO_EXP_TYPE_FLAGS
] = forwarder
? TYPE_ATTRIBUTE_FORWARDER
: 0;
3786 values
[MONO_EXP_TYPE_TYPEDEF
] = 0;
3787 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = impl
;
3788 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3789 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3793 while ((nested
= mono_class_get_nested_types (klass
, &iter
)))
3794 add_exported_type (assemblyb
, assembly
, nested
, current_idx
);
3798 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
)
3803 if (!assemblyb
->type_forwarders
)
3806 for (i
= 0; i
< mono_array_length (assemblyb
->type_forwarders
); ++i
) {
3807 MonoReflectionType
*t
= mono_array_get (assemblyb
->type_forwarders
, MonoReflectionType
*, i
);
3812 type
= mono_reflection_type_get_handle (t
);
3815 klass
= mono_class_from_mono_type (type
);
3817 add_exported_type (assemblyb
, assembly
, klass
, 0);
3821 #define align_pointer(base,p)\
3823 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3825 (p) += 4 - (__diff & 3);\
3829 compare_constants (const void *a
, const void *b
)
3831 const guint32
*a_values
= a
;
3832 const guint32
*b_values
= b
;
3833 return a_values
[MONO_CONSTANT_PARENT
] - b_values
[MONO_CONSTANT_PARENT
];
3837 compare_semantics (const void *a
, const void *b
)
3839 const guint32
*a_values
= a
;
3840 const guint32
*b_values
= b
;
3841 int assoc
= a_values
[MONO_METHOD_SEMA_ASSOCIATION
] - b_values
[MONO_METHOD_SEMA_ASSOCIATION
];
3844 return a_values
[MONO_METHOD_SEMA_SEMANTICS
] - b_values
[MONO_METHOD_SEMA_SEMANTICS
];
3848 compare_custom_attrs (const void *a
, const void *b
)
3850 const guint32
*a_values
= a
;
3851 const guint32
*b_values
= b
;
3853 return a_values
[MONO_CUSTOM_ATTR_PARENT
] - b_values
[MONO_CUSTOM_ATTR_PARENT
];
3857 compare_field_marshal (const void *a
, const void *b
)
3859 const guint32
*a_values
= a
;
3860 const guint32
*b_values
= b
;
3862 return a_values
[MONO_FIELD_MARSHAL_PARENT
] - b_values
[MONO_FIELD_MARSHAL_PARENT
];
3866 compare_nested (const void *a
, const void *b
)
3868 const guint32
*a_values
= a
;
3869 const guint32
*b_values
= b
;
3871 return a_values
[MONO_NESTED_CLASS_NESTED
] - b_values
[MONO_NESTED_CLASS_NESTED
];
3875 compare_genericparam (const void *a
, const void *b
)
3877 const GenericParamTableEntry
**a_entry
= (const GenericParamTableEntry
**) a
;
3878 const GenericParamTableEntry
**b_entry
= (const GenericParamTableEntry
**) b
;
3880 if ((*b_entry
)->owner
== (*a_entry
)->owner
)
3882 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType
*)(*a_entry
)->gparam
)) -
3883 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType
*)(*b_entry
)->gparam
));
3885 return (*a_entry
)->owner
- (*b_entry
)->owner
;
3889 compare_declsecurity_attrs (const void *a
, const void *b
)
3891 const guint32
*a_values
= a
;
3892 const guint32
*b_values
= b
;
3894 return a_values
[MONO_DECL_SECURITY_PARENT
] - b_values
[MONO_DECL_SECURITY_PARENT
];
3898 compare_interface_impl (const void *a
, const void *b
)
3900 const guint32
*a_values
= a
;
3901 const guint32
*b_values
= b
;
3903 int klass
= a_values
[MONO_INTERFACEIMPL_CLASS
] - b_values
[MONO_INTERFACEIMPL_CLASS
];
3907 return a_values
[MONO_INTERFACEIMPL_INTERFACE
] - b_values
[MONO_INTERFACEIMPL_INTERFACE
];
3911 pad_heap (MonoDynamicStream
*sh
)
3913 if (sh
->index
& 3) {
3914 int sz
= 4 - (sh
->index
& 3);
3915 memset (sh
->data
+ sh
->index
, 0, sz
);
3922 MonoDynamicStream
*stream
;
3926 * build_compressed_metadata() fills in the blob of data that represents the
3927 * raw metadata as it will be saved in the PE file. The five streams are output
3928 * and the metadata tables are comnpressed from the guint32 array representation,
3929 * to the compressed on-disk format.
3932 build_compressed_metadata (MonoDynamicImage
*assembly
)
3934 MonoDynamicTable
*table
;
3936 guint64 valid_mask
= 0;
3937 guint64 sorted_mask
;
3938 guint32 heapt_size
= 0;
3939 guint32 meta_size
= 256; /* allow for header and other stuff */
3940 guint32 table_offset
;
3941 guint32 ntables
= 0;
3947 struct StreamDesc stream_desc
[5];
3949 qsort (assembly
->gen_params
->pdata
, assembly
->gen_params
->len
, sizeof (gpointer
), compare_genericparam
);
3950 for (i
= 0; i
< assembly
->gen_params
->len
; i
++){
3951 GenericParamTableEntry
*entry
= g_ptr_array_index (assembly
->gen_params
, i
);
3952 write_generic_param_entry (assembly
, entry
);
3955 stream_desc
[0].name
= "#~";
3956 stream_desc
[0].stream
= &assembly
->tstream
;
3957 stream_desc
[1].name
= "#Strings";
3958 stream_desc
[1].stream
= &assembly
->sheap
;
3959 stream_desc
[2].name
= "#US";
3960 stream_desc
[2].stream
= &assembly
->us
;
3961 stream_desc
[3].name
= "#Blob";
3962 stream_desc
[3].stream
= &assembly
->blob
;
3963 stream_desc
[4].name
= "#GUID";
3964 stream_desc
[4].stream
= &assembly
->guid
;
3966 /* tables that are sorted */
3967 sorted_mask
= ((guint64
)1 << MONO_TABLE_CONSTANT
) | ((guint64
)1 << MONO_TABLE_FIELDMARSHAL
)
3968 | ((guint64
)1 << MONO_TABLE_METHODSEMANTICS
) | ((guint64
)1 << MONO_TABLE_CLASSLAYOUT
)
3969 | ((guint64
)1 << MONO_TABLE_FIELDLAYOUT
) | ((guint64
)1 << MONO_TABLE_FIELDRVA
)
3970 | ((guint64
)1 << MONO_TABLE_IMPLMAP
) | ((guint64
)1 << MONO_TABLE_NESTEDCLASS
)
3971 | ((guint64
)1 << MONO_TABLE_METHODIMPL
) | ((guint64
)1 << MONO_TABLE_CUSTOMATTRIBUTE
)
3972 | ((guint64
)1 << MONO_TABLE_DECLSECURITY
) | ((guint64
)1 << MONO_TABLE_GENERICPARAM
)
3973 | ((guint64
)1 << MONO_TABLE_INTERFACEIMPL
);
3975 /* Compute table sizes */
3976 /* the MonoImage has already been created in mono_image_basic_init() */
3977 meta
= &assembly
->image
;
3979 /* sizes should be multiple of 4 */
3980 pad_heap (&assembly
->blob
);
3981 pad_heap (&assembly
->guid
);
3982 pad_heap (&assembly
->sheap
);
3983 pad_heap (&assembly
->us
);
3985 /* Setup the info used by compute_sizes () */
3986 meta
->idx_blob_wide
= assembly
->blob
.index
>= 65536 ? 1 : 0;
3987 meta
->idx_guid_wide
= assembly
->guid
.index
>= 65536 ? 1 : 0;
3988 meta
->idx_string_wide
= assembly
->sheap
.index
>= 65536 ? 1 : 0;
3990 meta_size
+= assembly
->blob
.index
;
3991 meta_size
+= assembly
->guid
.index
;
3992 meta_size
+= assembly
->sheap
.index
;
3993 meta_size
+= assembly
->us
.index
;
3995 for (i
=0; i
< MONO_TABLE_NUM
; ++i
)
3996 meta
->tables
[i
].rows
= assembly
->tables
[i
].rows
;
3998 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3999 if (meta
->tables
[i
].rows
== 0)
4001 valid_mask
|= (guint64
)1 << i
;
4003 meta
->tables
[i
].row_size
= mono_metadata_compute_size (
4004 meta
, i
, &meta
->tables
[i
].size_bitfield
);
4005 heapt_size
+= meta
->tables
[i
].row_size
* meta
->tables
[i
].rows
;
4007 heapt_size
+= 24; /* #~ header size */
4008 heapt_size
+= ntables
* 4;
4009 /* make multiple of 4 */
4012 meta_size
+= heapt_size
;
4013 meta
->raw_metadata
= g_malloc0 (meta_size
);
4014 p
= (unsigned char*)meta
->raw_metadata
;
4015 /* the metadata signature */
4016 *p
++ = 'B'; *p
++ = 'S'; *p
++ = 'J'; *p
++ = 'B';
4017 /* version numbers and 4 bytes reserved */
4018 int16val
= (guint16
*)p
;
4019 *int16val
++ = GUINT16_TO_LE (meta
->md_version_major
);
4020 *int16val
= GUINT16_TO_LE (meta
->md_version_minor
);
4022 /* version string */
4023 int32val
= (guint32
*)p
;
4024 *int32val
= GUINT32_TO_LE ((strlen (meta
->version
) + 3) & (~3)); /* needs to be multiple of 4 */
4026 memcpy (p
, meta
->version
, strlen (meta
->version
));
4027 p
+= GUINT32_FROM_LE (*int32val
);
4028 align_pointer (meta
->raw_metadata
, p
);
4029 int16val
= (guint16
*)p
;
4030 *int16val
++ = GUINT16_TO_LE (0); /* flags must be 0 */
4031 *int16val
= GUINT16_TO_LE (5); /* number of streams */
4035 * write the stream info.
4037 table_offset
= (p
- (unsigned char*)meta
->raw_metadata
) + 5 * 8 + 40; /* room needed for stream headers */
4038 table_offset
+= 3; table_offset
&= ~3;
4040 assembly
->tstream
.index
= heapt_size
;
4041 for (i
= 0; i
< 5; ++i
) {
4042 int32val
= (guint32
*)p
;
4043 stream_desc
[i
].stream
->offset
= table_offset
;
4044 *int32val
++ = GUINT32_TO_LE (table_offset
);
4045 *int32val
= GUINT32_TO_LE (stream_desc
[i
].stream
->index
);
4046 table_offset
+= GUINT32_FROM_LE (*int32val
);
4047 table_offset
+= 3; table_offset
&= ~3;
4049 strcpy ((char*)p
, stream_desc
[i
].name
);
4050 p
+= strlen (stream_desc
[i
].name
) + 1;
4051 align_pointer (meta
->raw_metadata
, p
);
4054 * now copy the data, the table stream header and contents goes first.
4056 g_assert ((p
- (unsigned char*)meta
->raw_metadata
) < assembly
->tstream
.offset
);
4057 p
= (guchar
*)meta
->raw_metadata
+ assembly
->tstream
.offset
;
4058 int32val
= (guint32
*)p
;
4059 *int32val
= GUINT32_TO_LE (0); /* reserved */
4062 *p
++ = 2; /* version */
4065 if (meta
->idx_string_wide
)
4067 if (meta
->idx_guid_wide
)
4069 if (meta
->idx_blob_wide
)
4072 *p
++ = 1; /* reserved */
4073 int64val
= (guint64
*)p
;
4074 *int64val
++ = GUINT64_TO_LE (valid_mask
);
4075 *int64val
++ = GUINT64_TO_LE (valid_mask
& sorted_mask
); /* bitvector of sorted tables */
4077 int32val
= (guint32
*)p
;
4078 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
4079 if (meta
->tables
[i
].rows
== 0)
4081 *int32val
++ = GUINT32_TO_LE (meta
->tables
[i
].rows
);
4083 p
= (unsigned char*)int32val
;
4085 /* sort the tables that still need sorting */
4086 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
4088 qsort (table
->values
+ MONO_CONSTANT_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CONSTANT_SIZE
, compare_constants
);
4089 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
4091 qsort (table
->values
+ MONO_METHOD_SEMA_SIZE
, table
->rows
, sizeof (guint32
) * MONO_METHOD_SEMA_SIZE
, compare_semantics
);
4092 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4094 qsort (table
->values
+ MONO_CUSTOM_ATTR_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CUSTOM_ATTR_SIZE
, compare_custom_attrs
);
4095 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
4097 qsort (table
->values
+ MONO_FIELD_MARSHAL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_FIELD_MARSHAL_SIZE
, compare_field_marshal
);
4098 table
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
4100 qsort (table
->values
+ MONO_NESTED_CLASS_SIZE
, table
->rows
, sizeof (guint32
) * MONO_NESTED_CLASS_SIZE
, compare_nested
);
4101 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
4102 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
4104 qsort (table
->values
+ MONO_DECL_SECURITY_SIZE
, table
->rows
, sizeof (guint32
) * MONO_DECL_SECURITY_SIZE
, compare_declsecurity_attrs
);
4105 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
4107 qsort (table
->values
+ MONO_INTERFACEIMPL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_INTERFACEIMPL_SIZE
, compare_interface_impl
);
4109 /* compress the tables */
4110 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
4113 guint32 bitfield
= meta
->tables
[i
].size_bitfield
;
4114 if (!meta
->tables
[i
].rows
)
4116 if (assembly
->tables
[i
].columns
!= mono_metadata_table_count (bitfield
))
4117 g_error ("col count mismatch in %d: %d %d", i
, assembly
->tables
[i
].columns
, mono_metadata_table_count (bitfield
));
4118 meta
->tables
[i
].base
= (char*)p
;
4119 for (row
= 1; row
<= meta
->tables
[i
].rows
; ++row
) {
4120 values
= assembly
->tables
[i
].values
+ row
* assembly
->tables
[i
].columns
;
4121 for (col
= 0; col
< assembly
->tables
[i
].columns
; ++col
) {
4122 switch (mono_metadata_table_size (bitfield
, col
)) {
4124 *p
++ = values
[col
];
4127 *p
++ = values
[col
] & 0xff;
4128 *p
++ = (values
[col
] >> 8) & 0xff;
4131 *p
++ = values
[col
] & 0xff;
4132 *p
++ = (values
[col
] >> 8) & 0xff;
4133 *p
++ = (values
[col
] >> 16) & 0xff;
4134 *p
++ = (values
[col
] >> 24) & 0xff;
4137 g_assert_not_reached ();
4141 g_assert ((p
- (const unsigned char*)meta
->tables
[i
].base
) == (meta
->tables
[i
].rows
* meta
->tables
[i
].row_size
));
4144 g_assert (assembly
->guid
.offset
+ assembly
->guid
.index
< meta_size
);
4145 memcpy (meta
->raw_metadata
+ assembly
->sheap
.offset
, assembly
->sheap
.data
, assembly
->sheap
.index
);
4146 memcpy (meta
->raw_metadata
+ assembly
->us
.offset
, assembly
->us
.data
, assembly
->us
.index
);
4147 memcpy (meta
->raw_metadata
+ assembly
->blob
.offset
, assembly
->blob
.data
, assembly
->blob
.index
);
4148 memcpy (meta
->raw_metadata
+ assembly
->guid
.offset
, assembly
->guid
.data
, assembly
->guid
.index
);
4150 assembly
->meta_size
= assembly
->guid
.offset
+ assembly
->guid
.index
;
4154 * Some tables in metadata need to be sorted according to some criteria, but
4155 * when methods and fields are first created with reflection, they may be assigned a token
4156 * that doesn't correspond to the final token they will get assigned after the sorting.
4157 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
4158 * with the reflection objects that represent them. Once all the tables are set up, the
4159 * reflection objects will contains the correct table index. fixup_method() will fixup the
4160 * tokens for the method with ILGenerator @ilgen.
4163 fixup_method (MonoReflectionILGen
*ilgen
, gpointer value
, MonoDynamicImage
*assembly
)
4165 guint32 code_idx
= GPOINTER_TO_UINT (value
);
4166 MonoReflectionILTokenInfo
*iltoken
;
4167 MonoReflectionFieldBuilder
*field
;
4168 MonoReflectionCtorBuilder
*ctor
;
4169 MonoReflectionMethodBuilder
*method
;
4170 MonoReflectionTypeBuilder
*tb
;
4171 MonoReflectionArrayMethod
*am
;
4173 unsigned char *target
;
4175 for (i
= 0; i
< ilgen
->num_token_fixups
; ++i
) {
4176 iltoken
= (MonoReflectionILTokenInfo
*)mono_array_addr_with_size (ilgen
->token_fixups
, sizeof (MonoReflectionILTokenInfo
), i
);
4177 target
= (guchar
*)assembly
->code
.data
+ code_idx
+ iltoken
->code_pos
;
4178 switch (target
[3]) {
4179 case MONO_TABLE_FIELD
:
4180 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
4181 field
= (MonoReflectionFieldBuilder
*)iltoken
->member
;
4182 idx
= field
->table_idx
;
4183 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
4184 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
4185 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->field_to_table_idx
, f
));
4187 g_assert_not_reached ();
4190 case MONO_TABLE_METHOD
:
4191 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
4192 method
= (MonoReflectionMethodBuilder
*)iltoken
->member
;
4193 idx
= method
->table_idx
;
4194 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
4195 ctor
= (MonoReflectionCtorBuilder
*)iltoken
->member
;
4196 idx
= ctor
->table_idx
;
4197 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
4198 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod")) {
4199 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4200 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4202 g_assert_not_reached ();
4205 case MONO_TABLE_TYPEDEF
:
4206 if (strcmp (iltoken
->member
->vtable
->klass
->name
, "TypeBuilder"))
4207 g_assert_not_reached ();
4208 tb
= (MonoReflectionTypeBuilder
*)iltoken
->member
;
4209 idx
= tb
->table_idx
;
4211 case MONO_TABLE_MEMBERREF
:
4212 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoArrayMethod")) {
4213 am
= (MonoReflectionArrayMethod
*)iltoken
->member
;
4214 idx
= am
->table_idx
;
4215 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
4216 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod") ||
4217 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod") ||
4218 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericCMethod")) {
4219 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4220 g_assert (m
->klass
->generic_class
|| m
->klass
->generic_container
);
4222 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
4224 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
4225 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
4226 g_assert (is_field_on_inst (f
));
4228 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder") ||
4229 !strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
4231 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldOnTypeBuilderInst")) {
4233 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodOnTypeBuilderInst")) {
4235 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst")) {
4238 g_assert_not_reached ();
4241 case MONO_TABLE_METHODSPEC
:
4242 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod")) {
4243 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4244 g_assert (mono_method_signature (m
)->generic_param_count
);
4246 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
4248 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodOnTypeBuilderInst")) {
4251 g_assert_not_reached ();
4255 g_error ("got unexpected table 0x%02x in fixup", target
[3]);
4257 target
[0] = idx
& 0xff;
4258 target
[1] = (idx
>> 8) & 0xff;
4259 target
[2] = (idx
>> 16) & 0xff;
4266 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4267 * value is not known when the table is emitted.
4270 fixup_cattrs (MonoDynamicImage
*assembly
)
4272 MonoDynamicTable
*table
;
4274 guint32 type
, i
, idx
, token
;
4277 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4279 for (i
= 0; i
< table
->rows
; ++i
) {
4280 values
= table
->values
+ ((i
+ 1) * MONO_CUSTOM_ATTR_SIZE
);
4282 type
= values
[MONO_CUSTOM_ATTR_TYPE
];
4283 if ((type
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_METHODDEF
) {
4284 idx
= type
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
4285 token
= mono_metadata_make_token (MONO_TABLE_METHOD
, idx
);
4286 ctor
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4289 if (!strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
4290 MonoMethod
*m
= ((MonoReflectionMethod
*)ctor
)->method
;
4291 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4292 values
[MONO_CUSTOM_ATTR_TYPE
] = (idx
<< MONO_CUSTOM_ATTR_TYPE_BITS
) | MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
4299 assembly_add_resource_manifest (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
, guint32 implementation
)
4301 MonoDynamicTable
*table
;
4304 table
= &assembly
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4306 alloc_table (table
, table
->rows
);
4307 values
= table
->values
+ table
->next_idx
* MONO_MANIFEST_SIZE
;
4308 values
[MONO_MANIFEST_OFFSET
] = rsrc
->offset
;
4309 values
[MONO_MANIFEST_FLAGS
] = rsrc
->attrs
;
4310 values
[MONO_MANIFEST_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, rsrc
->name
);
4311 values
[MONO_MANIFEST_IMPLEMENTATION
] = implementation
;
4316 assembly_add_resource (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
)
4318 MonoDynamicTable
*table
;
4322 char *b
= blob_size
;
4324 guint32 idx
, offset
;
4326 if (rsrc
->filename
) {
4327 name
= mono_string_to_utf8 (rsrc
->filename
);
4328 sname
= g_path_get_basename (name
);
4330 table
= &assembly
->tables
[MONO_TABLE_FILE
];
4332 alloc_table (table
, table
->rows
);
4333 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
4334 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_NO_METADATA
;
4335 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, sname
);
4338 mono_sha1_get_digest_from_file (name
, hash
);
4339 mono_metadata_encode_value (20, b
, &b
);
4340 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
4341 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
4343 idx
= table
->next_idx
++;
4345 idx
= MONO_IMPLEMENTATION_FILE
| (idx
<< MONO_IMPLEMENTATION_BITS
);
4351 data
= mono_array_addr (rsrc
->data
, char, 0);
4352 len
= mono_array_length (rsrc
->data
);
4358 sizebuf
[0] = offset
; sizebuf
[1] = offset
>> 8;
4359 sizebuf
[2] = offset
>> 16; sizebuf
[3] = offset
>> 24;
4360 rsrc
->offset
= mono_image_add_stream_data (&assembly
->resources
, sizebuf
, 4);
4361 mono_image_add_stream_data (&assembly
->resources
, data
, len
);
4365 * The entry should be emitted into the MANIFESTRESOURCE table of
4366 * the main module, but that needs to reference the FILE table
4367 * which isn't emitted yet.
4374 assembly_add_resource_manifest (mb
, assembly
, rsrc
, idx
);
4378 set_version_from_string (MonoString
*version
, guint32
*values
)
4380 gchar
*ver
, *p
, *str
;
4383 values
[MONO_ASSEMBLY_MAJOR_VERSION
] = 0;
4384 values
[MONO_ASSEMBLY_MINOR_VERSION
] = 0;
4385 values
[MONO_ASSEMBLY_REV_NUMBER
] = 0;
4386 values
[MONO_ASSEMBLY_BUILD_NUMBER
] = 0;
4389 ver
= str
= mono_string_to_utf8 (version
);
4390 for (i
= 0; i
< 4; ++i
) {
4391 values
[MONO_ASSEMBLY_MAJOR_VERSION
+ i
] = strtol (ver
, &p
, 10);
4397 /* handle Revision and Build */
4407 load_public_key (MonoArray
*pkey
, MonoDynamicImage
*assembly
) {
4411 char *b
= blob_size
;
4416 len
= mono_array_length (pkey
);
4417 mono_metadata_encode_value (len
, b
, &b
);
4418 token
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
- blob_size
);
4419 mono_image_add_stream_data (&assembly
->blob
, mono_array_addr (pkey
, char, 0), len
);
4421 assembly
->public_key
= g_malloc (len
);
4422 memcpy (assembly
->public_key
, mono_array_addr (pkey
, char, 0), len
);
4423 assembly
->public_key_len
= len
;
4425 /* Special case: check for ECMA key (16 bytes) */
4426 if ((len
== MONO_ECMA_KEY_LENGTH
) && mono_is_ecma_key (mono_array_addr (pkey
, char, 0), len
)) {
4427 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4428 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
;
4429 } else if (len
>= MONO_PUBLIC_KEY_HEADER_LENGTH
+ MONO_MINIMUM_PUBLIC_KEY_LENGTH
) {
4430 /* minimum key size (in 2.0) is 384 bits */
4431 assembly
->strong_name_size
= len
- MONO_PUBLIC_KEY_HEADER_LENGTH
;
4433 /* FIXME - verifier */
4434 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len
), (int)len
);
4435 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
; /* to be safe */
4437 assembly
->strong_name
= g_malloc0 (assembly
->strong_name_size
);
4443 mono_image_emit_manifest (MonoReflectionModuleBuilder
*moduleb
)
4445 MonoDynamicTable
*table
;
4446 MonoDynamicImage
*assembly
;
4447 MonoReflectionAssemblyBuilder
*assemblyb
;
4451 guint32 module_index
;
4453 assemblyb
= moduleb
->assemblyb
;
4454 assembly
= moduleb
->dynamic_image
;
4455 domain
= mono_object_domain (assemblyb
);
4457 /* Emit ASSEMBLY table */
4458 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLY
];
4459 alloc_table (table
, 1);
4460 values
= table
->values
+ MONO_ASSEMBLY_SIZE
;
4461 values
[MONO_ASSEMBLY_HASH_ALG
] = assemblyb
->algid
? assemblyb
->algid
: ASSEMBLY_HASH_SHA1
;
4462 values
[MONO_ASSEMBLY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->name
);
4463 if (assemblyb
->culture
) {
4464 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->culture
);
4466 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert (&assembly
->sheap
, "");
4468 values
[MONO_ASSEMBLY_PUBLIC_KEY
] = load_public_key (assemblyb
->public_key
, assembly
);
4469 values
[MONO_ASSEMBLY_FLAGS
] = assemblyb
->flags
;
4470 set_version_from_string (assemblyb
->version
, values
);
4472 /* Emit FILE + EXPORTED_TYPE table */
4474 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4476 MonoReflectionModuleBuilder
*file_module
=
4477 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4478 if (file_module
!= moduleb
) {
4479 mono_image_fill_file_table (domain
, (MonoReflectionModule
*)file_module
, assembly
);
4481 if (file_module
->types
) {
4482 for (j
= 0; j
< file_module
->num_types
; ++j
) {
4483 MonoReflectionTypeBuilder
*tb
= mono_array_get (file_module
->types
, MonoReflectionTypeBuilder
*, j
);
4484 mono_image_fill_export_table (domain
, tb
, module_index
, 0, assembly
);
4489 if (assemblyb
->loaded_modules
) {
4490 for (i
= 0; i
< mono_array_length (assemblyb
->loaded_modules
); ++i
) {
4491 MonoReflectionModule
*file_module
=
4492 mono_array_get (assemblyb
->loaded_modules
, MonoReflectionModule
*, i
);
4493 mono_image_fill_file_table (domain
, file_module
, assembly
);
4495 mono_image_fill_export_table_from_module (domain
, file_module
, module_index
, assembly
);
4498 if (assemblyb
->type_forwarders
)
4499 mono_image_fill_export_table_from_type_forwarders (assemblyb
, assembly
);
4501 /* Emit MANIFESTRESOURCE table */
4503 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4505 MonoReflectionModuleBuilder
*file_module
=
4506 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4507 /* The table for the main module is emitted later */
4508 if (file_module
!= moduleb
) {
4510 if (file_module
->resources
) {
4511 int len
= mono_array_length (file_module
->resources
);
4512 for (j
= 0; j
< len
; ++j
) {
4513 MonoReflectionResource
* res
= (MonoReflectionResource
*)mono_array_addr (file_module
->resources
, MonoReflectionResource
, j
);
4514 assembly_add_resource_manifest (file_module
, assembly
, res
, MONO_IMPLEMENTATION_FILE
| (module_index
<< MONO_IMPLEMENTATION_BITS
));
4521 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4524 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4525 * for the modulebuilder @moduleb.
4526 * At the end of the process, method and field tokens are fixed up and the
4527 * on-disk compressed metadata representation is created.
4530 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4532 MonoDynamicTable
*table
;
4533 MonoDynamicImage
*assembly
;
4534 MonoReflectionAssemblyBuilder
*assemblyb
;
4540 assemblyb
= moduleb
->assemblyb
;
4541 assembly
= moduleb
->dynamic_image
;
4542 domain
= mono_object_domain (assemblyb
);
4544 if (assembly
->text_rva
)
4547 assembly
->text_rva
= START_TEXT_RVA
;
4549 if (moduleb
->is_main
) {
4550 mono_image_emit_manifest (moduleb
);
4553 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4554 table
->rows
= 1; /* .<Module> */
4556 alloc_table (table
, table
->rows
);
4558 * Set the first entry.
4560 values
= table
->values
+ table
->columns
;
4561 values
[MONO_TYPEDEF_FLAGS
] = 0;
4562 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, "<Module>") ;
4563 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, "") ;
4564 values
[MONO_TYPEDEF_EXTENDS
] = 0;
4565 values
[MONO_TYPEDEF_FIELD_LIST
] = 1;
4566 values
[MONO_TYPEDEF_METHOD_LIST
] = 1;
4569 * handle global methods
4570 * FIXME: test what to do when global methods are defined in multiple modules.
4572 if (moduleb
->global_methods
) {
4573 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
4574 table
->rows
+= mono_array_length (moduleb
->global_methods
);
4575 alloc_table (table
, table
->rows
);
4576 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
)
4577 mono_image_get_method_info (
4578 mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
4580 if (moduleb
->global_fields
) {
4581 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
4582 table
->rows
+= mono_array_length (moduleb
->global_fields
);
4583 alloc_table (table
, table
->rows
);
4584 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
)
4585 mono_image_get_field_info (
4586 mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
4589 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
4590 alloc_table (table
, 1);
4591 mono_image_fill_module_table (domain
, moduleb
, assembly
);
4593 /* Collect all types into a list sorted by their table_idx */
4594 types
= g_ptr_array_new ();
4597 for (i
= 0; i
< moduleb
->num_types
; ++i
) {
4598 MonoReflectionTypeBuilder
*type
= mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
);
4599 collect_types (types
, type
);
4602 g_ptr_array_sort (types
, (GCompareFunc
)compare_types_by_table_idx
);
4603 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4604 table
->rows
+= types
->len
;
4605 alloc_table (table
, table
->rows
);
4608 * Emit type names + namespaces at one place inside the string heap,
4609 * so load_class_names () needs to touch fewer pages.
4611 for (i
= 0; i
< types
->len
; ++i
) {
4612 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4613 string_heap_insert_mstring (&assembly
->sheap
, tb
->nspace
);
4615 for (i
= 0; i
< types
->len
; ++i
) {
4616 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4617 string_heap_insert_mstring (&assembly
->sheap
, tb
->name
);
4620 for (i
= 0; i
< types
->len
; ++i
) {
4621 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4622 mono_image_get_type_info (domain
, type
, assembly
);
4626 * table->rows is already set above and in mono_image_fill_module_table.
4628 /* add all the custom attributes at the end, once all the indexes are stable */
4629 mono_image_add_cattrs (assembly
, 1, MONO_CUSTOM_ATTR_ASSEMBLY
, assemblyb
->cattrs
);
4631 /* CAS assembly permissions */
4632 if (assemblyb
->permissions_minimum
)
4633 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_minimum
);
4634 if (assemblyb
->permissions_optional
)
4635 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_optional
);
4636 if (assemblyb
->permissions_refused
)
4637 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_refused
);
4639 module_add_cattrs (assembly
, moduleb
);
4642 mono_g_hash_table_foreach (assembly
->token_fixups
, (GHFunc
)fixup_method
, assembly
);
4644 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4645 * the final tokens and don't need another fixup pass. */
4647 if (moduleb
->global_methods
) {
4648 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
4649 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4650 moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
4651 mono_image_add_methodimpl (assembly
, mb
);
4655 for (i
= 0; i
< types
->len
; ++i
) {
4656 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4657 if (type
->methods
) {
4658 for (j
= 0; j
< type
->num_methods
; ++j
) {
4659 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4660 type
->methods
, MonoReflectionMethodBuilder
*, j
);
4662 mono_image_add_methodimpl (assembly
, mb
);
4667 g_ptr_array_free (types
, TRUE
);
4669 fixup_cattrs (assembly
);
4672 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4675 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4677 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4680 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4684 guint32 import_lookup_table
;
4688 guint32 import_address_table_rva
;
4696 #ifndef DISABLE_REFLECTION_EMIT
4699 * mono_image_insert_string:
4700 * @module: module builder object
4703 * Insert @str into the user string stream of @module.
4706 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
4708 MonoDynamicImage
*assembly
;
4713 MONO_ARCH_SAVE_REGS
;
4715 if (!module
->dynamic_image
)
4716 mono_image_module_basic_init (module
);
4718 assembly
= module
->dynamic_image
;
4720 if (assembly
->save
) {
4721 mono_metadata_encode_value (1 | (str
->length
* 2), b
, &b
);
4722 idx
= mono_image_add_stream_data (&assembly
->us
, buf
, b
-buf
);
4723 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4725 char *swapped
= g_malloc (2 * mono_string_length (str
));
4726 const char *p
= (const char*)mono_string_chars (str
);
4728 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
4729 mono_image_add_stream_data (&assembly
->us
, swapped
, str
->length
* 2);
4733 mono_image_add_stream_data (&assembly
->us
, (const char*)mono_string_chars (str
), str
->length
* 2);
4735 mono_image_add_stream_data (&assembly
->us
, "", 1);
4737 idx
= assembly
->us
.index
++;
4740 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (MONO_TOKEN_STRING
| idx
), str
);
4742 return MONO_TOKEN_STRING
| idx
;
4746 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
4751 klass
= obj
->vtable
->klass
;
4752 if (strcmp (klass
->name
, "MonoMethod") == 0) {
4753 MonoMethod
*method
= ((MonoReflectionMethod
*)obj
)->method
;
4754 MonoMethodSignature
*sig
, *old
;
4755 guint32 sig_token
, parent
;
4758 g_assert (opt_param_types
&& (mono_method_signature (method
)->sentinelpos
>= 0));
4760 nargs
= mono_array_length (opt_param_types
);
4761 old
= mono_method_signature (method
);
4762 sig
= mono_metadata_signature_alloc ( &assembly
->image
, old
->param_count
+ nargs
);
4764 sig
->hasthis
= old
->hasthis
;
4765 sig
->explicit_this
= old
->explicit_this
;
4766 sig
->call_convention
= old
->call_convention
;
4767 sig
->generic_param_count
= old
->generic_param_count
;
4768 sig
->param_count
= old
->param_count
+ nargs
;
4769 sig
->sentinelpos
= old
->param_count
;
4770 sig
->ret
= old
->ret
;
4772 for (i
= 0; i
< old
->param_count
; i
++)
4773 sig
->params
[i
] = old
->params
[i
];
4775 for (i
= 0; i
< nargs
; i
++) {
4776 MonoReflectionType
*rt
= mono_array_get (opt_param_types
, MonoReflectionType
*, i
);
4777 sig
->params
[old
->param_count
+ i
] = mono_reflection_type_get_handle (rt
);
4780 parent
= mono_image_typedef_or_ref (assembly
, &method
->klass
->byval_arg
);
4781 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_MEMBERREF_PARENT_TYPEREF
);
4782 parent
>>= MONO_TYPEDEFORREF_BITS
;
4784 parent
<<= MONO_MEMBERREF_PARENT_BITS
;
4785 parent
|= MONO_MEMBERREF_PARENT_TYPEREF
;
4787 sig_token
= method_encode_signature (assembly
, sig
);
4788 token
= mono_image_get_varargs_method_token (assembly
, parent
, method
->name
, sig_token
);
4789 } else if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4790 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4791 ReflectionMethodBuilder rmb
;
4792 guint32 parent
, sig
;
4795 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
4796 rmb
.opt_types
= opt_param_types
;
4798 sig
= method_builder_encode_signature (assembly
, &rmb
);
4800 parent
= mono_image_create_token (assembly
, obj
, TRUE
, TRUE
);
4801 g_assert (mono_metadata_token_table (parent
) == MONO_TABLE_METHOD
);
4803 parent
= mono_metadata_token_index (parent
) << MONO_MEMBERREF_PARENT_BITS
;
4804 parent
|= MONO_MEMBERREF_PARENT_METHODDEF
;
4806 name
= mono_string_to_utf8 (rmb
.name
);
4807 token
= mono_image_get_varargs_method_token (
4808 assembly
, parent
, name
, sig
);
4811 g_error ("requested method token for %s\n", klass
->name
);
4818 * mono_image_create_token:
4819 * @assembly: a dynamic assembly
4821 * @register_token: Whenever to register the token in the assembly->tokens hash.
4823 * Get a token to insert in the IL code stream for the given MemberInfo.
4824 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4825 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4829 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
4830 gboolean create_methodspec
, gboolean register_token
)
4835 klass
= obj
->vtable
->klass
;
4837 /* Check for user defined reflection objects */
4838 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4839 if (klass
->image
!= mono_defaults
.corlib
|| (strcmp (klass
->name
, "TypeDelegator") == 0))
4840 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4842 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4843 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4844 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4846 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
&& !mb
->generic_params
)
4847 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4849 token
= mono_image_get_methodbuilder_token (assembly
, mb
, create_methodspec
);
4850 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4851 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
4852 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
4853 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4855 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
)
4856 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4858 token
= mono_image_get_ctorbuilder_token (assembly
, mb
);
4859 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4860 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
4861 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
4862 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
4863 if (tb
->generic_params
) {
4864 token
= mono_image_get_generic_field_token (assembly
, fb
);
4866 token
= fb
->table_idx
| MONO_TOKEN_FIELD_DEF
;
4868 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
4869 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
4870 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
4871 } else if (strcmp (klass
->name
, "MonoType") == 0) {
4872 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
4873 MonoClass
*mc
= mono_class_from_mono_type (type
);
4874 token
= mono_metadata_token_from_dor (
4875 mono_image_typedef_or_ref_full (assembly
, type
, mc
->generic_container
== NULL
));
4876 } else if (strcmp (klass
->name
, "GenericTypeParameterBuilder") == 0) {
4877 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
4878 token
= mono_metadata_token_from_dor (
4879 mono_image_typedef_or_ref (assembly
, type
));
4880 } else if (strcmp (klass
->name
, "MonoGenericClass") == 0) {
4881 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
4882 token
= mono_metadata_token_from_dor (
4883 mono_image_typedef_or_ref (assembly
, type
));
4884 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
4885 strcmp (klass
->name
, "MonoMethod") == 0 ||
4886 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
4887 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
4888 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
4889 if (m
->method
->is_inflated
) {
4890 if (create_methodspec
)
4891 token
= mono_image_get_methodspec_token (assembly
, m
->method
);
4893 token
= mono_image_get_inflated_method_token (assembly
, m
->method
);
4894 } else if ((m
->method
->klass
->image
== &assembly
->image
) &&
4895 !m
->method
->klass
->generic_class
) {
4896 static guint32 method_table_idx
= 0xffffff;
4897 if (m
->method
->klass
->wastypebuilder
) {
4898 /* we use the same token as the one that was assigned
4899 * to the Methodbuilder.
4900 * FIXME: do the equivalent for Fields.
4902 token
= m
->method
->token
;
4905 * Each token should have a unique index, but the indexes are
4906 * assigned by managed code, so we don't know about them. An
4907 * easy solution is to count backwards...
4909 method_table_idx
--;
4910 token
= MONO_TOKEN_METHOD_DEF
| method_table_idx
;
4913 token
= mono_image_get_methodref_token (assembly
, m
->method
, create_methodspec
);
4915 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4916 } else if (strcmp (klass
->name
, "MonoField") == 0) {
4917 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
4918 if ((f
->field
->parent
->image
== &assembly
->image
) && !is_field_on_inst (f
->field
)) {
4919 static guint32 field_table_idx
= 0xffffff;
4921 token
= MONO_TOKEN_FIELD_DEF
| field_table_idx
;
4923 token
= mono_image_get_fieldref_token (assembly
, f
);
4925 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4926 } else if (strcmp (klass
->name
, "MonoArrayMethod") == 0) {
4927 MonoReflectionArrayMethod
*m
= (MonoReflectionArrayMethod
*)obj
;
4928 token
= mono_image_get_array_token (assembly
, m
);
4929 } else if (strcmp (klass
->name
, "SignatureHelper") == 0) {
4930 MonoReflectionSigHelper
*s
= (MonoReflectionSigHelper
*)obj
;
4931 token
= MONO_TOKEN_SIGNATURE
| mono_image_get_sighelper_token (assembly
, s
);
4932 } else if (strcmp (klass
->name
, "EnumBuilder") == 0) {
4933 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
4934 token
= mono_metadata_token_from_dor (
4935 mono_image_typedef_or_ref (assembly
, type
));
4936 } else if (strcmp (klass
->name
, "FieldOnTypeBuilderInst") == 0) {
4937 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
4938 token
= mono_image_get_field_on_inst_token (assembly
, f
);
4939 } else if (strcmp (klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
4940 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
4941 token
= mono_image_get_ctor_on_inst_token (assembly
, c
, create_methodspec
);
4942 } else if (strcmp (klass
->name
, "MethodOnTypeBuilderInst") == 0) {
4943 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
4944 token
= mono_image_get_method_on_inst_token (assembly
, m
, create_methodspec
);
4945 } else if (is_sre_array (klass
) || is_sre_byref (klass
) || is_sre_pointer (klass
)) {
4946 MonoReflectionType
*type
= (MonoReflectionType
*)obj
;
4947 token
= mono_metadata_token_from_dor (
4948 mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle (type
)));
4950 g_error ("requested token for %s\n", klass
->name
);
4954 mono_image_register_token (assembly
, token
, obj
);
4960 * mono_image_register_token:
4962 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4963 * the Module.ResolveXXXToken () methods to work.
4966 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
4968 MonoObject
*prev
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4970 /* There could be multiple MethodInfo objects with the same token */
4971 //g_assert (prev == obj);
4973 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), obj
);
4977 static MonoDynamicImage
*
4978 create_dynamic_mono_image (MonoDynamicAssembly
*assembly
, char *assembly_name
, char *module_name
)
4980 static const guchar entrycode
[16] = {0xff, 0x25, 0};
4981 MonoDynamicImage
*image
;
4984 const char *version
;
4986 if (!strcmp (mono_get_runtime_info ()->framework_version
, "2.1"))
4987 version
= "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4989 version
= mono_get_runtime_info ()->runtime_version
;
4992 image
= GC_MALLOC (sizeof (MonoDynamicImage
));
4994 image
= g_new0 (MonoDynamicImage
, 1);
4997 mono_profiler_module_event (&image
->image
, MONO_PROFILE_START_LOAD
);
4999 /*g_print ("created image %p\n", image);*/
5000 /* keep in sync with image.c */
5001 image
->image
.name
= assembly_name
;
5002 image
->image
.assembly_name
= image
->image
.name
; /* they may be different */
5003 image
->image
.module_name
= module_name
;
5004 image
->image
.version
= g_strdup (version
);
5005 image
->image
.md_version_major
= 1;
5006 image
->image
.md_version_minor
= 1;
5007 image
->image
.dynamic
= TRUE
;
5009 image
->image
.references
= g_new0 (MonoAssembly
*, 1);
5010 image
->image
.references
[0] = NULL
;
5012 mono_image_init (&image
->image
);
5014 image
->token_fixups
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
);
5015 image
->method_to_table_idx
= g_hash_table_new (NULL
, NULL
);
5016 image
->field_to_table_idx
= g_hash_table_new (NULL
, NULL
);
5017 image
->method_aux_hash
= g_hash_table_new (NULL
, NULL
);
5018 image
->handleref
= g_hash_table_new (NULL
, NULL
);
5019 image
->handleref_managed
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
);
5020 image
->tokens
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
5021 image
->generic_def_objects
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
5022 image
->methodspec
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
);
5023 image
->typespec
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
5024 image
->typeref
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
5025 image
->blob_cache
= g_hash_table_new ((GHashFunc
)mono_blob_entry_hash
, (GCompareFunc
)mono_blob_entry_equal
);
5026 image
->gen_params
= g_ptr_array_new ();
5028 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
5029 string_heap_init (&image
->sheap
);
5030 mono_image_add_stream_data (&image
->us
, "", 1);
5031 add_to_blob_cached (image
, (char*) "", 1, NULL
, 0);
5032 /* import tables... */
5033 mono_image_add_stream_data (&image
->code
, (char*)entrycode
, sizeof (entrycode
));
5034 image
->iat_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two IAT entries */
5035 image
->idt_offset
= mono_image_add_stream_zero (&image
->code
, 2 * sizeof (MonoIDT
)); /* two IDT entries */
5036 image
->imp_names_offset
= mono_image_add_stream_zero (&image
->code
, 2); /* flags for name entry */
5037 mono_image_add_stream_data (&image
->code
, "_CorExeMain", 12);
5038 mono_image_add_stream_data (&image
->code
, "mscoree.dll", 12);
5039 image
->ilt_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two ILT entries */
5040 stream_data_align (&image
->code
);
5042 image
->cli_header_offset
= mono_image_add_stream_zero (&image
->code
, sizeof (MonoCLIHeader
));
5044 for (i
=0; i
< MONO_TABLE_NUM
; ++i
) {
5045 image
->tables
[i
].next_idx
= 1;
5046 image
->tables
[i
].columns
= table_sizes
[i
];
5049 image
->image
.assembly
= (MonoAssembly
*)assembly
;
5050 image
->run
= assembly
->run
;
5051 image
->save
= assembly
->save
;
5052 image
->pe_kind
= 0x1; /* ILOnly */
5053 image
->machine
= 0x14c; /* I386 */
5055 mono_profiler_module_loaded (&image
->image
, MONO_PROFILE_OK
);
5062 free_blob_cache_entry (gpointer key
, gpointer val
, gpointer user_data
)
5068 mono_dynamic_image_free (MonoDynamicImage
*image
)
5070 MonoDynamicImage
*di
= image
;
5075 mono_g_hash_table_destroy (di
->methodspec
);
5077 g_hash_table_destroy (di
->typespec
);
5079 g_hash_table_destroy (di
->typeref
);
5081 g_hash_table_destroy (di
->handleref
);
5082 if (di
->handleref_managed
)
5083 mono_g_hash_table_destroy (di
->handleref_managed
);
5085 mono_g_hash_table_destroy (di
->tokens
);
5086 if (di
->generic_def_objects
)
5087 mono_g_hash_table_destroy (di
->generic_def_objects
);
5088 if (di
->blob_cache
) {
5089 g_hash_table_foreach (di
->blob_cache
, free_blob_cache_entry
, NULL
);
5090 g_hash_table_destroy (di
->blob_cache
);
5092 if (di
->standalonesig_cache
)
5093 g_hash_table_destroy (di
->standalonesig_cache
);
5094 for (list
= di
->array_methods
; list
; list
= list
->next
) {
5095 ArrayMethod
*am
= (ArrayMethod
*)list
->data
;
5100 g_list_free (di
->array_methods
);
5101 if (di
->gen_params
) {
5102 for (i
= 0; i
< di
->gen_params
->len
; i
++) {
5103 GenericParamTableEntry
*entry
= g_ptr_array_index (di
->gen_params
, i
);
5104 if (entry
->gparam
->type
.type
) {
5105 MonoGenericParam
*param
= entry
->gparam
->type
.type
->data
.generic_param
;
5106 g_free ((char*)mono_generic_param_info (param
)->name
);
5109 mono_gc_deregister_root ((char*) &entry
->gparam
);
5112 g_ptr_array_free (di
->gen_params
, TRUE
);
5114 if (di
->token_fixups
)
5115 mono_g_hash_table_destroy (di
->token_fixups
);
5116 if (di
->method_to_table_idx
)
5117 g_hash_table_destroy (di
->method_to_table_idx
);
5118 if (di
->field_to_table_idx
)
5119 g_hash_table_destroy (di
->field_to_table_idx
);
5120 if (di
->method_aux_hash
)
5121 g_hash_table_destroy (di
->method_aux_hash
);
5122 g_free (di
->strong_name
);
5123 g_free (di
->win32_res
);
5125 g_free (di
->public_key
);
5127 /*g_print ("string heap destroy for image %p\n", di);*/
5128 mono_dynamic_stream_reset (&di
->sheap
);
5129 mono_dynamic_stream_reset (&di
->code
);
5130 mono_dynamic_stream_reset (&di
->resources
);
5131 mono_dynamic_stream_reset (&di
->us
);
5132 mono_dynamic_stream_reset (&di
->blob
);
5133 mono_dynamic_stream_reset (&di
->tstream
);
5134 mono_dynamic_stream_reset (&di
->guid
);
5135 for (i
= 0; i
< MONO_TABLE_NUM
; ++i
) {
5136 g_free (di
->tables
[i
].values
);
5140 #ifndef DISABLE_REFLECTION_EMIT
5143 * mono_image_basic_init:
5144 * @assembly: an assembly builder object
5146 * Create the MonoImage that represents the assembly builder and setup some
5147 * of the helper hash table and the basic metadata streams.
5150 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
5152 MonoDynamicAssembly
*assembly
;
5153 MonoDynamicImage
*image
;
5154 MonoDomain
*domain
= mono_object_domain (assemblyb
);
5156 MONO_ARCH_SAVE_REGS
;
5158 if (assemblyb
->dynamic_assembly
)
5162 assembly
= assemblyb
->dynamic_assembly
= GC_MALLOC (sizeof (MonoDynamicAssembly
));
5164 assembly
= assemblyb
->dynamic_assembly
= g_new0 (MonoDynamicAssembly
, 1);
5167 mono_profiler_assembly_event (&assembly
->assembly
, MONO_PROFILE_START_LOAD
);
5169 assembly
->assembly
.ref_count
= 1;
5170 assembly
->assembly
.dynamic
= TRUE
;
5171 assembly
->assembly
.corlib_internal
= assemblyb
->corlib_internal
;
5172 assemblyb
->assembly
.assembly
= (MonoAssembly
*)assembly
;
5173 assembly
->assembly
.basedir
= mono_string_to_utf8 (assemblyb
->dir
);
5174 if (assemblyb
->culture
)
5175 assembly
->assembly
.aname
.culture
= mono_string_to_utf8 (assemblyb
->culture
);
5177 assembly
->assembly
.aname
.culture
= g_strdup ("");
5179 if (assemblyb
->version
) {
5180 char *vstr
= mono_string_to_utf8 (assemblyb
->version
);
5181 char **version
= g_strsplit (vstr
, ".", 4);
5182 char **parts
= version
;
5183 assembly
->assembly
.aname
.major
= atoi (*parts
++);
5184 assembly
->assembly
.aname
.minor
= atoi (*parts
++);
5185 assembly
->assembly
.aname
.build
= *parts
!= NULL
? atoi (*parts
++) : 0;
5186 assembly
->assembly
.aname
.revision
= *parts
!= NULL
? atoi (*parts
) : 0;
5188 g_strfreev (version
);
5191 assembly
->assembly
.aname
.major
= 0;
5192 assembly
->assembly
.aname
.minor
= 0;
5193 assembly
->assembly
.aname
.build
= 0;
5194 assembly
->assembly
.aname
.revision
= 0;
5197 assembly
->run
= assemblyb
->access
!= 2;
5198 assembly
->save
= assemblyb
->access
!= 1;
5199 assembly
->domain
= domain
;
5201 image
= create_dynamic_mono_image (assembly
, mono_string_to_utf8 (assemblyb
->name
), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5202 image
->initial_image
= TRUE
;
5203 assembly
->assembly
.aname
.name
= image
->image
.name
;
5204 assembly
->assembly
.image
= &image
->image
;
5205 if (assemblyb
->pktoken
&& assemblyb
->pktoken
->max_length
) {
5206 /* -1 to correct for the trailing NULL byte */
5207 if (assemblyb
->pktoken
->max_length
!= MONO_PUBLIC_KEY_TOKEN_LENGTH
- 1) {
5208 g_error ("Public key token length invalid for assembly %s: %i", assembly
->assembly
.aname
.name
, assemblyb
->pktoken
->max_length
);
5210 memcpy (&assembly
->assembly
.aname
.public_key_token
, mono_array_addr (assemblyb
->pktoken
, guint8
, 0), assemblyb
->pktoken
->max_length
);
5213 mono_domain_assemblies_lock (domain
);
5214 domain
->domain_assemblies
= g_slist_prepend (domain
->domain_assemblies
, assembly
);
5215 mono_domain_assemblies_unlock (domain
);
5217 register_assembly (mono_object_domain (assemblyb
), &assemblyb
->assembly
, &assembly
->assembly
);
5219 mono_profiler_assembly_loaded (&assembly
->assembly
, MONO_PROFILE_OK
);
5221 mono_assembly_invoke_load_hook ((MonoAssembly
*)assembly
);
5224 #endif /* !DISABLE_REFLECTION_EMIT */
5226 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5229 calc_section_size (MonoDynamicImage
*assembly
)
5233 /* alignment constraints */
5234 mono_image_add_stream_zero (&assembly
->code
, 4 - (assembly
->code
.index
% 4));
5235 g_assert ((assembly
->code
.index
% 4) == 0);
5236 assembly
->meta_size
+= 3;
5237 assembly
->meta_size
&= ~3;
5238 mono_image_add_stream_zero (&assembly
->resources
, 4 - (assembly
->resources
.index
% 4));
5239 g_assert ((assembly
->resources
.index
% 4) == 0);
5241 assembly
->sections
[MONO_SECTION_TEXT
].size
= assembly
->meta_size
+ assembly
->code
.index
+ assembly
->resources
.index
+ assembly
->strong_name_size
;
5242 assembly
->sections
[MONO_SECTION_TEXT
].attrs
= SECT_FLAGS_HAS_CODE
| SECT_FLAGS_MEM_EXECUTE
| SECT_FLAGS_MEM_READ
;
5245 if (assembly
->win32_res
) {
5246 guint32 res_size
= (assembly
->win32_res_size
+ 3) & ~3;
5248 assembly
->sections
[MONO_SECTION_RSRC
].size
= res_size
;
5249 assembly
->sections
[MONO_SECTION_RSRC
].attrs
= SECT_FLAGS_HAS_INITIALIZED_DATA
| SECT_FLAGS_MEM_READ
;
5253 assembly
->sections
[MONO_SECTION_RELOC
].size
= 12;
5254 assembly
->sections
[MONO_SECTION_RELOC
].attrs
= SECT_FLAGS_MEM_READ
| SECT_FLAGS_MEM_DISCARDABLE
| SECT_FLAGS_HAS_INITIALIZED_DATA
;
5264 MonoReflectionWin32Resource
*win32_res
; /* Only for leaf nodes */
5268 resource_tree_compare_by_id (gconstpointer a
, gconstpointer b
)
5270 ResTreeNode
*t1
= (ResTreeNode
*)a
;
5271 ResTreeNode
*t2
= (ResTreeNode
*)b
;
5273 return t1
->id
- t2
->id
;
5277 * resource_tree_create:
5279 * Organize the resources into a resource tree.
5281 static ResTreeNode
*
5282 resource_tree_create (MonoArray
*win32_resources
)
5284 ResTreeNode
*tree
, *res_node
, *type_node
, *lang_node
;
5288 tree
= g_new0 (ResTreeNode
, 1);
5290 for (i
= 0; i
< mono_array_length (win32_resources
); ++i
) {
5291 MonoReflectionWin32Resource
*win32_res
=
5292 (MonoReflectionWin32Resource
*)mono_array_addr (win32_resources
, MonoReflectionWin32Resource
, i
);
5296 /* FIXME: BUG: this stores managed references in unmanaged memory */
5297 lang_node
= g_new0 (ResTreeNode
, 1);
5298 lang_node
->id
= win32_res
->lang_id
;
5299 lang_node
->win32_res
= win32_res
;
5301 /* Create type node if neccesary */
5303 for (l
= tree
->children
; l
; l
= l
->next
)
5304 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_type
) {
5305 type_node
= (ResTreeNode
*)l
->data
;
5310 type_node
= g_new0 (ResTreeNode
, 1);
5311 type_node
->id
= win32_res
->res_type
;
5314 * The resource types have to be sorted otherwise
5315 * Windows Explorer can't display the version information.
5317 tree
->children
= g_slist_insert_sorted (tree
->children
,
5318 type_node
, resource_tree_compare_by_id
);
5321 /* Create res node if neccesary */
5323 for (l
= type_node
->children
; l
; l
= l
->next
)
5324 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_id
) {
5325 res_node
= (ResTreeNode
*)l
->data
;
5330 res_node
= g_new0 (ResTreeNode
, 1);
5331 res_node
->id
= win32_res
->res_id
;
5332 type_node
->children
= g_slist_append (type_node
->children
, res_node
);
5335 res_node
->children
= g_slist_append (res_node
->children
, lang_node
);
5342 * resource_tree_encode:
5344 * Encode the resource tree into the format used in the PE file.
5347 resource_tree_encode (ResTreeNode
*node
, char *begin
, char *p
, char **endbuf
)
5350 MonoPEResourceDir dir
;
5351 MonoPEResourceDirEntry dir_entry
;
5352 MonoPEResourceDataEntry data_entry
;
5354 guint32 res_id_entries
;
5357 * For the format of the resource directory, see the article
5358 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5362 memset (&dir
, 0, sizeof (dir
));
5363 memset (&dir_entry
, 0, sizeof (dir_entry
));
5364 memset (&data_entry
, 0, sizeof (data_entry
));
5366 g_assert (sizeof (dir
) == 16);
5367 g_assert (sizeof (dir_entry
) == 8);
5368 g_assert (sizeof (data_entry
) == 16);
5370 node
->offset
= p
- begin
;
5372 /* IMAGE_RESOURCE_DIRECTORY */
5373 res_id_entries
= g_slist_length (node
->children
);
5374 dir
.res_id_entries
= GUINT16_TO_LE (res_id_entries
);
5376 memcpy (p
, &dir
, sizeof (dir
));
5379 /* Reserve space for entries */
5381 p
+= sizeof (dir_entry
) * res_id_entries
;
5383 /* Write children */
5384 for (l
= node
->children
; l
; l
= l
->next
) {
5385 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5387 if (child
->win32_res
) {
5390 child
->offset
= p
- begin
;
5392 /* IMAGE_RESOURCE_DATA_ENTRY */
5393 data_entry
.rde_data_offset
= GUINT32_TO_LE (p
- begin
+ sizeof (data_entry
));
5394 size
= mono_array_length (child
->win32_res
->res_data
);
5395 data_entry
.rde_size
= GUINT32_TO_LE (size
);
5397 memcpy (p
, &data_entry
, sizeof (data_entry
));
5398 p
+= sizeof (data_entry
);
5400 memcpy (p
, mono_array_addr (child
->win32_res
->res_data
, char, 0), size
);
5403 resource_tree_encode (child
, begin
, p
, &p
);
5407 /* IMAGE_RESOURCE_ENTRY */
5408 for (l
= node
->children
; l
; l
= l
->next
) {
5409 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5411 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry
, FALSE
, child
->id
);
5412 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry
, !child
->win32_res
, child
->offset
);
5414 memcpy (entries
, &dir_entry
, sizeof (dir_entry
));
5415 entries
+= sizeof (dir_entry
);
5422 resource_tree_free (ResTreeNode
* node
)
5425 for (list
= node
->children
; list
; list
= list
->next
)
5426 resource_tree_free ((ResTreeNode
*)list
->data
);
5427 g_slist_free(node
->children
);
5432 assembly_add_win32_resources (MonoDynamicImage
*assembly
, MonoReflectionAssemblyBuilder
*assemblyb
)
5437 MonoReflectionWin32Resource
*win32_res
;
5440 if (!assemblyb
->win32_resources
)
5444 * Resources are stored in a three level tree inside the PE file.
5445 * - level one contains a node for each type of resource
5446 * - level two contains a node for each resource
5447 * - level three contains a node for each instance of a resource for a
5448 * specific language.
5451 tree
= resource_tree_create (assemblyb
->win32_resources
);
5453 /* Estimate the size of the encoded tree */
5455 for (i
= 0; i
< mono_array_length (assemblyb
->win32_resources
); ++i
) {
5456 win32_res
= (MonoReflectionWin32Resource
*)mono_array_addr (assemblyb
->win32_resources
, MonoReflectionWin32Resource
, i
);
5457 size
+= mono_array_length (win32_res
->res_data
);
5459 /* Directory structure */
5460 size
+= mono_array_length (assemblyb
->win32_resources
) * 256;
5461 p
= buf
= g_malloc (size
);
5463 resource_tree_encode (tree
, p
, p
, &p
);
5465 g_assert (p
- buf
<= size
);
5467 assembly
->win32_res
= g_malloc (p
- buf
);
5468 assembly
->win32_res_size
= p
- buf
;
5469 memcpy (assembly
->win32_res
, buf
, p
- buf
);
5472 resource_tree_free (tree
);
5476 fixup_resource_directory (char *res_section
, char *p
, guint32 rva
)
5478 MonoPEResourceDir
*dir
= (MonoPEResourceDir
*)p
;
5481 p
+= sizeof (MonoPEResourceDir
);
5482 for (i
= 0; i
< GUINT16_FROM_LE (dir
->res_named_entries
) + GUINT16_FROM_LE (dir
->res_id_entries
); ++i
) {
5483 MonoPEResourceDirEntry
*dir_entry
= (MonoPEResourceDirEntry
*)p
;
5484 char *child
= res_section
+ MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry
);
5485 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry
)) {
5486 fixup_resource_directory (res_section
, child
, rva
);
5488 MonoPEResourceDataEntry
*data_entry
= (MonoPEResourceDataEntry
*)child
;
5489 data_entry
->rde_data_offset
= GUINT32_TO_LE (GUINT32_FROM_LE (data_entry
->rde_data_offset
) + rva
);
5492 p
+= sizeof (MonoPEResourceDirEntry
);
5497 checked_write_file (HANDLE f
, gconstpointer buffer
, guint32 numbytes
)
5500 if (!WriteFile (f
, buffer
, numbytes
, &dummy
, NULL
))
5501 g_error ("WriteFile returned %d\n", GetLastError ());
5505 * mono_image_create_pefile:
5506 * @mb: a module builder object
5508 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5509 * assembly->pefile where it can be easily retrieved later in chunks.
5512 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5514 MonoMSDOSHeader
*msdos
;
5515 MonoDotNetHeader
*header
;
5516 MonoSectionTable
*section
;
5517 MonoCLIHeader
*cli_header
;
5518 guint32 size
, image_size
, virtual_base
, text_offset
;
5519 guint32 header_start
, section_start
, file_offset
, virtual_offset
;
5520 MonoDynamicImage
*assembly
;
5521 MonoReflectionAssemblyBuilder
*assemblyb
;
5522 MonoDynamicStream pefile_stream
= {0};
5523 MonoDynamicStream
*pefile
= &pefile_stream
;
5525 guint32
*rva
, value
;
5527 static const unsigned char msheader
[] = {
5528 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5529 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5530 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5531 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5532 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5533 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5534 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5535 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5538 assemblyb
= mb
->assemblyb
;
5540 mono_image_basic_init (assemblyb
);
5541 assembly
= mb
->dynamic_image
;
5543 assembly
->pe_kind
= assemblyb
->pe_kind
;
5544 assembly
->machine
= assemblyb
->machine
;
5545 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->pe_kind
= assemblyb
->pe_kind
;
5546 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->machine
= assemblyb
->machine
;
5548 mono_image_build_metadata (mb
);
5550 if (mb
->is_main
&& assemblyb
->resources
) {
5551 int len
= mono_array_length (assemblyb
->resources
);
5552 for (i
= 0; i
< len
; ++i
)
5553 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (assemblyb
->resources
, MonoReflectionResource
, i
));
5556 if (mb
->resources
) {
5557 int len
= mono_array_length (mb
->resources
);
5558 for (i
= 0; i
< len
; ++i
)
5559 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (mb
->resources
, MonoReflectionResource
, i
));
5562 build_compressed_metadata (assembly
);
5565 assembly_add_win32_resources (assembly
, assemblyb
);
5567 nsections
= calc_section_size (assembly
);
5569 /* The DOS header and stub */
5570 g_assert (sizeof (MonoMSDOSHeader
) == sizeof (msheader
));
5571 mono_image_add_stream_data (pefile
, (char*)msheader
, sizeof (msheader
));
5573 /* the dotnet header */
5574 header_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoDotNetHeader
));
5576 /* the section tables */
5577 section_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoSectionTable
) * nsections
);
5579 file_offset
= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5580 virtual_offset
= VIRT_ALIGN
;
5583 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5584 if (!assembly
->sections
[i
].size
)
5587 file_offset
+= FILE_ALIGN
- 1;
5588 file_offset
&= ~(FILE_ALIGN
- 1);
5589 virtual_offset
+= VIRT_ALIGN
- 1;
5590 virtual_offset
&= ~(VIRT_ALIGN
- 1);
5592 assembly
->sections
[i
].offset
= file_offset
;
5593 assembly
->sections
[i
].rva
= virtual_offset
;
5595 file_offset
+= assembly
->sections
[i
].size
;
5596 virtual_offset
+= assembly
->sections
[i
].size
;
5597 image_size
+= (assembly
->sections
[i
].size
+ VIRT_ALIGN
- 1) & ~(VIRT_ALIGN
- 1);
5600 file_offset
+= FILE_ALIGN
- 1;
5601 file_offset
&= ~(FILE_ALIGN
- 1);
5603 image_size
+= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5605 /* back-patch info */
5606 msdos
= (MonoMSDOSHeader
*)pefile
->data
;
5607 msdos
->pe_offset
= GUINT32_FROM_LE (sizeof (MonoMSDOSHeader
));
5609 header
= (MonoDotNetHeader
*)(pefile
->data
+ header_start
);
5610 header
->pesig
[0] = 'P';
5611 header
->pesig
[1] = 'E';
5613 header
->coff
.coff_machine
= GUINT16_FROM_LE (assemblyb
->machine
);
5614 header
->coff
.coff_sections
= GUINT16_FROM_LE (nsections
);
5615 header
->coff
.coff_time
= GUINT32_FROM_LE (time (NULL
));
5616 header
->coff
.coff_opt_header_size
= GUINT16_FROM_LE (sizeof (MonoDotNetHeader
) - sizeof (MonoCOFFHeader
) - 4);
5617 if (assemblyb
->pekind
== 1) {
5619 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x210e);
5622 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x010e);
5625 virtual_base
= 0x400000; /* FIXME: 0x10000000 if a DLL */
5627 header
->pe
.pe_magic
= GUINT16_FROM_LE (0x10B);
5628 header
->pe
.pe_major
= 6;
5629 header
->pe
.pe_minor
= 0;
5630 size
= assembly
->sections
[MONO_SECTION_TEXT
].size
;
5631 size
+= FILE_ALIGN
- 1;
5632 size
&= ~(FILE_ALIGN
- 1);
5633 header
->pe
.pe_code_size
= GUINT32_FROM_LE(size
);
5634 size
= assembly
->sections
[MONO_SECTION_RSRC
].size
;
5635 size
+= FILE_ALIGN
- 1;
5636 size
&= ~(FILE_ALIGN
- 1);
5637 header
->pe
.pe_data_size
= GUINT32_FROM_LE(size
);
5638 g_assert (START_TEXT_RVA
== assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5639 header
->pe
.pe_rva_code_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5640 header
->pe
.pe_rva_data_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5641 /* pe_rva_entry_point always at the beginning of the text section */
5642 header
->pe
.pe_rva_entry_point
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5644 header
->nt
.pe_image_base
= GUINT32_FROM_LE (virtual_base
);
5645 header
->nt
.pe_section_align
= GUINT32_FROM_LE (VIRT_ALIGN
);
5646 header
->nt
.pe_file_alignment
= GUINT32_FROM_LE (FILE_ALIGN
);
5647 header
->nt
.pe_os_major
= GUINT16_FROM_LE (4);
5648 header
->nt
.pe_os_minor
= GUINT16_FROM_LE (0);
5649 header
->nt
.pe_subsys_major
= GUINT16_FROM_LE (4);
5650 size
= section_start
;
5651 size
+= FILE_ALIGN
- 1;
5652 size
&= ~(FILE_ALIGN
- 1);
5653 header
->nt
.pe_header_size
= GUINT32_FROM_LE (size
);
5655 size
+= VIRT_ALIGN
- 1;
5656 size
&= ~(VIRT_ALIGN
- 1);
5657 header
->nt
.pe_image_size
= GUINT32_FROM_LE (size
);
5660 // Translate the PEFileKind value to the value expected by the Windows loader
5666 // PEFileKinds.Dll == 1
5667 // PEFileKinds.ConsoleApplication == 2
5668 // PEFileKinds.WindowApplication == 3
5671 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5672 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5674 if (assemblyb
->pekind
== 3)
5679 header
->nt
.pe_subsys_required
= GUINT16_FROM_LE (kind
);
5681 header
->nt
.pe_stack_reserve
= GUINT32_FROM_LE (0x00100000);
5682 header
->nt
.pe_stack_commit
= GUINT32_FROM_LE (0x00001000);
5683 header
->nt
.pe_heap_reserve
= GUINT32_FROM_LE (0x00100000);
5684 header
->nt
.pe_heap_commit
= GUINT32_FROM_LE (0x00001000);
5685 header
->nt
.pe_loader_flags
= GUINT32_FROM_LE (0);
5686 header
->nt
.pe_data_dir_count
= GUINT32_FROM_LE (16);
5688 /* fill data directory entries */
5690 header
->datadir
.pe_resource_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].size
);
5691 header
->datadir
.pe_resource_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5693 header
->datadir
.pe_reloc_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].size
);
5694 header
->datadir
.pe_reloc_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].rva
);
5696 header
->datadir
.pe_cli_header
.size
= GUINT32_FROM_LE (72);
5697 header
->datadir
.pe_cli_header
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->cli_header_offset
);
5698 header
->datadir
.pe_iat
.size
= GUINT32_FROM_LE (8);
5699 header
->datadir
.pe_iat
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5700 /* patch entrypoint name */
5701 if (assemblyb
->pekind
== 1)
5702 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorDllMain", 12);
5704 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorExeMain", 12);
5705 /* patch imported function RVA name */
5706 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->iat_offset
);
5707 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
);
5709 /* the import table */
5710 header
->datadir
.pe_import_table
.size
= GUINT32_FROM_LE (79); /* FIXME: magic number? */
5711 header
->datadir
.pe_import_table
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->idt_offset
);
5712 /* patch imported dll RVA name and other entries in the dir */
5713 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, name_rva
));
5714 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
+ 14); /* 14 is hint+strlen+1 of func name */
5715 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_address_table_rva
));
5716 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5717 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_lookup_table
));
5718 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->ilt_offset
);
5720 p
= (guchar
*)(assembly
->code
.data
+ assembly
->ilt_offset
);
5721 value
= (assembly
->text_rva
+ assembly
->imp_names_offset
);
5722 *p
++ = (value
) & 0xff;
5723 *p
++ = (value
>> 8) & (0xff);
5724 *p
++ = (value
>> 16) & (0xff);
5725 *p
++ = (value
>> 24) & (0xff);
5727 /* the CLI header info */
5728 cli_header
= (MonoCLIHeader
*)(assembly
->code
.data
+ assembly
->cli_header_offset
);
5729 cli_header
->ch_size
= GUINT32_FROM_LE (72);
5730 cli_header
->ch_runtime_major
= GUINT16_FROM_LE (2);
5731 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (5);
5732 cli_header
->ch_flags
= GUINT32_FROM_LE (assemblyb
->pe_kind
);
5733 if (assemblyb
->entry_point
) {
5734 guint32 table_idx
= 0;
5735 if (!strcmp (assemblyb
->entry_point
->object
.vtable
->klass
->name
, "MethodBuilder")) {
5736 MonoReflectionMethodBuilder
*methodb
= (MonoReflectionMethodBuilder
*)assemblyb
->entry_point
;
5737 table_idx
= methodb
->table_idx
;
5739 table_idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, assemblyb
->entry_point
->method
));
5741 cli_header
->ch_entry_point
= GUINT32_FROM_LE (table_idx
| MONO_TOKEN_METHOD_DEF
);
5743 cli_header
->ch_entry_point
= GUINT32_FROM_LE (0);
5745 /* The embedded managed resources */
5746 text_offset
= assembly
->text_rva
+ assembly
->code
.index
;
5747 cli_header
->ch_resources
.rva
= GUINT32_FROM_LE (text_offset
);
5748 cli_header
->ch_resources
.size
= GUINT32_FROM_LE (assembly
->resources
.index
);
5749 text_offset
+= assembly
->resources
.index
;
5750 cli_header
->ch_metadata
.rva
= GUINT32_FROM_LE (text_offset
);
5751 cli_header
->ch_metadata
.size
= GUINT32_FROM_LE (assembly
->meta_size
);
5752 text_offset
+= assembly
->meta_size
;
5753 if (assembly
->strong_name_size
) {
5754 cli_header
->ch_strong_name
.rva
= GUINT32_FROM_LE (text_offset
);
5755 cli_header
->ch_strong_name
.size
= GUINT32_FROM_LE (assembly
->strong_name_size
);
5756 text_offset
+= assembly
->strong_name_size
;
5759 /* write the section tables and section content */
5760 section
= (MonoSectionTable
*)(pefile
->data
+ section_start
);
5761 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5762 static const char section_names
[][7] = {
5763 ".text", ".rsrc", ".reloc"
5765 if (!assembly
->sections
[i
].size
)
5767 strcpy (section
->st_name
, section_names
[i
]);
5768 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5769 section
->st_virtual_address
= GUINT32_FROM_LE (assembly
->sections
[i
].rva
);
5770 section
->st_virtual_size
= GUINT32_FROM_LE (assembly
->sections
[i
].size
);
5771 section
->st_raw_data_size
= GUINT32_FROM_LE (GUINT32_TO_LE (section
->st_virtual_size
) + (FILE_ALIGN
- 1));
5772 section
->st_raw_data_size
&= GUINT32_FROM_LE (~(FILE_ALIGN
- 1));
5773 section
->st_raw_data_ptr
= GUINT32_FROM_LE (assembly
->sections
[i
].offset
);
5774 section
->st_flags
= GUINT32_FROM_LE (assembly
->sections
[i
].attrs
);
5778 checked_write_file (file
, pefile
->data
, pefile
->index
);
5780 mono_dynamic_stream_reset (pefile
);
5782 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5783 if (!assembly
->sections
[i
].size
)
5786 if (SetFilePointer (file
, assembly
->sections
[i
].offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5787 g_error ("SetFilePointer returned %d\n", GetLastError ());
5790 case MONO_SECTION_TEXT
:
5791 /* patch entry point */
5792 p
= (guchar
*)(assembly
->code
.data
+ 2);
5793 value
= (virtual_base
+ assembly
->text_rva
+ assembly
->iat_offset
);
5794 *p
++ = (value
) & 0xff;
5795 *p
++ = (value
>> 8) & 0xff;
5796 *p
++ = (value
>> 16) & 0xff;
5797 *p
++ = (value
>> 24) & 0xff;
5799 checked_write_file (file
, assembly
->code
.data
, assembly
->code
.index
);
5800 checked_write_file (file
, assembly
->resources
.data
, assembly
->resources
.index
);
5801 checked_write_file (file
, assembly
->image
.raw_metadata
, assembly
->meta_size
);
5802 checked_write_file (file
, assembly
->strong_name
, assembly
->strong_name_size
);
5805 g_free (assembly
->image
.raw_metadata
);
5807 case MONO_SECTION_RELOC
: {
5811 guint16 type_and_offset
;
5815 g_assert (sizeof (reloc
) == 12);
5817 reloc
.page_rva
= GUINT32_FROM_LE (assembly
->text_rva
);
5818 reloc
.block_size
= GUINT32_FROM_LE (12);
5821 * the entrypoint is always at the start of the text section
5822 * 3 is IMAGE_REL_BASED_HIGHLOW
5823 * 2 is patch_size_rva - text_rva
5825 reloc
.type_and_offset
= GUINT16_FROM_LE ((3 << 12) + (2));
5828 checked_write_file (file
, &reloc
, sizeof (reloc
));
5832 case MONO_SECTION_RSRC
:
5833 if (assembly
->win32_res
) {
5835 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5836 fixup_resource_directory (assembly
->win32_res
, assembly
->win32_res
, assembly
->sections
[i
].rva
);
5837 checked_write_file (file
, assembly
->win32_res
, assembly
->win32_res_size
);
5841 g_assert_not_reached ();
5845 /* check that the file is properly padded */
5846 if (SetFilePointer (file
, file_offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5847 g_error ("SetFilePointer returned %d\n", GetLastError ());
5848 if (! SetEndOfFile (file
))
5849 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5851 mono_dynamic_stream_reset (&assembly
->code
);
5852 mono_dynamic_stream_reset (&assembly
->us
);
5853 mono_dynamic_stream_reset (&assembly
->blob
);
5854 mono_dynamic_stream_reset (&assembly
->guid
);
5855 mono_dynamic_stream_reset (&assembly
->sheap
);
5857 g_hash_table_foreach (assembly
->blob_cache
, (GHFunc
)g_free
, NULL
);
5858 g_hash_table_destroy (assembly
->blob_cache
);
5859 assembly
->blob_cache
= NULL
;
5862 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5865 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5867 g_assert_not_reached ();
5870 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5872 #ifndef DISABLE_REFLECTION_EMIT
5874 MonoReflectionModule
*
5875 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
5879 MonoImageOpenStatus status
;
5880 MonoDynamicAssembly
*assembly
;
5881 guint32 module_count
;
5882 MonoImage
**new_modules
;
5883 gboolean
*new_modules_loaded
;
5885 name
= mono_string_to_utf8 (fileName
);
5887 image
= mono_image_open (name
, &status
);
5890 if (status
== MONO_IMAGE_ERROR_ERRNO
)
5891 exc
= mono_get_exception_file_not_found (fileName
);
5893 exc
= mono_get_exception_bad_image_format (name
);
5895 mono_raise_exception (exc
);
5900 assembly
= ab
->dynamic_assembly
;
5901 image
->assembly
= (MonoAssembly
*)assembly
;
5903 module_count
= image
->assembly
->image
->module_count
;
5904 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5905 new_modules_loaded
= g_new0 (gboolean
, module_count
+ 1);
5907 if (image
->assembly
->image
->modules
)
5908 memcpy (new_modules
, image
->assembly
->image
->modules
, module_count
* sizeof (MonoImage
*));
5909 if (image
->assembly
->image
->modules_loaded
)
5910 memcpy (new_modules_loaded
, image
->assembly
->image
->modules_loaded
, module_count
* sizeof (gboolean
));
5911 new_modules
[module_count
] = image
;
5912 new_modules_loaded
[module_count
] = TRUE
;
5913 mono_image_addref (image
);
5915 g_free (image
->assembly
->image
->modules
);
5916 image
->assembly
->image
->modules
= new_modules
;
5917 image
->assembly
->image
->modules_loaded
= new_modules_loaded
;
5918 image
->assembly
->image
->module_count
++;
5920 mono_assembly_load_references (image
, &status
);
5922 mono_image_close (image
);
5923 mono_raise_exception (mono_get_exception_file_not_found (fileName
));
5926 return mono_module_get_object (mono_domain_get (), image
);
5929 #endif /* DISABLE_REFLECTION_EMIT */
5932 * We need to return always the same object for MethodInfo, FieldInfo etc..
5933 * but we need to consider the reflected type.
5934 * type uses a different hash, since it uses custom hash/equal functions.
5939 MonoClass
*refclass
;
5943 reflected_equal (gconstpointer a
, gconstpointer b
) {
5944 const ReflectedEntry
*ea
= a
;
5945 const ReflectedEntry
*eb
= b
;
5947 return (ea
->item
== eb
->item
) && (ea
->refclass
== eb
->refclass
);
5951 reflected_hash (gconstpointer a
) {
5952 const ReflectedEntry
*ea
= a
;
5953 return mono_aligned_addr_hash (ea
->item
);
5956 #define CHECK_OBJECT(t,p,k) \
5962 mono_domain_lock (domain); \
5963 if (!domain->refobject_hash) \
5964 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5965 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5966 mono_domain_unlock (domain); \
5969 mono_domain_unlock (domain); \
5972 #ifdef HAVE_BOEHM_GC
5973 /* ReflectedEntry doesn't need to be GC tracked */
5974 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5975 #define FREE_REFENTRY(entry) g_free ((entry))
5976 #define REFENTRY_REQUIRES_CLEANUP
5978 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5980 #define FREE_REFENTRY(entry)
5983 #define CACHE_OBJECT(t,p,o,k) \
5986 ReflectedEntry pe; \
5988 pe.refclass = (k); \
5989 mono_domain_lock (domain); \
5990 if (!domain->refobject_hash) \
5991 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5992 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5994 ReflectedEntry *e = ALLOC_REFENTRY; \
5996 e->refclass = (k); \
5997 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
6000 mono_domain_unlock (domain); \
6005 clear_cached_object (MonoDomain
*domain
, gpointer o
, MonoClass
*klass
)
6007 mono_domain_lock (domain
);
6008 if (domain
->refobject_hash
) {
6010 gpointer orig_pe
, orig_value
;
6013 pe
.refclass
= klass
;
6014 if (mono_g_hash_table_lookup_extended (domain
->refobject_hash
, &pe
, &orig_pe
, &orig_value
)) {
6015 mono_g_hash_table_remove (domain
->refobject_hash
, &pe
);
6016 FREE_REFENTRY (orig_pe
);
6019 mono_domain_unlock (domain
);
6022 #ifdef REFENTRY_REQUIRES_CLEANUP
6024 cleanup_refobject_hash (gpointer key
, gpointer value
, gpointer user_data
)
6026 FREE_REFENTRY (key
);
6031 mono_reflection_cleanup_domain (MonoDomain
*domain
)
6033 if (domain
->refobject_hash
) {
6034 /*let's avoid scanning the whole hashtable if not needed*/
6035 #ifdef REFENTRY_REQUIRES_CLEANUP
6036 mono_g_hash_table_foreach (domain
->refobject_hash
, cleanup_refobject_hash
, NULL
);
6038 mono_g_hash_table_destroy (domain
->refobject_hash
);
6039 domain
->refobject_hash
= NULL
;
6043 #ifndef DISABLE_REFLECTION_EMIT
6045 register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
)
6047 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
6051 register_module (MonoDomain
*domain
, MonoReflectionModuleBuilder
*res
, MonoDynamicImage
*module
)
6053 CACHE_OBJECT (MonoReflectionModuleBuilder
*, module
, res
, NULL
);
6057 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
6059 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
6060 MonoReflectionAssemblyBuilder
*ab
= moduleb
->assemblyb
;
6064 MonoImage
**new_modules
;
6066 char *name
, *fqname
;
6068 * FIXME: we already created an image in mono_image_basic_init (), but
6069 * we don't know which module it belongs to, since that is only
6070 * determined at assembly save time.
6072 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
6073 name
= mono_string_to_utf8 (ab
->name
);
6074 fqname
= mono_string_to_utf8_checked (moduleb
->module
.fqname
, &error
);
6075 if (!mono_error_ok (&error
)) {
6077 mono_error_raise_exception (&error
);
6079 image
= create_dynamic_mono_image (ab
->dynamic_assembly
, name
, fqname
);
6081 moduleb
->module
.image
= &image
->image
;
6082 moduleb
->dynamic_image
= image
;
6083 register_module (mono_object_domain (moduleb
), moduleb
, image
);
6085 /* register the module with the assembly */
6086 ass
= ab
->dynamic_assembly
->assembly
.image
;
6087 module_count
= ass
->module_count
;
6088 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
6091 memcpy (new_modules
, ass
->modules
, module_count
* sizeof (MonoImage
*));
6092 new_modules
[module_count
] = &image
->image
;
6093 mono_image_addref (&image
->image
);
6095 g_free (ass
->modules
);
6096 ass
->modules
= new_modules
;
6097 ass
->module_count
++;
6102 mono_image_set_wrappers_type (MonoReflectionModuleBuilder
*moduleb
, MonoReflectionType
*type
)
6104 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
6106 g_assert (type
->type
);
6107 image
->wrappers_type
= mono_class_from_mono_type (type
->type
);
6113 * mono_assembly_get_object:
6114 * @domain: an app domain
6115 * @assembly: an assembly
6117 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
6119 MonoReflectionAssembly
*
6120 mono_assembly_get_object (MonoDomain
*domain
, MonoAssembly
*assembly
)
6122 static MonoClass
*assembly_type
;
6123 MonoReflectionAssembly
*res
;
6125 CHECK_OBJECT (MonoReflectionAssembly
*, assembly
, NULL
);
6126 if (!assembly_type
) {
6127 MonoClass
*class = mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoAssembly");
6129 class = mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Assembly");
6131 assembly_type
= class;
6133 res
= (MonoReflectionAssembly
*)mono_object_new (domain
, assembly_type
);
6134 res
->assembly
= assembly
;
6136 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
6141 MonoReflectionModule
*
6142 mono_module_get_object (MonoDomain
*domain
, MonoImage
*image
)
6144 static MonoClass
*System_Reflection_Module
;
6145 MonoReflectionModule
*res
;
6148 CHECK_OBJECT (MonoReflectionModule
*, image
, NULL
);
6149 if (!System_Reflection_Module
)
6150 System_Reflection_Module
= mono_class_from_name (
6151 mono_defaults
.corlib
, "System.Reflection", "Module");
6152 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
6155 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
6157 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, image
->name
));
6158 basename
= g_path_get_basename (image
->name
);
6159 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, basename
));
6160 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, image
->module_name
));
6164 if (image
->assembly
->image
== image
) {
6165 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULE
, 1);
6169 if (image
->assembly
->image
->modules
) {
6170 for (i
= 0; i
< image
->assembly
->image
->module_count
; i
++) {
6171 if (image
->assembly
->image
->modules
[i
] == image
)
6172 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULEREF
, i
+ 1);
6174 g_assert (res
->token
);
6178 CACHE_OBJECT (MonoReflectionModule
*, image
, res
, NULL
);
6181 MonoReflectionModule
*
6182 mono_module_file_get_object (MonoDomain
*domain
, MonoImage
*image
, int table_index
)
6184 static MonoClass
*System_Reflection_Module
;
6185 MonoReflectionModule
*res
;
6186 MonoTableInfo
*table
;
6187 guint32 cols
[MONO_FILE_SIZE
];
6189 guint32 i
, name_idx
;
6192 if (!System_Reflection_Module
)
6193 System_Reflection_Module
= mono_class_from_name (
6194 mono_defaults
.corlib
, "System.Reflection", "Module");
6195 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
6197 table
= &image
->tables
[MONO_TABLE_FILE
];
6198 g_assert (table_index
< table
->rows
);
6199 mono_metadata_decode_row (table
, table_index
, cols
, MONO_FILE_SIZE
);
6202 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
6203 name
= mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]);
6205 /* Check whenever the row has a corresponding row in the moduleref table */
6206 table
= &image
->tables
[MONO_TABLE_MODULEREF
];
6207 for (i
= 0; i
< table
->rows
; ++i
) {
6208 name_idx
= mono_metadata_decode_row_col (table
, i
, MONO_MODULEREF_NAME
);
6209 val
= mono_metadata_string_heap (image
, name_idx
);
6210 if (strcmp (val
, name
) == 0)
6211 res
->image
= image
->modules
[i
];
6214 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, name
));
6215 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, name
));
6216 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, name
));
6217 res
->is_resource
= cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
;
6218 res
->token
= mono_metadata_make_token (MONO_TABLE_FILE
, table_index
+ 1);
6224 mymono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
6226 if ((t1
->type
!= t2
->type
) ||
6227 (t1
->byref
!= t2
->byref
))
6231 case MONO_TYPE_VOID
:
6232 case MONO_TYPE_BOOLEAN
:
6233 case MONO_TYPE_CHAR
:
6244 case MONO_TYPE_STRING
:
6247 case MONO_TYPE_OBJECT
:
6248 case MONO_TYPE_TYPEDBYREF
:
6250 case MONO_TYPE_VALUETYPE
:
6251 case MONO_TYPE_CLASS
:
6252 case MONO_TYPE_SZARRAY
:
6253 return t1
->data
.klass
== t2
->data
.klass
;
6255 return mymono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
);
6256 case MONO_TYPE_ARRAY
:
6257 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
6259 return t1
->data
.array
->eklass
== t2
->data
.array
->eklass
;
6260 case MONO_TYPE_GENERICINST
: {
6262 MonoGenericInst
*i1
= t1
->data
.generic_class
->context
.class_inst
;
6263 MonoGenericInst
*i2
= t2
->data
.generic_class
->context
.class_inst
;
6264 if (i1
->type_argc
!= i2
->type_argc
)
6266 if (!mono_metadata_type_equal (&t1
->data
.generic_class
->container_class
->byval_arg
,
6267 &t2
->data
.generic_class
->container_class
->byval_arg
))
6269 /* FIXME: we should probably just compare the instance pointers directly. */
6270 for (i
= 0; i
< i1
->type_argc
; ++i
) {
6271 if (!mono_metadata_type_equal (i1
->type_argv
[i
], i2
->type_argv
[i
]))
6277 case MONO_TYPE_MVAR
:
6278 return t1
->data
.generic_param
== t2
->data
.generic_param
;
6280 g_error ("implement type compare for %0x!", t1
->type
);
6288 mymono_metadata_type_hash (MonoType
*t1
)
6294 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
6296 case MONO_TYPE_VALUETYPE
:
6297 case MONO_TYPE_CLASS
:
6298 case MONO_TYPE_SZARRAY
:
6299 /* check if the distribution is good enough */
6300 return ((hash
<< 5) - hash
) ^ g_str_hash (t1
->data
.klass
->name
);
6302 return ((hash
<< 5) - hash
) ^ mymono_metadata_type_hash (t1
->data
.type
);
6303 case MONO_TYPE_GENERICINST
: {
6305 MonoGenericInst
*inst
= t1
->data
.generic_class
->context
.class_inst
;
6306 hash
+= g_str_hash (t1
->data
.generic_class
->container_class
->name
);
6308 for (i
= 0; i
< inst
->type_argc
; ++i
) {
6309 hash
+= mymono_metadata_type_hash (inst
->type_argv
[i
]);
6318 static MonoReflectionGenericClass
*
6319 mono_generic_class_get_object (MonoDomain
*domain
, MonoType
*geninst
)
6321 static MonoClass
*System_Reflection_MonoGenericClass
;
6322 MonoReflectionGenericClass
*res
;
6323 MonoClass
*klass
, *gklass
;
6324 MonoGenericInst
*ginst
;
6325 MonoArray
*type_args
;
6329 g_assert (0); /*This code path should not be taken anymore, all MGC instantiation must happen in managed code*/
6331 if (!System_Reflection_MonoGenericClass
) {
6332 System_Reflection_MonoGenericClass
= mono_class_from_name (
6333 mono_defaults
.corlib
, "System.Reflection", "MonoGenericClass");
6334 g_assert (System_Reflection_MonoGenericClass
);
6337 klass
= mono_class_from_mono_type (geninst
);
6338 gklass
= klass
->generic_class
->container_class
;
6340 mono_class_init (klass
);
6343 res
= (MonoReflectionGenericClass
*) mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, System_Reflection_MonoGenericClass
), mono_class_instance_size (System_Reflection_MonoGenericClass
));
6345 res
= (MonoReflectionGenericClass
*) mono_object_new (domain
, System_Reflection_MonoGenericClass
);
6348 res
->type
.type
= geninst
;
6349 tb
= mono_class_get_ref_info (gklass
);
6351 g_assert (!strcmp (tb
->vtable
->klass
->name
, "TypeBuilder"));
6352 MONO_OBJECT_SETREF (res
, generic_type
, tb
);
6354 ginst
= klass
->generic_class
->context
.class_inst
;
6355 type_args
= mono_array_new (domain
, mono_defaults
.systemtype_class
, ginst
->type_argc
);
6356 for (i
= 0; i
< ginst
->type_argc
; ++i
)
6357 mono_array_setref (type_args
, i
, mono_type_get_object (domain
, ginst
->type_argv
[i
]));
6358 MONO_OBJECT_SETREF (res
, type_arguments
, type_args
);
6364 verify_safe_for_managed_space (MonoType
*type
)
6366 switch (type
->type
) {
6368 case MONO_TYPE_ARRAY
:
6369 return verify_safe_for_managed_space (&type
->data
.array
->eklass
->byval_arg
);
6371 return verify_safe_for_managed_space (type
->data
.type
);
6372 case MONO_TYPE_SZARRAY
:
6373 return verify_safe_for_managed_space (&type
->data
.klass
->byval_arg
);
6374 case MONO_TYPE_GENERICINST
: {
6375 MonoGenericInst
*inst
= type
->data
.generic_class
->inst
;
6379 for (i
= 0; i
< inst
->type_argc
; ++i
)
6380 if (!verify_safe_for_managed_space (inst
->type_argv
[i
]))
6386 case MONO_TYPE_MVAR
:
6393 * mono_type_get_object:
6394 * @domain: an app domain
6397 * Return an System.MonoType object representing the type @type.
6400 mono_type_get_object (MonoDomain
*domain
, MonoType
*type
)
6402 MonoReflectionType
*res
;
6403 MonoClass
*klass
= mono_class_from_mono_type (type
);
6405 /*we must avoid using @type as it might have come
6406 * from a mono_metadata_type_dup and the caller
6407 * expects that is can be freed.
6408 * Using the right type from
6410 type
= klass
->byval_arg
.byref
== type
->byref
? &klass
->byval_arg
: &klass
->this_arg
;
6412 /* void is very common */
6413 if (type
->type
== MONO_TYPE_VOID
&& domain
->typeof_void
)
6414 return (MonoReflectionType
*)domain
->typeof_void
;
6417 * If the vtable of the given class was already created, we can use
6418 * the MonoType from there and avoid all locking and hash table lookups.
6420 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6421 * that the resulting object is different.
6423 if (type
== &klass
->byval_arg
&& !klass
->image
->dynamic
) {
6424 MonoVTable
*vtable
= mono_class_try_get_vtable (domain
, klass
);
6425 if (vtable
&& vtable
->type
)
6426 return vtable
->type
;
6429 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6430 mono_domain_lock (domain
);
6431 if (!domain
->type_hash
)
6432 domain
->type_hash
= mono_g_hash_table_new_type ((GHashFunc
)mymono_metadata_type_hash
,
6433 (GCompareFunc
)mymono_metadata_type_equal
, MONO_HASH_VALUE_GC
);
6434 if ((res
= mono_g_hash_table_lookup (domain
->type_hash
, type
))) {
6435 mono_domain_unlock (domain
);
6436 mono_loader_unlock ();
6439 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6440 if ((type
->type
== MONO_TYPE_GENERICINST
) && type
->data
.generic_class
->is_dynamic
&& !type
->data
.generic_class
->container_class
->wastypebuilder
) {
6441 res
= (MonoReflectionType
*)mono_generic_class_get_object (domain
, type
);
6442 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6443 mono_domain_unlock (domain
);
6444 mono_loader_unlock ();
6448 if (!verify_safe_for_managed_space (type
)) {
6449 mono_domain_unlock (domain
);
6450 mono_loader_unlock ();
6451 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6454 if (mono_class_get_ref_info (klass
) && !klass
->wastypebuilder
) {
6455 gboolean is_type_done
= TRUE
;
6456 /* Generic parameters have reflection_info set but they are not finished together with their enclosing type.
6457 * We must ensure that once a type is finished we don't return a GenericTypeParameterBuilder.
6458 * We can't simply close the types as this will interfere with other parts of the generics machinery.
6460 if (klass
->byval_arg
.type
== MONO_TYPE_MVAR
|| klass
->byval_arg
.type
== MONO_TYPE_VAR
) {
6461 MonoGenericParam
*gparam
= klass
->byval_arg
.data
.generic_param
;
6463 if (gparam
->owner
&& gparam
->owner
->is_method
) {
6464 MonoMethod
*method
= gparam
->owner
->owner
.method
;
6465 if (method
&& mono_class_get_generic_type_definition (method
->klass
)->wastypebuilder
)
6466 is_type_done
= FALSE
;
6467 } else if (gparam
->owner
&& !gparam
->owner
->is_method
) {
6468 MonoClass
*klass
= gparam
->owner
->owner
.klass
;
6469 if (klass
&& mono_class_get_generic_type_definition (klass
)->wastypebuilder
)
6470 is_type_done
= FALSE
;
6474 /* g_assert_not_reached (); */
6475 /* should this be considered an error condition? */
6476 if (is_type_done
&& !type
->byref
) {
6477 mono_domain_unlock (domain
);
6478 mono_loader_unlock ();
6479 return mono_class_get_ref_info (klass
);
6482 // FIXME: Get rid of this, do it in the icalls for Type
6483 mono_class_init (klass
);
6485 res
= (MonoReflectionType
*)mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, mono_defaults
.monotype_class
), mono_class_instance_size (mono_defaults
.monotype_class
));
6487 res
= (MonoReflectionType
*)mono_object_new (domain
, mono_defaults
.monotype_class
);
6490 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6492 if (type
->type
== MONO_TYPE_VOID
)
6493 domain
->typeof_void
= (MonoObject
*)res
;
6495 mono_domain_unlock (domain
);
6496 mono_loader_unlock ();
6501 * mono_method_get_object:
6502 * @domain: an app domain
6504 * @refclass: the reflected type (can be NULL)
6506 * Return an System.Reflection.MonoMethod object representing the method @method.
6508 MonoReflectionMethod
*
6509 mono_method_get_object (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
6512 * We use the same C representation for methods and constructors, but the type
6513 * name in C# is different.
6515 static MonoClass
*System_Reflection_MonoMethod
= NULL
;
6516 static MonoClass
*System_Reflection_MonoCMethod
= NULL
;
6517 static MonoClass
*System_Reflection_MonoGenericMethod
= NULL
;
6518 static MonoClass
*System_Reflection_MonoGenericCMethod
= NULL
;
6520 MonoReflectionMethod
*ret
;
6522 if (method
->is_inflated
) {
6523 MonoReflectionGenericMethod
*gret
;
6525 refclass
= method
->klass
;
6526 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6527 if ((*method
->name
== '.') && (!strcmp (method
->name
, ".ctor") || !strcmp (method
->name
, ".cctor"))) {
6528 if (!System_Reflection_MonoGenericCMethod
)
6529 System_Reflection_MonoGenericCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericCMethod");
6530 klass
= System_Reflection_MonoGenericCMethod
;
6532 if (!System_Reflection_MonoGenericMethod
)
6533 System_Reflection_MonoGenericMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericMethod");
6534 klass
= System_Reflection_MonoGenericMethod
;
6536 gret
= (MonoReflectionGenericMethod
*)mono_object_new (domain
, klass
);
6537 gret
->method
.method
= method
;
6538 MONO_OBJECT_SETREF (gret
, method
.name
, mono_string_new (domain
, method
->name
));
6539 MONO_OBJECT_SETREF (gret
, method
.reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6540 CACHE_OBJECT (MonoReflectionMethod
*, method
, (MonoReflectionMethod
*)gret
, refclass
);
6544 refclass
= method
->klass
;
6546 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6547 if (*method
->name
== '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0)) {
6548 if (!System_Reflection_MonoCMethod
)
6549 System_Reflection_MonoCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoCMethod");
6550 klass
= System_Reflection_MonoCMethod
;
6553 if (!System_Reflection_MonoMethod
)
6554 System_Reflection_MonoMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoMethod");
6555 klass
= System_Reflection_MonoMethod
;
6557 ret
= (MonoReflectionMethod
*)mono_object_new (domain
, klass
);
6558 ret
->method
= method
;
6559 MONO_OBJECT_SETREF (ret
, reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6560 CACHE_OBJECT (MonoReflectionMethod
*, method
, ret
, refclass
);
6564 * mono_method_clear_object:
6566 * Clear the cached reflection objects for the dynamic method METHOD.
6569 mono_method_clear_object (MonoDomain
*domain
, MonoMethod
*method
)
6572 g_assert (method
->dynamic
);
6574 klass
= method
->klass
;
6576 clear_cached_object (domain
, method
, klass
);
6577 klass
= klass
->parent
;
6579 /* Added by mono_param_get_objects () */
6580 clear_cached_object (domain
, &(method
->signature
), NULL
);
6581 klass
= method
->klass
;
6583 clear_cached_object (domain
, &(method
->signature
), klass
);
6584 klass
= klass
->parent
;
6589 * mono_field_get_object:
6590 * @domain: an app domain
6594 * Return an System.Reflection.MonoField object representing the field @field
6597 MonoReflectionField
*
6598 mono_field_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
)
6600 MonoReflectionField
*res
;
6601 static MonoClass
*monofield_klass
;
6603 CHECK_OBJECT (MonoReflectionField
*, field
, klass
);
6604 if (!monofield_klass
)
6605 monofield_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoField");
6606 res
= (MonoReflectionField
*)mono_object_new (domain
, monofield_klass
);
6609 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, mono_field_get_name (field
)));
6610 if (is_field_on_inst (field
))
6611 res
->attrs
= get_field_on_inst_generic_type (field
)->attrs
;
6613 res
->attrs
= field
->type
->attrs
;
6614 MONO_OBJECT_SETREF (res
, type
, mono_type_get_object (domain
, field
->type
));
6615 CACHE_OBJECT (MonoReflectionField
*, field
, res
, klass
);
6619 * mono_property_get_object:
6620 * @domain: an app domain
6622 * @property: a property
6624 * Return an System.Reflection.MonoProperty object representing the property @property
6627 MonoReflectionProperty
*
6628 mono_property_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
)
6630 MonoReflectionProperty
*res
;
6631 static MonoClass
*monoproperty_klass
;
6633 CHECK_OBJECT (MonoReflectionProperty
*, property
, klass
);
6634 if (!monoproperty_klass
)
6635 monoproperty_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoProperty");
6636 res
= (MonoReflectionProperty
*)mono_object_new (domain
, monoproperty_klass
);
6638 res
->property
= property
;
6639 CACHE_OBJECT (MonoReflectionProperty
*, property
, res
, klass
);
6643 * mono_event_get_object:
6644 * @domain: an app domain
6648 * Return an System.Reflection.MonoEvent object representing the event @event
6651 MonoReflectionEvent
*
6652 mono_event_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
)
6654 MonoReflectionEvent
*res
;
6655 MonoReflectionMonoEvent
*mono_event
;
6656 static MonoClass
*monoevent_klass
;
6658 CHECK_OBJECT (MonoReflectionEvent
*, event
, klass
);
6659 if (!monoevent_klass
)
6660 monoevent_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoEvent");
6661 mono_event
= (MonoReflectionMonoEvent
*)mono_object_new (domain
, monoevent_klass
);
6662 mono_event
->klass
= klass
;
6663 mono_event
->event
= event
;
6664 res
= (MonoReflectionEvent
*)mono_event
;
6665 CACHE_OBJECT (MonoReflectionEvent
*, event
, res
, klass
);
6669 * mono_get_reflection_missing_object:
6670 * @domain: Domain where the object lives
6672 * Returns the System.Reflection.Missing.Value singleton object
6673 * (of type System.Reflection.Missing).
6675 * Used as the value for ParameterInfo.DefaultValue when Optional
6679 mono_get_reflection_missing_object (MonoDomain
*domain
)
6682 static MonoClassField
*missing_value_field
= NULL
;
6684 if (!missing_value_field
) {
6685 MonoClass
*missing_klass
;
6686 missing_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Missing");
6687 mono_class_init (missing_klass
);
6688 missing_value_field
= mono_class_get_field_from_name (missing_klass
, "Value");
6689 g_assert (missing_value_field
);
6691 obj
= mono_field_get_value_object (domain
, missing_value_field
, NULL
);
6697 get_dbnull (MonoDomain
*domain
, MonoObject
**dbnull
)
6700 *dbnull
= mono_get_dbnull_object (domain
);
6705 get_reflection_missing (MonoDomain
*domain
, MonoObject
**reflection_missing
)
6707 if (!*reflection_missing
)
6708 *reflection_missing
= mono_get_reflection_missing_object (domain
);
6709 return *reflection_missing
;
6713 * mono_param_get_objects:
6714 * @domain: an app domain
6717 * Return an System.Reflection.ParameterInfo array object representing the parameters
6718 * in the method @method.
6721 mono_param_get_objects_internal (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
6723 static MonoClass
*System_Reflection_ParameterInfo
;
6724 static MonoClass
*System_Reflection_ParameterInfo_array
;
6725 MonoArray
*res
= NULL
;
6726 MonoReflectionMethod
*member
= NULL
;
6727 MonoReflectionParameter
*param
= NULL
;
6728 char **names
, **blobs
= NULL
;
6729 guint32
*types
= NULL
;
6730 MonoType
*type
= NULL
;
6731 MonoObject
*dbnull
= NULL
;
6732 MonoObject
*missing
= NULL
;
6733 MonoMarshalSpec
**mspecs
;
6734 MonoMethodSignature
*sig
;
6735 MonoVTable
*pinfo_vtable
;
6738 if (!System_Reflection_ParameterInfo_array
) {
6741 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ParameterInfo");
6742 mono_memory_barrier ();
6743 System_Reflection_ParameterInfo
= klass
;
6745 klass
= mono_array_class_get (klass
, 1);
6746 mono_memory_barrier ();
6747 System_Reflection_ParameterInfo_array
= klass
;
6750 if (!mono_method_signature (method
)->param_count
)
6751 return mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), 0);
6753 /* Note: the cache is based on the address of the signature into the method
6754 * since we already cache MethodInfos with the method as keys.
6756 CHECK_OBJECT (MonoArray
*, &(method
->signature
), refclass
);
6758 sig
= mono_method_signature (method
);
6759 member
= mono_method_get_object (domain
, method
, refclass
);
6760 names
= g_new (char *, sig
->param_count
);
6761 mono_method_get_param_names (method
, (const char **) names
);
6763 mspecs
= g_new (MonoMarshalSpec
*, sig
->param_count
+ 1);
6764 mono_method_get_marshal_info (method
, mspecs
);
6766 res
= mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), sig
->param_count
);
6767 pinfo_vtable
= mono_class_vtable (domain
, System_Reflection_ParameterInfo
);
6768 for (i
= 0; i
< sig
->param_count
; ++i
) {
6769 param
= (MonoReflectionParameter
*)mono_object_new_specific (pinfo_vtable
);
6770 MONO_OBJECT_SETREF (param
, ClassImpl
, mono_type_get_object (domain
, sig
->params
[i
]));
6771 MONO_OBJECT_SETREF (param
, MemberImpl
, (MonoObject
*)member
);
6772 MONO_OBJECT_SETREF (param
, NameImpl
, mono_string_new (domain
, names
[i
]));
6773 param
->PositionImpl
= i
;
6774 param
->AttrsImpl
= sig
->params
[i
]->attrs
;
6776 if (!(param
->AttrsImpl
& PARAM_ATTRIBUTE_HAS_DEFAULT
)) {
6777 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6778 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6780 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6784 blobs
= g_new0 (char *, sig
->param_count
);
6785 types
= g_new0 (guint32
, sig
->param_count
);
6786 get_default_param_value_blobs (method
, blobs
, types
);
6789 /* Build MonoType for the type from the Constant Table */
6791 type
= g_new0 (MonoType
, 1);
6792 type
->type
= types
[i
];
6793 type
->data
.klass
= NULL
;
6794 if (types
[i
] == MONO_TYPE_CLASS
)
6795 type
->data
.klass
= mono_defaults
.object_class
;
6796 else if ((sig
->params
[i
]->type
== MONO_TYPE_VALUETYPE
) && sig
->params
[i
]->data
.klass
->enumtype
) {
6797 /* For enums, types [i] contains the base type */
6799 type
->type
= MONO_TYPE_VALUETYPE
;
6800 type
->data
.klass
= mono_class_from_mono_type (sig
->params
[i
]);
6802 type
->data
.klass
= mono_class_from_mono_type (type
);
6804 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, mono_get_object_from_blob (domain
, type
, blobs
[i
]));
6806 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6807 if (types
[i
] != MONO_TYPE_CLASS
&& !param
->DefaultValueImpl
) {
6808 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6809 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6811 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6817 MONO_OBJECT_SETREF (param
, MarshalAsImpl
, (MonoObject
*)mono_reflection_marshal_from_marshal_spec (domain
, method
->klass
, mspecs
[i
+ 1]));
6819 mono_array_setref (res
, i
, param
);
6826 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
6828 mono_metadata_free_marshal_spec (mspecs
[i
]);
6831 CACHE_OBJECT (MonoArray
*, &(method
->signature
), res
, refclass
);
6835 mono_param_get_objects (MonoDomain
*domain
, MonoMethod
*method
)
6837 return mono_param_get_objects_internal (domain
, method
, NULL
);
6841 * mono_method_body_get_object:
6842 * @domain: an app domain
6845 * Return an System.Reflection.MethodBody object representing the method @method.
6847 MonoReflectionMethodBody
*
6848 mono_method_body_get_object (MonoDomain
*domain
, MonoMethod
*method
)
6850 static MonoClass
*System_Reflection_MethodBody
= NULL
;
6851 static MonoClass
*System_Reflection_LocalVariableInfo
= NULL
;
6852 static MonoClass
*System_Reflection_ExceptionHandlingClause
= NULL
;
6853 MonoReflectionMethodBody
*ret
;
6854 MonoMethodHeader
*header
;
6855 guint32 method_rva
, local_var_sig_token
;
6857 unsigned char format
, flags
;
6860 if (!System_Reflection_MethodBody
)
6861 System_Reflection_MethodBody
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MethodBody");
6862 if (!System_Reflection_LocalVariableInfo
)
6863 System_Reflection_LocalVariableInfo
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "LocalVariableInfo");
6864 if (!System_Reflection_ExceptionHandlingClause
)
6865 System_Reflection_ExceptionHandlingClause
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ExceptionHandlingClause");
6867 CHECK_OBJECT (MonoReflectionMethodBody
*, method
, NULL
);
6869 if ((method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
6870 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
6871 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
6872 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
))
6874 header
= mono_method_get_header (method
);
6876 /* Obtain local vars signature token */
6877 method_rva
= mono_metadata_decode_row_col (&method
->klass
->image
->tables
[MONO_TABLE_METHOD
], mono_metadata_token_index (method
->token
) - 1, MONO_METHOD_RVA
);
6878 ptr
= mono_image_rva_map (method
->klass
->image
, method_rva
);
6879 flags
= *(const unsigned char *) ptr
;
6880 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
6882 case METHOD_HEADER_TINY_FORMAT
:
6883 local_var_sig_token
= 0;
6885 case METHOD_HEADER_FAT_FORMAT
:
6889 local_var_sig_token
= read32 (ptr
);
6892 g_assert_not_reached ();
6895 ret
= (MonoReflectionMethodBody
*)mono_object_new (domain
, System_Reflection_MethodBody
);
6897 ret
->init_locals
= header
->init_locals
;
6898 ret
->max_stack
= header
->max_stack
;
6899 ret
->local_var_sig_token
= local_var_sig_token
;
6900 MONO_OBJECT_SETREF (ret
, il
, mono_array_new_cached (domain
, mono_defaults
.byte_class
, header
->code_size
));
6901 memcpy (mono_array_addr (ret
->il
, guint8
, 0), header
->code
, header
->code_size
);
6904 MONO_OBJECT_SETREF (ret
, locals
, mono_array_new_cached (domain
, System_Reflection_LocalVariableInfo
, header
->num_locals
));
6905 for (i
= 0; i
< header
->num_locals
; ++i
) {
6906 MonoReflectionLocalVariableInfo
*info
= (MonoReflectionLocalVariableInfo
*)mono_object_new (domain
, System_Reflection_LocalVariableInfo
);
6907 MONO_OBJECT_SETREF (info
, local_type
, mono_type_get_object (domain
, header
->locals
[i
]));
6908 info
->is_pinned
= header
->locals
[i
]->pinned
;
6909 info
->local_index
= i
;
6910 mono_array_setref (ret
->locals
, i
, info
);
6914 MONO_OBJECT_SETREF (ret
, clauses
, mono_array_new_cached (domain
, System_Reflection_ExceptionHandlingClause
, header
->num_clauses
));
6915 for (i
= 0; i
< header
->num_clauses
; ++i
) {
6916 MonoReflectionExceptionHandlingClause
*info
= (MonoReflectionExceptionHandlingClause
*)mono_object_new (domain
, System_Reflection_ExceptionHandlingClause
);
6917 MonoExceptionClause
*clause
= &header
->clauses
[i
];
6919 info
->flags
= clause
->flags
;
6920 info
->try_offset
= clause
->try_offset
;
6921 info
->try_length
= clause
->try_len
;
6922 info
->handler_offset
= clause
->handler_offset
;
6923 info
->handler_length
= clause
->handler_len
;
6924 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)
6925 info
->filter_offset
= clause
->data
.filter_offset
;
6926 else if (clause
->data
.catch_class
)
6927 MONO_OBJECT_SETREF (info
, catch_type
, mono_type_get_object (mono_domain_get (), &clause
->data
.catch_class
->byval_arg
));
6929 mono_array_setref (ret
->clauses
, i
, info
);
6932 mono_metadata_free_mh (header
);
6933 CACHE_OBJECT (MonoReflectionMethodBody
*, method
, ret
, NULL
);
6938 * mono_get_dbnull_object:
6939 * @domain: Domain where the object lives
6941 * Returns the System.DBNull.Value singleton object
6943 * Used as the value for ParameterInfo.DefaultValue
6946 mono_get_dbnull_object (MonoDomain
*domain
)
6949 static MonoClassField
*dbnull_value_field
= NULL
;
6951 if (!dbnull_value_field
) {
6952 MonoClass
*dbnull_klass
;
6953 dbnull_klass
= mono_class_from_name (mono_defaults
.corlib
, "System", "DBNull");
6954 mono_class_init (dbnull_klass
);
6955 dbnull_value_field
= mono_class_get_field_from_name (dbnull_klass
, "Value");
6956 g_assert (dbnull_value_field
);
6958 obj
= mono_field_get_value_object (domain
, dbnull_value_field
, NULL
);
6964 get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
)
6966 guint32 param_index
, i
, lastp
, crow
= 0;
6967 guint32 param_cols
[MONO_PARAM_SIZE
], const_cols
[MONO_CONSTANT_SIZE
];
6970 MonoClass
*klass
= method
->klass
;
6971 MonoImage
*image
= klass
->image
;
6972 MonoMethodSignature
*methodsig
= mono_method_signature (method
);
6974 MonoTableInfo
*constt
;
6975 MonoTableInfo
*methodt
;
6976 MonoTableInfo
*paramt
;
6978 if (!methodsig
->param_count
)
6981 mono_class_init (klass
);
6983 if (klass
->image
->dynamic
) {
6984 MonoReflectionMethodAux
*aux
;
6985 if (method
->is_inflated
)
6986 method
= ((MonoMethodInflated
*)method
)->declaring
;
6987 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
6988 if (aux
&& aux
->param_defaults
) {
6989 memcpy (blobs
, &(aux
->param_defaults
[1]), methodsig
->param_count
* sizeof (char*));
6990 memcpy (types
, &(aux
->param_default_types
[1]), methodsig
->param_count
* sizeof (guint32
));
6995 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
6996 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
6997 constt
= &image
->tables
[MONO_TABLE_CONSTANT
];
6999 idx
= mono_method_get_index (method
) - 1;
7000 g_assert (idx
!= -1);
7002 param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
7003 if (idx
+ 1 < methodt
->rows
)
7004 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
7006 lastp
= paramt
->rows
+ 1;
7008 for (i
= param_index
; i
< lastp
; ++i
) {
7011 mono_metadata_decode_row (paramt
, i
- 1, param_cols
, MONO_PARAM_SIZE
);
7012 paramseq
= param_cols
[MONO_PARAM_SEQUENCE
];
7014 if (!(param_cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_DEFAULT
))
7017 crow
= mono_metadata_get_constant_index (image
, MONO_TOKEN_PARAM_DEF
| i
, crow
+ 1);
7022 mono_metadata_decode_row (constt
, crow
- 1, const_cols
, MONO_CONSTANT_SIZE
);
7023 blobs
[paramseq
- 1] = (gpointer
) mono_metadata_blob_heap (image
, const_cols
[MONO_CONSTANT_VALUE
]);
7024 types
[paramseq
- 1] = const_cols
[MONO_CONSTANT_TYPE
];
7031 mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
)
7036 MonoType
*basetype
= type
;
7041 klass
= mono_class_from_mono_type (type
);
7042 if (klass
->valuetype
) {
7043 object
= mono_object_new (domain
, klass
);
7044 retval
= ((gchar
*) object
+ sizeof (MonoObject
));
7045 if (klass
->enumtype
)
7046 basetype
= mono_class_enum_basetype (klass
);
7051 if (!mono_get_constant_value_from_blob (domain
, basetype
->type
, blob
, retval
))
7058 assembly_name_to_aname (MonoAssemblyName
*assembly
, char *p
) {
7062 memset (assembly
, 0, sizeof (MonoAssemblyName
));
7064 assembly
->culture
= "";
7065 memset (assembly
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
7067 while (*p
&& (isalnum (*p
) || *p
== '.' || *p
== '-' || *p
== '_' || *p
== '$' || *p
== '@'))
7070 while (g_ascii_isspace (*p
) || *p
== ',') {
7079 if (*p
== 'V' && g_ascii_strncasecmp (p
, "Version=", 8) == 0) {
7081 assembly
->major
= strtoul (p
, &s
, 10);
7082 if (s
== p
|| *s
!= '.')
7085 assembly
->minor
= strtoul (p
, &s
, 10);
7086 if (s
== p
|| *s
!= '.')
7089 assembly
->build
= strtoul (p
, &s
, 10);
7090 if (s
== p
|| *s
!= '.')
7093 assembly
->revision
= strtoul (p
, &s
, 10);
7097 } else if (*p
== 'C' && g_ascii_strncasecmp (p
, "Culture=", 8) == 0) {
7099 if (g_ascii_strncasecmp (p
, "neutral", 7) == 0) {
7100 assembly
->culture
= "";
7103 assembly
->culture
= p
;
7104 while (*p
&& *p
!= ',') {
7108 } else if (*p
== 'P' && g_ascii_strncasecmp (p
, "PublicKeyToken=", 15) == 0) {
7110 if (strncmp (p
, "null", 4) == 0) {
7115 while (*p
&& *p
!= ',') {
7118 len
= (p
- start
+ 1);
7119 if (len
> MONO_PUBLIC_KEY_TOKEN_LENGTH
)
7120 len
= MONO_PUBLIC_KEY_TOKEN_LENGTH
;
7121 g_strlcpy ((char*)assembly
->public_key_token
, start
, len
);
7124 while (*p
&& *p
!= ',')
7128 while (g_ascii_isspace (*p
) || *p
== ',') {
7142 * mono_reflection_parse_type:
7145 * Parse a type name as accepted by the GetType () method and output the info
7146 * extracted in the info structure.
7147 * the name param will be mangled, so, make a copy before passing it to this function.
7148 * The fields in info will be valid until the memory pointed to by name is valid.
7150 * See also mono_type_get_name () below.
7152 * Returns: 0 on parse error.
7155 _mono_reflection_parse_type (char *name
, char **endptr
, gboolean is_recursed
,
7156 MonoTypeNameParse
*info
)
7158 char *start
, *p
, *w
, *temp
, *last_point
, *startn
;
7159 int in_modifiers
= 0;
7160 int isbyref
= 0, rank
, arity
= 0, i
;
7162 start
= p
= w
= name
;
7164 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
7165 memset (&info
->assembly
, 0, sizeof (MonoAssemblyName
));
7166 info
->name
= info
->name_space
= NULL
;
7167 info
->nested
= NULL
;
7168 info
->modifiers
= NULL
;
7169 info
->type_arguments
= NULL
;
7171 /* last_point separates the namespace from the name */
7174 while (*p
== ' ') p
++, start
++, w
++, name
++;
7179 *p
= 0; /* NULL terminate the name */
7181 info
->nested
= g_list_append (info
->nested
, startn
);
7182 /* we have parsed the nesting namespace + name */
7186 info
->name_space
= start
;
7188 info
->name
= last_point
+ 1;
7190 info
->name_space
= (char *)"";
7209 i
= strtol (p
, &temp
, 10);
7226 info
->name_space
= start
;
7228 info
->name
= last_point
+ 1;
7230 info
->name_space
= (char *)"";
7237 if (isbyref
) /* only one level allowed by the spec */
7240 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (0));
7244 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-1));
7250 info
->type_arguments
= g_ptr_array_new ();
7251 for (i
= 0; i
< arity
; i
++) {
7252 MonoTypeNameParse
*subinfo
= g_new0 (MonoTypeNameParse
, 1);
7253 gboolean fqname
= FALSE
;
7255 g_ptr_array_add (info
->type_arguments
, subinfo
);
7262 if (!_mono_reflection_parse_type (p
, &p
, TRUE
, subinfo
))
7273 while (*p
&& (*p
!= ']'))
7281 if (g_ascii_isspace (*aname
)) {
7288 !assembly_name_to_aname (&subinfo
->assembly
, aname
))
7292 if (i
+ 1 < arity
) {
7312 else if (*p
== '*') /* '*' means unknown lower bound */
7313 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-2));
7320 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (rank
));
7331 if (g_ascii_isspace (*p
)) {
7338 return 0; /* missing assembly name */
7339 if (!assembly_name_to_aname (&info
->assembly
, p
))
7345 if (info
->assembly
.name
)
7348 // *w = 0; /* terminate class name */
7350 if (!info
->name
|| !*info
->name
)
7354 /* add other consistency checks */
7359 mono_reflection_parse_type (char *name
, MonoTypeNameParse
*info
)
7361 return _mono_reflection_parse_type (name
, NULL
, FALSE
, info
);
7365 _mono_reflection_get_type_from_info (MonoTypeNameParse
*info
, MonoImage
*image
, gboolean ignorecase
)
7367 gboolean type_resolve
= FALSE
;
7369 MonoImage
*rootimage
= image
;
7371 if (info
->assembly
.name
) {
7372 MonoAssembly
*assembly
= mono_assembly_loaded (&info
->assembly
);
7373 if (!assembly
&& image
&& image
->assembly
&& mono_assembly_names_equal (&info
->assembly
, &image
->assembly
->aname
))
7375 * This could happen in the AOT compiler case when the search hook is not
7378 assembly
= image
->assembly
;
7380 /* then we must load the assembly ourselve - see #60439 */
7381 assembly
= mono_assembly_load (&info
->assembly
, NULL
, NULL
);
7385 image
= assembly
->image
;
7386 } else if (!image
) {
7387 image
= mono_defaults
.corlib
;
7390 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7391 if (type
== NULL
&& !info
->assembly
.name
&& image
!= mono_defaults
.corlib
) {
7392 image
= mono_defaults
.corlib
;
7393 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7400 mono_reflection_get_type_internal (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7405 gboolean bounded
= FALSE
;
7408 image
= mono_defaults
.corlib
;
7411 klass
= mono_class_from_name_case (image
, info
->name_space
, info
->name
);
7413 klass
= mono_class_from_name (image
, info
->name_space
, info
->name
);
7416 for (mod
= info
->nested
; mod
; mod
= mod
->next
) {
7417 gpointer iter
= NULL
;
7421 mono_class_init (parent
);
7423 while ((klass
= mono_class_get_nested_types (parent
, &iter
))) {
7425 if (mono_utf8_strcasecmp (klass
->name
, mod
->data
) == 0)
7428 if (strcmp (klass
->name
, mod
->data
) == 0)
7437 mono_class_init (klass
);
7439 if (info
->type_arguments
) {
7440 MonoType
**type_args
= g_new0 (MonoType
*, info
->type_arguments
->len
);
7441 MonoReflectionType
*the_type
;
7445 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7446 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7448 type_args
[i
] = _mono_reflection_get_type_from_info (subinfo
, rootimage
, ignorecase
);
7449 if (!type_args
[i
]) {
7455 the_type
= mono_type_get_object (mono_domain_get (), &klass
->byval_arg
);
7457 instance
= mono_reflection_bind_generic_parameters (
7458 the_type
, info
->type_arguments
->len
, type_args
);
7464 klass
= mono_class_from_mono_type (instance
);
7467 for (mod
= info
->modifiers
; mod
; mod
= mod
->next
) {
7468 modval
= GPOINTER_TO_UINT (mod
->data
);
7469 if (!modval
) { /* byref: must be last modifier */
7470 return &klass
->this_arg
;
7471 } else if (modval
== -1) {
7472 klass
= mono_ptr_class_get (&klass
->byval_arg
);
7473 } else if (modval
== -2) {
7475 } else { /* array rank */
7476 klass
= mono_bounded_array_class_get (klass
, modval
, bounded
);
7478 mono_class_init (klass
);
7481 return &klass
->byval_arg
;
7485 * mono_reflection_get_type:
7486 * @image: a metadata context
7487 * @info: type description structure
7488 * @ignorecase: flag for case-insensitive string compares
7489 * @type_resolve: whenever type resolve was already tried
7491 * Build a MonoType from the type description in @info.
7496 mono_reflection_get_type (MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
) {
7497 return mono_reflection_get_type_with_rootimage(image
, image
, info
, ignorecase
, type_resolve
);
7501 mono_reflection_get_type_internal_dynamic (MonoImage
*rootimage
, MonoAssembly
*assembly
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7503 MonoReflectionAssemblyBuilder
*abuilder
;
7507 g_assert (assembly
->dynamic
);
7508 abuilder
= (MonoReflectionAssemblyBuilder
*)mono_assembly_get_object (((MonoDynamicAssembly
*)assembly
)->domain
, assembly
);
7510 /* Enumerate all modules */
7513 if (abuilder
->modules
) {
7514 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
7515 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
7516 type
= mono_reflection_get_type_internal (rootimage
, &mb
->dynamic_image
->image
, info
, ignorecase
);
7522 if (!type
&& abuilder
->loaded_modules
) {
7523 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
7524 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
7525 type
= mono_reflection_get_type_internal (rootimage
, mod
->image
, info
, ignorecase
);
7535 mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
)
7538 MonoReflectionAssembly
*assembly
;
7542 if (image
&& image
->dynamic
)
7543 type
= mono_reflection_get_type_internal_dynamic (rootimage
, image
->assembly
, info
, ignorecase
);
7545 type
= mono_reflection_get_type_internal (rootimage
, image
, info
, ignorecase
);
7548 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7555 *type_resolve
= TRUE
;
7558 /* Reconstruct the type name */
7559 fullName
= g_string_new ("");
7560 if (info
->name_space
&& (info
->name_space
[0] != '\0'))
7561 g_string_printf (fullName
, "%s.%s", info
->name_space
, info
->name
);
7563 g_string_printf (fullName
, "%s", info
->name
);
7564 for (mod
= info
->nested
; mod
; mod
= mod
->next
)
7565 g_string_append_printf (fullName
, "+%s", (char*)mod
->data
);
7567 assembly
= mono_domain_try_type_resolve ( mono_domain_get (), fullName
->str
, NULL
);
7569 if (assembly
->assembly
->dynamic
)
7570 type
= mono_reflection_get_type_internal_dynamic (rootimage
, assembly
->assembly
, info
, ignorecase
);
7572 type
= mono_reflection_get_type_internal (rootimage
, assembly
->assembly
->image
,
7575 g_string_free (fullName
, TRUE
);
7580 mono_reflection_free_type_info (MonoTypeNameParse
*info
)
7582 g_list_free (info
->modifiers
);
7583 g_list_free (info
->nested
);
7585 if (info
->type_arguments
) {
7588 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7589 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7591 mono_reflection_free_type_info (subinfo
);
7592 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7596 g_ptr_array_free (info
->type_arguments
, TRUE
);
7601 * mono_reflection_type_from_name:
7603 * @image: a metadata context (can be NULL).
7605 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7606 * it defaults to get the type from @image or, if @image is NULL or loading
7607 * from it fails, uses corlib.
7611 mono_reflection_type_from_name (char *name
, MonoImage
*image
)
7613 MonoType
*type
= NULL
;
7614 MonoTypeNameParse info
;
7617 /* Make a copy since parse_type modifies its argument */
7618 tmp
= g_strdup (name
);
7620 /*g_print ("requested type %s\n", str);*/
7621 if (mono_reflection_parse_type (tmp
, &info
)) {
7622 type
= _mono_reflection_get_type_from_info (&info
, image
, FALSE
);
7626 mono_reflection_free_type_info (&info
);
7631 * mono_reflection_get_token:
7633 * Return the metadata token of OBJ which should be an object
7634 * representing a metadata element.
7637 mono_reflection_get_token (MonoObject
*obj
)
7642 klass
= obj
->vtable
->klass
;
7644 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
7645 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
7647 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7648 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
7649 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
7651 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7652 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
7653 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
7655 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7656 token
= mono_image_create_token (((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
, obj
, FALSE
, TRUE
);
7657 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
7658 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
7659 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
7660 } else if (strcmp (klass
->name
, "MonoType") == 0) {
7661 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
7662 token
= mono_class_from_mono_type (type
)->type_token
;
7663 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
7664 strcmp (klass
->name
, "MonoMethod") == 0 ||
7665 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
7666 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
7667 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
7668 if (m
->method
->is_inflated
) {
7669 MonoMethodInflated
*inflated
= (MonoMethodInflated
*) m
->method
;
7670 return inflated
->declaring
->token
;
7672 token
= m
->method
->token
;
7674 } else if (strcmp (klass
->name
, "MonoField") == 0) {
7675 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
7677 if (is_field_on_inst (f
->field
)) {
7678 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)f
->field
->parent
->generic_class
;
7679 int field_index
= f
->field
- dgclass
->fields
;
7682 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
7683 obj
= dgclass
->field_objects
[field_index
];
7684 return mono_reflection_get_token (obj
);
7686 token
= mono_class_get_field_token (f
->field
);
7687 } else if (strcmp (klass
->name
, "MonoProperty") == 0) {
7688 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)obj
;
7690 token
= mono_class_get_property_token (p
->property
);
7691 } else if (strcmp (klass
->name
, "MonoEvent") == 0) {
7692 MonoReflectionMonoEvent
*p
= (MonoReflectionMonoEvent
*)obj
;
7694 token
= mono_class_get_event_token (p
->event
);
7695 } else if (strcmp (klass
->name
, "ParameterInfo") == 0) {
7696 MonoReflectionParameter
*p
= (MonoReflectionParameter
*)obj
;
7697 MonoClass
*member_class
= mono_object_class (p
->MemberImpl
);
7698 g_assert (mono_class_is_reflection_method_or_constructor (member_class
));
7700 token
= mono_method_get_param_token (((MonoReflectionMethod
*)p
->MemberImpl
)->method
, p
->PositionImpl
);
7701 } else if (strcmp (klass
->name
, "Module") == 0) {
7702 MonoReflectionModule
*m
= (MonoReflectionModule
*)obj
;
7705 } else if (strcmp (klass
->name
, "Assembly") == 0 || strcmp (klass
->name
, "MonoAssembly") == 0) {
7706 token
= mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1);
7708 gchar
*msg
= g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass
->name_space
, klass
->name
);
7709 MonoException
*ex
= mono_get_exception_not_implemented (msg
);
7711 mono_raise_exception (ex
);
7718 load_cattr_value (MonoImage
*image
, MonoType
*t
, const char *p
, const char **end
)
7720 int slen
, type
= t
->type
;
7721 MonoClass
*tklass
= t
->data
.klass
;
7727 case MONO_TYPE_BOOLEAN
: {
7728 MonoBoolean
*bval
= g_malloc (sizeof (MonoBoolean
));
7733 case MONO_TYPE_CHAR
:
7735 case MONO_TYPE_I2
: {
7736 guint16
*val
= g_malloc (sizeof (guint16
));
7741 #if SIZEOF_VOID_P == 4
7747 case MONO_TYPE_I4
: {
7748 guint32
*val
= g_malloc (sizeof (guint32
));
7753 #if SIZEOF_VOID_P == 8
7754 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
7758 case MONO_TYPE_I8
: {
7759 guint64
*val
= g_malloc (sizeof (guint64
));
7764 case MONO_TYPE_R8
: {
7765 double *val
= g_malloc (sizeof (double));
7770 case MONO_TYPE_VALUETYPE
:
7771 if (t
->data
.klass
->enumtype
) {
7772 type
= mono_class_enum_basetype (t
->data
.klass
)->type
;
7775 g_error ("generic valutype %s not handled in custom attr value decoding", t
->data
.klass
->name
);
7778 case MONO_TYPE_STRING
:
7779 if (*p
== (char)0xFF) {
7783 slen
= mono_metadata_decode_value (p
, &p
);
7785 return mono_string_new_len (mono_domain_get (), p
, slen
);
7786 case MONO_TYPE_CLASS
: {
7789 if (*p
== (char)0xFF) {
7794 slen
= mono_metadata_decode_value (p
, &p
);
7795 n
= g_memdup (p
, slen
+ 1);
7797 t
= mono_reflection_type_from_name (n
, image
);
7799 g_warning ("Cannot load type '%s'", n
);
7803 return mono_type_get_object (mono_domain_get (), t
);
7807 case MONO_TYPE_OBJECT
: {
7810 MonoClass
*subc
= NULL
;
7815 } else if (subt
== 0x0E) {
7816 type
= MONO_TYPE_STRING
;
7818 } else if (subt
== 0x1D) {
7819 MonoType simple_type
= {{0}};
7824 /* See Partition II, Appendix B3 */
7825 etype
= MONO_TYPE_OBJECT
;
7826 type
= MONO_TYPE_SZARRAY
;
7827 simple_type
.type
= etype
;
7828 tklass
= mono_class_from_mono_type (&simple_type
);
7830 } else if (subt
== 0x55) {
7833 slen
= mono_metadata_decode_value (p
, &p
);
7834 n
= g_memdup (p
, slen
+ 1);
7836 t
= mono_reflection_type_from_name (n
, image
);
7838 g_error ("Cannot load type '%s'", n
);
7841 subc
= mono_class_from_mono_type (t
);
7842 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
7843 MonoType simple_type
= {{0}};
7844 simple_type
.type
= subt
;
7845 subc
= mono_class_from_mono_type (&simple_type
);
7847 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
7849 val
= load_cattr_value (image
, &subc
->byval_arg
, p
, end
);
7850 obj
= mono_object_new (mono_domain_get (), subc
);
7851 g_assert (!subc
->has_references
);
7852 memcpy ((char*)obj
+ sizeof (MonoObject
), val
, mono_class_value_size (subc
, NULL
));
7856 case MONO_TYPE_SZARRAY
: {
7858 guint32 i
, alen
, basetype
;
7861 if (alen
== 0xffffffff) {
7865 arr
= mono_array_new (mono_domain_get(), tklass
, alen
);
7866 basetype
= tklass
->byval_arg
.type
;
7867 if (basetype
== MONO_TYPE_VALUETYPE
&& tklass
->enumtype
)
7868 basetype
= mono_class_enum_basetype (tklass
)->type
;
7873 case MONO_TYPE_BOOLEAN
:
7874 for (i
= 0; i
< alen
; i
++) {
7875 MonoBoolean val
= *p
++;
7876 mono_array_set (arr
, MonoBoolean
, i
, val
);
7879 case MONO_TYPE_CHAR
:
7882 for (i
= 0; i
< alen
; i
++) {
7883 guint16 val
= read16 (p
);
7884 mono_array_set (arr
, guint16
, i
, val
);
7891 for (i
= 0; i
< alen
; i
++) {
7892 guint32 val
= read32 (p
);
7893 mono_array_set (arr
, guint32
, i
, val
);
7898 for (i
= 0; i
< alen
; i
++) {
7901 mono_array_set (arr
, double, i
, val
);
7907 for (i
= 0; i
< alen
; i
++) {
7908 guint64 val
= read64 (p
);
7909 mono_array_set (arr
, guint64
, i
, val
);
7913 case MONO_TYPE_CLASS
:
7914 case MONO_TYPE_OBJECT
:
7915 case MONO_TYPE_STRING
:
7916 for (i
= 0; i
< alen
; i
++) {
7917 MonoObject
*item
= load_cattr_value (image
, &tklass
->byval_arg
, p
, &p
);
7918 mono_array_setref (arr
, i
, item
);
7922 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
7928 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
7934 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
)
7936 static MonoClass
*klass
;
7937 static MonoMethod
*ctor
;
7939 void *params
[2], *unboxed
;
7942 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeTypedArgument");
7944 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7946 params
[0] = mono_type_get_object (mono_domain_get (), t
);
7948 retval
= mono_object_new (mono_domain_get (), klass
);
7949 unboxed
= mono_object_unbox (retval
);
7950 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7956 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
)
7958 static MonoClass
*klass
;
7959 static MonoMethod
*ctor
;
7961 void *unboxed
, *params
[2];
7964 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeNamedArgument");
7966 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7969 params
[1] = typedarg
;
7970 retval
= mono_object_new (mono_domain_get (), klass
);
7971 unboxed
= mono_object_unbox (retval
);
7972 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7978 type_is_reference (MonoType
*type
)
7980 switch (type
->type
) {
7981 case MONO_TYPE_BOOLEAN
:
7982 case MONO_TYPE_CHAR
:
7995 case MONO_TYPE_VALUETYPE
:
8003 free_param_data (MonoMethodSignature
*sig
, void **params
) {
8005 for (i
= 0; i
< sig
->param_count
; ++i
) {
8006 if (!type_is_reference (sig
->params
[i
]))
8007 g_free (params
[i
]);
8012 * Find the field index in the metadata FieldDef table.
8015 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
8018 for (i
= 0; i
< klass
->field
.count
; ++i
) {
8019 if (field
== &klass
->fields
[i
])
8020 return klass
->field
.first
+ 1 + i
;
8026 * Find the property index in the metadata Property table.
8029 find_property_index (MonoClass
*klass
, MonoProperty
*property
) {
8032 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
8033 if (property
== &klass
->ext
->properties
[i
])
8034 return klass
->ext
->property
.first
+ 1 + i
;
8040 * Find the event index in the metadata Event table.
8043 find_event_index (MonoClass
*klass
, MonoEvent
*event
) {
8046 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
8047 if (event
== &klass
->ext
->events
[i
])
8048 return klass
->ext
->event
.first
+ 1 + i
;
8054 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
8056 const char *p
= (const char*)data
;
8058 guint32 i
, j
, num_named
;
8060 void *params_buf
[32];
8062 MonoMethodSignature
*sig
;
8064 mono_class_init (method
->klass
);
8067 attr
= mono_object_new (mono_domain_get (), method
->klass
);
8068 mono_runtime_invoke (method
, attr
, NULL
, NULL
);
8072 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
8075 /*g_print ("got attr %s\n", method->klass->name);*/
8077 sig
= mono_method_signature (method
);
8078 if (sig
->param_count
< 32)
8079 params
= params_buf
;
8081 /* Allocate using GC so it gets GC tracking */
8082 params
= mono_gc_alloc_fixed (sig
->param_count
* sizeof (void*), NULL
);
8086 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
8087 params
[i
] = load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
8091 attr
= mono_object_new (mono_domain_get (), method
->klass
);
8092 mono_runtime_invoke (method
, attr
, params
, NULL
);
8093 free_param_data (method
->signature
, params
);
8094 num_named
= read16 (named
);
8096 for (j
= 0; j
< num_named
; j
++) {
8098 char *name
, named_type
, data_type
;
8099 named_type
= *named
++;
8100 data_type
= *named
++; /* type of data */
8101 if (data_type
== MONO_TYPE_SZARRAY
)
8102 data_type
= *named
++;
8103 if (data_type
== MONO_TYPE_ENUM
) {
8106 type_len
= mono_metadata_decode_blob_size (named
, &named
);
8107 type_name
= g_malloc (type_len
+ 1);
8108 memcpy (type_name
, named
, type_len
);
8109 type_name
[type_len
] = 0;
8111 /* FIXME: lookup the type and check type consistency */
8114 name_len
= mono_metadata_decode_blob_size (named
, &named
);
8115 name
= g_malloc (name_len
+ 1);
8116 memcpy (name
, named
, name_len
);
8117 name
[name_len
] = 0;
8119 if (named_type
== 0x53) {
8120 MonoClassField
*field
= mono_class_get_field_from_name (mono_object_class (attr
), name
);
8121 void *val
= load_cattr_value (image
, field
->type
, named
, &named
);
8122 mono_field_set_value (attr
, field
, val
);
8123 if (!type_is_reference (field
->type
))
8125 } else if (named_type
== 0x54) {
8128 MonoType
*prop_type
;
8130 prop
= mono_class_get_property_from_name (mono_object_class (attr
), name
);
8131 /* can we have more that 1 arg in a custom attr named property? */
8132 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
8133 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
8134 pparams
[0] = load_cattr_value (image
, prop_type
, named
, &named
);
8135 mono_property_set_value (prop
, attr
, pparams
, NULL
);
8136 if (!type_is_reference (prop_type
))
8137 g_free (pparams
[0]);
8142 if (params
!= params_buf
)
8143 mono_gc_free_fixed (params
);
8149 * mono_reflection_create_custom_attr_data_args:
8151 * Create an array of typed and named arguments from the cattr blob given by DATA.
8152 * TYPED_ARGS and NAMED_ARGS will contain the objects representing the arguments,
8153 * NAMED_ARG_INFO will contain information about the named arguments.
8156 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
)
8158 MonoArray
*typedargs
, *namedargs
;
8159 MonoClass
*attrklass
;
8161 const char *p
= (const char*)data
;
8163 guint32 i
, j
, num_named
;
8164 CattrNamedArg
*arginfo
= NULL
;
8166 mono_class_init (method
->klass
);
8170 *named_arg_info
= NULL
;
8172 domain
= mono_domain_get ();
8174 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
8177 typedargs
= mono_array_new (domain
, mono_get_object_class (), mono_method_signature (method
)->param_count
);
8181 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
8185 val
= load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
8186 obj
= type_is_reference (mono_method_signature (method
)->params
[i
]) ?
8187 val
: mono_value_box (domain
, mono_class_from_mono_type (mono_method_signature (method
)->params
[i
]), val
);
8188 mono_array_setref (typedargs
, i
, obj
);
8190 if (!type_is_reference (mono_method_signature (method
)->params
[i
]))
8195 num_named
= read16 (named
);
8196 namedargs
= mono_array_new (domain
, mono_get_object_class (), num_named
);
8198 attrklass
= method
->klass
;
8200 arginfo
= g_new0 (CattrNamedArg
, num_named
);
8201 *named_arg_info
= arginfo
;
8203 for (j
= 0; j
< num_named
; j
++) {
8205 char *name
, named_type
, data_type
;
8206 named_type
= *named
++;
8207 data_type
= *named
++; /* type of data */
8208 if (data_type
== MONO_TYPE_SZARRAY
)
8209 data_type
= *named
++;
8210 if (data_type
== MONO_TYPE_ENUM
) {
8213 type_len
= mono_metadata_decode_blob_size (named
, &named
);
8214 type_name
= g_malloc (type_len
+ 1);
8215 memcpy (type_name
, named
, type_len
);
8216 type_name
[type_len
] = 0;
8218 /* FIXME: lookup the type and check type consistency */
8221 name_len
= mono_metadata_decode_blob_size (named
, &named
);
8222 name
= g_malloc (name_len
+ 1);
8223 memcpy (name
, named
, name_len
);
8224 name
[name_len
] = 0;
8226 if (named_type
== 0x53) {
8228 MonoClassField
*field
= mono_class_get_field_from_name (attrklass
, name
);
8231 arginfo
[j
].type
= field
->type
;
8232 arginfo
[j
].field
= field
;
8234 val
= load_cattr_value (image
, field
->type
, named
, &named
);
8235 obj
= type_is_reference (field
->type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (field
->type
), val
);
8236 mono_array_setref (namedargs
, j
, obj
);
8237 if (!type_is_reference (field
->type
))
8239 } else if (named_type
== 0x54) {
8241 MonoType
*prop_type
;
8242 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
8245 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
8246 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
8248 arginfo
[j
].type
= prop_type
;
8249 arginfo
[j
].prop
= prop
;
8251 val
= load_cattr_value (image
, prop_type
, named
, &named
);
8252 obj
= type_is_reference (prop_type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (prop_type
), val
);
8253 mono_array_setref (namedargs
, j
, obj
);
8254 if (!type_is_reference (prop_type
))
8260 *typed_args
= typedargs
;
8261 *named_args
= namedargs
;
8265 create_custom_attr_data (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
8267 MonoArray
*typedargs
, *namedargs
;
8268 static MonoMethod
*ctor
;
8272 CattrNamedArg
*arginfo
;
8275 mono_class_init (method
->klass
);
8278 ctor
= mono_class_get_method_from_name (mono_defaults
.customattribute_data_class
, ".ctor", 3);
8280 domain
= mono_domain_get ();
8282 /* This is for Attributes with no parameters */
8283 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
8284 params
[0] = mono_method_get_object (domain
, method
, NULL
);
8285 params
[1] = params
[2] = NULL
;
8286 mono_runtime_invoke (method
, attr
, params
, NULL
);
8290 mono_reflection_create_custom_attr_data_args (image
, method
, data
, len
, &typedargs
, &namedargs
, &arginfo
);
8291 if (!typedargs
|| !namedargs
)
8294 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
8295 MonoObject
*obj
= mono_array_get (typedargs
, MonoObject
*, i
);
8296 MonoObject
*typedarg
;
8298 typedarg
= create_cattr_typed_arg (mono_method_signature (method
)->params
[i
], obj
);
8299 mono_array_setref (typedargs
, i
, typedarg
);
8302 for (i
= 0; i
< mono_array_length (namedargs
); ++i
) {
8303 MonoObject
*obj
= mono_array_get (namedargs
, MonoObject
*, i
);
8304 MonoObject
*typedarg
, *namedarg
, *minfo
;
8306 if (arginfo
[i
].prop
)
8307 minfo
= (MonoObject
*)mono_property_get_object (domain
, NULL
, arginfo
[i
].prop
);
8309 minfo
= (MonoObject
*)mono_field_get_object (domain
, NULL
, arginfo
[i
].field
);
8311 typedarg
= create_cattr_typed_arg (arginfo
[i
].type
, obj
);
8312 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
8314 mono_array_setref (namedargs
, i
, namedarg
);
8317 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
8318 params
[0] = mono_method_get_object (domain
, method
, NULL
);
8319 params
[1] = typedargs
;
8320 params
[2] = namedargs
;
8321 mono_runtime_invoke (ctor
, attr
, params
, NULL
);
8326 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
8332 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, cinfo
->num_attrs
);
8333 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8334 if (!cinfo
->attrs
[i
].ctor
)
8335 /* The cattr type is not finished yet */
8336 /* We should include the type name but cinfo doesn't contain it */
8337 mono_raise_exception (mono_get_exception_type_load (NULL
, NULL
));
8338 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
8339 mono_array_setref (result
, i
, attr
);
8345 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
)
8352 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8353 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
))
8357 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, n
);
8359 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8360 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
)) {
8361 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
8362 mono_array_setref (result
, n
, attr
);
8370 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
)
8376 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, cinfo
->num_attrs
);
8377 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8378 attr
= create_custom_attr_data (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
8379 mono_array_setref (result
, i
, attr
);
8385 * mono_custom_attrs_from_index:
8387 * Returns: NULL if no attributes are found or if a loading error occurs.
8390 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
8392 guint32 mtoken
, i
, len
;
8393 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
8395 MonoCustomAttrInfo
*ainfo
;
8396 GList
*tmp
, *list
= NULL
;
8399 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
8401 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
8405 while (i
< ca
->rows
) {
8406 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
8408 list
= g_list_prepend (list
, GUINT_TO_POINTER (i
));
8411 len
= g_list_length (list
);
8414 ainfo
= g_malloc0 (MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * len
);
8415 ainfo
->num_attrs
= len
;
8416 ainfo
->image
= image
;
8417 for (i
= 0, tmp
= list
; i
< len
; ++i
, tmp
= tmp
->next
) {
8418 mono_metadata_decode_row (ca
, GPOINTER_TO_UINT (tmp
->data
), cols
, MONO_CUSTOM_ATTR_SIZE
);
8419 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
8420 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
8421 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
8422 mtoken
|= MONO_TOKEN_METHOD_DEF
;
8424 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
8425 mtoken
|= MONO_TOKEN_MEMBER_REF
;
8428 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
8431 ainfo
->attrs
[i
].ctor
= mono_get_method (image
, mtoken
, NULL
);
8432 if (!ainfo
->attrs
[i
].ctor
) {
8433 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image
->name
, mtoken
);
8438 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
8439 ainfo
->attrs
[i
].data_size
= mono_metadata_decode_value (data
, &data
);
8440 ainfo
->attrs
[i
].data
= (guchar
*)data
;
8448 mono_custom_attrs_from_method (MonoMethod
*method
)
8453 * An instantiated method has the same cattrs as the generic method definition.
8455 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8456 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8458 if (method
->is_inflated
)
8459 method
= ((MonoMethodInflated
*) method
)->declaring
;
8461 if (method
->dynamic
|| method
->klass
->image
->dynamic
)
8462 return lookup_custom_attr (method
->klass
->image
, method
);
8465 /* Synthetic methods */
8468 idx
= mono_method_get_index (method
);
8469 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8470 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
8471 return mono_custom_attrs_from_index (method
->klass
->image
, idx
);
8475 mono_custom_attrs_from_class (MonoClass
*klass
)
8479 if (klass
->generic_class
)
8480 klass
= klass
->generic_class
->container_class
;
8482 if (klass
->image
->dynamic
)
8483 return lookup_custom_attr (klass
->image
, klass
);
8485 if (klass
->byval_arg
.type
== MONO_TYPE_VAR
|| klass
->byval_arg
.type
== MONO_TYPE_MVAR
) {
8486 idx
= mono_metadata_token_index (klass
->sizes
.generic_param_token
);
8487 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8488 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
8490 idx
= mono_metadata_token_index (klass
->type_token
);
8491 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8492 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
8494 return mono_custom_attrs_from_index (klass
->image
, idx
);
8498 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
8502 if (assembly
->image
->dynamic
)
8503 return lookup_custom_attr (assembly
->image
, assembly
);
8504 idx
= 1; /* there is only one assembly */
8505 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8506 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
8507 return mono_custom_attrs_from_index (assembly
->image
, idx
);
8510 static MonoCustomAttrInfo
*
8511 mono_custom_attrs_from_module (MonoImage
*image
)
8516 return lookup_custom_attr (image
, image
);
8517 idx
= 1; /* there is only one module */
8518 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8519 idx
|= MONO_CUSTOM_ATTR_MODULE
;
8520 return mono_custom_attrs_from_index (image
, idx
);
8524 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
8528 if (klass
->image
->dynamic
) {
8529 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
8530 return lookup_custom_attr (klass
->image
, property
);
8532 idx
= find_property_index (klass
, property
);
8533 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8534 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
8535 return mono_custom_attrs_from_index (klass
->image
, idx
);
8539 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
8543 if (klass
->image
->dynamic
) {
8544 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
8545 return lookup_custom_attr (klass
->image
, event
);
8547 idx
= find_event_index (klass
, event
);
8548 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8549 idx
|= MONO_CUSTOM_ATTR_EVENT
;
8550 return mono_custom_attrs_from_index (klass
->image
, idx
);
8554 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
8557 if (klass
->image
->dynamic
) {
8558 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
8559 return lookup_custom_attr (klass
->image
, field
);
8561 idx
= find_field_index (klass
, field
);
8562 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8563 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
8564 return mono_custom_attrs_from_index (klass
->image
, idx
);
8568 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
8571 guint32 i
, idx
, method_index
;
8572 guint32 param_list
, param_last
, param_pos
, found
;
8574 MonoReflectionMethodAux
*aux
;
8577 * An instantiated method has the same cattrs as the generic method definition.
8579 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8580 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8582 if (method
->is_inflated
)
8583 method
= ((MonoMethodInflated
*) method
)->declaring
;
8585 if (method
->klass
->image
->dynamic
) {
8586 MonoCustomAttrInfo
*res
, *ainfo
;
8589 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
8590 if (!aux
|| !aux
->param_cattr
)
8593 /* Need to copy since it will be freed later */
8594 ainfo
= aux
->param_cattr
[param
];
8597 size
= MONO_SIZEOF_CUSTOM_ATTR_INFO
+ sizeof (MonoCustomAttrEntry
) * ainfo
->num_attrs
;
8598 res
= g_malloc0 (size
);
8599 memcpy (res
, ainfo
, size
);
8603 image
= method
->klass
->image
;
8604 method_index
= mono_method_get_index (method
);
8605 ca
= &image
->tables
[MONO_TABLE_METHOD
];
8607 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
8608 if (method_index
== ca
->rows
) {
8609 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8610 param_last
= ca
->rows
+ 1;
8612 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
8613 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8616 for (i
= param_list
; i
< param_last
; ++i
) {
8617 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
8618 if (param_pos
== param
) {
8626 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8627 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
8628 return mono_custom_attrs_from_index (image
, idx
);
8632 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8636 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8637 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8638 if (mono_class_has_parent (klass
, attr_klass
) || (MONO_CLASS_IS_INTERFACE (attr_klass
) && mono_class_is_assignable_from (attr_klass
, klass
)))
8645 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8652 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8653 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8654 if (mono_class_has_parent (klass
, attr_klass
)) {
8659 if (attr_index
== -1)
8662 attrs
= mono_custom_attrs_construct (ainfo
);
8664 return mono_array_get (attrs
, MonoObject
*, attr_index
);
8670 * mono_reflection_get_custom_attrs_info:
8671 * @obj: a reflection object handle
8673 * Return the custom attribute info for attributes defined for the
8674 * reflection handle @obj. The objects.
8676 * FIXME this function leaks like a sieve for SRE objects.
8679 mono_reflection_get_custom_attrs_info (MonoObject
*obj
)
8682 MonoCustomAttrInfo
*cinfo
= NULL
;
8684 klass
= obj
->vtable
->klass
;
8685 if (klass
== mono_defaults
.monotype_class
) {
8686 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
8687 klass
= mono_class_from_mono_type (type
);
8688 cinfo
= mono_custom_attrs_from_class (klass
);
8689 } else if (strcmp ("Assembly", klass
->name
) == 0 || strcmp ("MonoAssembly", klass
->name
) == 0) {
8690 MonoReflectionAssembly
*rassembly
= (MonoReflectionAssembly
*)obj
;
8691 cinfo
= mono_custom_attrs_from_assembly (rassembly
->assembly
);
8692 } else if (strcmp ("Module", klass
->name
) == 0) {
8693 MonoReflectionModule
*module
= (MonoReflectionModule
*)obj
;
8694 cinfo
= mono_custom_attrs_from_module (module
->image
);
8695 } else if (strcmp ("MonoProperty", klass
->name
) == 0) {
8696 MonoReflectionProperty
*rprop
= (MonoReflectionProperty
*)obj
;
8697 cinfo
= mono_custom_attrs_from_property (rprop
->property
->parent
, rprop
->property
);
8698 } else if (strcmp ("MonoEvent", klass
->name
) == 0) {
8699 MonoReflectionMonoEvent
*revent
= (MonoReflectionMonoEvent
*)obj
;
8700 cinfo
= mono_custom_attrs_from_event (revent
->event
->parent
, revent
->event
);
8701 } else if (strcmp ("MonoField", klass
->name
) == 0) {
8702 MonoReflectionField
*rfield
= (MonoReflectionField
*)obj
;
8703 cinfo
= mono_custom_attrs_from_field (rfield
->field
->parent
, rfield
->field
);
8704 } else if ((strcmp ("MonoMethod", klass
->name
) == 0) || (strcmp ("MonoCMethod", klass
->name
) == 0)) {
8705 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8706 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8707 } else if ((strcmp ("MonoGenericMethod", klass
->name
) == 0) || (strcmp ("MonoGenericCMethod", klass
->name
) == 0)) {
8708 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8709 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8710 } else if (strcmp ("ParameterInfo", klass
->name
) == 0) {
8711 MonoReflectionParameter
*param
= (MonoReflectionParameter
*)obj
;
8712 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
8713 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
8714 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
8715 cinfo
= mono_custom_attrs_from_param (rmethod
->method
, param
->PositionImpl
+ 1);
8716 } else if (is_sr_mono_property (member_class
)) {
8717 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
8719 if (!(method
= prop
->property
->get
))
8720 method
= prop
->property
->set
;
8723 cinfo
= mono_custom_attrs_from_param (method
, param
->PositionImpl
+ 1);
8725 #ifndef DISABLE_REFLECTION_EMIT
8726 else if (is_sre_method_on_tb_inst (member_class
)) {/*XXX This is a workaround for Compiler Context*/
8727 MonoMethod
*method
= mono_reflection_method_on_tb_inst_get_handle ((MonoReflectionMethodOnTypeBuilderInst
*)param
->MemberImpl
);
8728 cinfo
= mono_custom_attrs_from_param (method
, param
->PositionImpl
+ 1);
8729 } else if (is_sre_ctor_on_tb_inst (member_class
)) { /*XX This is a workaround for Compiler Context*/
8730 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)param
->MemberImpl
;
8731 MonoMethod
*method
= NULL
;
8732 if (is_sre_ctor_builder (mono_object_class (c
->cb
)))
8733 method
= ((MonoReflectionCtorBuilder
*)c
->cb
)->mhandle
;
8734 else if (is_sr_mono_cmethod (mono_object_class (c
->cb
)))
8735 method
= ((MonoReflectionMethod
*)c
->cb
)->method
;
8737 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
));
8739 cinfo
= mono_custom_attrs_from_param (method
, param
->PositionImpl
+ 1);
8743 char *type_name
= mono_type_get_full_name (member_class
);
8744 char *msg
= g_strdup_printf ("Custom attributes on a ParamInfo with member %s are not supported", type_name
);
8745 MonoException
*ex
= mono_get_exception_not_supported (msg
);
8748 mono_raise_exception (ex
);
8750 } else if (strcmp ("AssemblyBuilder", klass
->name
) == 0) {
8751 MonoReflectionAssemblyBuilder
*assemblyb
= (MonoReflectionAssemblyBuilder
*)obj
;
8752 cinfo
= mono_custom_attrs_from_builders (NULL
, assemblyb
->assembly
.assembly
->image
, assemblyb
->cattrs
);
8753 } else if (strcmp ("TypeBuilder", klass
->name
) == 0) {
8754 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
8755 cinfo
= mono_custom_attrs_from_builders (NULL
, &tb
->module
->dynamic_image
->image
, tb
->cattrs
);
8756 } else if (strcmp ("ModuleBuilder", klass
->name
) == 0) {
8757 MonoReflectionModuleBuilder
*mb
= (MonoReflectionModuleBuilder
*)obj
;
8758 cinfo
= mono_custom_attrs_from_builders (NULL
, &mb
->dynamic_image
->image
, mb
->cattrs
);
8759 } else if (strcmp ("ConstructorBuilder", klass
->name
) == 0) {
8760 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
8761 cinfo
= mono_custom_attrs_from_builders (NULL
, cb
->mhandle
->klass
->image
, cb
->cattrs
);
8762 } else if (strcmp ("MethodBuilder", klass
->name
) == 0) {
8763 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
8764 cinfo
= mono_custom_attrs_from_builders (NULL
, mb
->mhandle
->klass
->image
, mb
->cattrs
);
8765 } else if (strcmp ("FieldBuilder", klass
->name
) == 0) {
8766 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
8767 cinfo
= mono_custom_attrs_from_builders (NULL
, &((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
->image
, fb
->cattrs
);
8768 } else if (strcmp ("MonoGenericClass", klass
->name
) == 0) {
8769 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)obj
;
8770 cinfo
= mono_reflection_get_custom_attrs_info ((MonoObject
*)gclass
->generic_type
);
8771 } else { /* handle other types here... */
8772 g_error ("get custom attrs not yet supported for %s", klass
->name
);
8779 * mono_reflection_get_custom_attrs_by_type:
8780 * @obj: a reflection object handle
8782 * Return an array with all the custom attributes defined of the
8783 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8784 * of that type are returned. The objects are fully build. Return NULL if a loading error
8788 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj
, MonoClass
*attr_klass
)
8791 MonoCustomAttrInfo
*cinfo
;
8793 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8796 result
= mono_custom_attrs_construct_by_type (cinfo
, attr_klass
);
8798 result
= mono_custom_attrs_construct (cinfo
);
8800 mono_custom_attrs_free (cinfo
);
8802 if (mono_loader_get_last_error ())
8804 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, 0);
8811 * mono_reflection_get_custom_attrs:
8812 * @obj: a reflection object handle
8814 * Return an array with all the custom attributes defined of the
8815 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8819 mono_reflection_get_custom_attrs (MonoObject
*obj
)
8821 return mono_reflection_get_custom_attrs_by_type (obj
, NULL
);
8825 * mono_reflection_get_custom_attrs_data:
8826 * @obj: a reflection obj handle
8828 * Returns an array of System.Reflection.CustomAttributeData,
8829 * which include information about attributes reflected on
8830 * types loaded using the Reflection Only methods
8833 mono_reflection_get_custom_attrs_data (MonoObject
*obj
)
8836 MonoCustomAttrInfo
*cinfo
;
8838 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8840 result
= mono_custom_attrs_data_construct (cinfo
);
8842 mono_custom_attrs_free (cinfo
);
8844 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, 0);
8849 static MonoReflectionType
*
8850 mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
)
8852 static MonoMethod
*method_get_underlying_system_type
= NULL
;
8853 MonoMethod
*usertype_method
;
8855 if (!method_get_underlying_system_type
)
8856 method_get_underlying_system_type
= mono_class_get_method_from_name (mono_defaults
.systemtype_class
, "get_UnderlyingSystemType", 0);
8857 usertype_method
= mono_object_get_virtual_method ((MonoObject
*) t
, method_get_underlying_system_type
);
8858 return (MonoReflectionType
*) mono_runtime_invoke (usertype_method
, t
, NULL
, NULL
);
8863 is_corlib_type (MonoClass
*class)
8865 return class->image
== mono_defaults
.corlib
;
8868 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8869 static MonoClass *cached_class; \
8871 return cached_class == _class; \
8872 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8873 cached_class = _class; \
8880 #ifndef DISABLE_REFLECTION_EMIT
8882 is_sre_array (MonoClass
*class)
8884 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8888 is_sre_byref (MonoClass
*class)
8890 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8894 is_sre_pointer (MonoClass
*class)
8896 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8900 is_sre_generic_instance (MonoClass
*class)
8902 check_corlib_type_cached (class, "System.Reflection", "MonoGenericClass");
8906 is_sre_type_builder (MonoClass
*class)
8908 check_corlib_type_cached (class, "System.Reflection.Emit", "TypeBuilder");
8912 is_sre_method_builder (MonoClass
*class)
8914 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodBuilder");
8918 is_sre_ctor_builder (MonoClass
*class)
8920 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorBuilder");
8924 is_sre_field_builder (MonoClass
*class)
8926 check_corlib_type_cached (class, "System.Reflection.Emit", "FieldBuilder");
8930 is_sre_method_on_tb_inst (MonoClass
*class)
8932 check_corlib_type_cached (class, "System.Reflection.Emit", "MethodOnTypeBuilderInst");
8936 is_sre_ctor_on_tb_inst (MonoClass
*class)
8938 check_corlib_type_cached (class, "System.Reflection.Emit", "ConstructorOnTypeBuilderInst");
8942 mono_reflection_type_get_handle (MonoReflectionType
* ref
)
8950 if (is_usertype (ref
)) {
8951 ref
= mono_reflection_type_get_underlying_system_type (ref
);
8952 if (ref
== NULL
|| is_usertype (ref
))
8958 class = mono_object_class (ref
);
8960 if (is_sre_array (class)) {
8962 MonoReflectionArrayType
*sre_array
= (MonoReflectionArrayType
*)ref
;
8963 MonoType
*base
= mono_reflection_type_get_handle (sre_array
->element_type
);
8965 if (sre_array
->rank
== 0) //single dimentional array
8966 res
= &mono_array_class_get (mono_class_from_mono_type (base
), 1)->byval_arg
;
8968 res
= &mono_bounded_array_class_get (mono_class_from_mono_type (base
), sre_array
->rank
, TRUE
)->byval_arg
;
8969 sre_array
->type
.type
= res
;
8971 } else if (is_sre_byref (class)) {
8973 MonoReflectionDerivedType
*sre_byref
= (MonoReflectionDerivedType
*)ref
;
8974 MonoType
*base
= mono_reflection_type_get_handle (sre_byref
->element_type
);
8976 res
= &mono_class_from_mono_type (base
)->this_arg
;
8977 sre_byref
->type
.type
= res
;
8979 } else if (is_sre_pointer (class)) {
8981 MonoReflectionDerivedType
*sre_pointer
= (MonoReflectionDerivedType
*)ref
;
8982 MonoType
*base
= mono_reflection_type_get_handle (sre_pointer
->element_type
);
8984 res
= &mono_ptr_class_get (base
)->byval_arg
;
8985 sre_pointer
->type
.type
= res
;
8987 } else if (is_sre_generic_instance (class)) {
8988 MonoType
*res
, **types
;
8989 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)ref
;
8992 count
= mono_array_length (gclass
->type_arguments
);
8993 types
= g_new0 (MonoType
*, count
);
8994 for (i
= 0; i
< count
; ++i
) {
8995 MonoReflectionType
*t
= mono_array_get (gclass
->type_arguments
, gpointer
, i
);
8996 types
[i
] = mono_reflection_type_get_handle (t
);
9003 res
= mono_reflection_bind_generic_parameters (gclass
->generic_type
, count
, types
);
9006 gclass
->type
.type
= res
;
9010 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref
)->byval_arg
));
9017 mono_reflection_create_unmanaged_type (MonoReflectionType
*type
)
9019 mono_reflection_type_get_handle (type
);
9023 mono_reflection_register_with_runtime (MonoReflectionType
*type
)
9025 MonoType
*res
= mono_reflection_type_get_handle (type
);
9026 MonoDomain
*domain
= mono_object_domain ((MonoObject
*)type
);
9030 mono_raise_exception (mono_get_exception_argument (NULL
, "Invalid generic instantiation, one or more arguments are not proper user types"));
9032 class = mono_class_from_mono_type (res
);
9034 mono_loader_lock (); /*same locking as mono_type_get_object*/
9035 mono_domain_lock (domain
);
9037 if (!class->image
->dynamic
) {
9038 mono_class_setup_supertypes (class);
9040 if (!domain
->type_hash
)
9041 domain
->type_hash
= mono_g_hash_table_new_type ((GHashFunc
)mymono_metadata_type_hash
,
9042 (GCompareFunc
)mymono_metadata_type_equal
, MONO_HASH_VALUE_GC
);
9043 mono_g_hash_table_insert (domain
->type_hash
, res
, type
);
9045 mono_domain_unlock (domain
);
9046 mono_loader_unlock ();
9050 * LOCKING: Assumes the loader lock is held.
9052 static MonoMethodSignature
*
9053 parameters_to_signature (MonoImage
*image
, MonoArray
*parameters
) {
9054 MonoMethodSignature
*sig
;
9057 count
= parameters
? mono_array_length (parameters
): 0;
9059 sig
= image_g_malloc0 (image
, MONO_SIZEOF_METHOD_SIGNATURE
+ sizeof (MonoType
*) * count
);
9060 sig
->param_count
= count
;
9061 sig
->sentinelpos
= -1; /* FIXME */
9062 for (i
= 0; i
< count
; ++i
)
9063 sig
->params
[i
] = mono_type_array_get_and_resolve (parameters
, i
);
9068 * LOCKING: Assumes the loader lock is held.
9070 static MonoMethodSignature
*
9071 ctor_builder_to_signature (MonoImage
*image
, MonoReflectionCtorBuilder
*ctor
) {
9072 MonoMethodSignature
*sig
;
9074 sig
= parameters_to_signature (image
, ctor
->parameters
);
9075 sig
->hasthis
= ctor
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
9076 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
9081 * LOCKING: Assumes the loader lock is held.
9083 static MonoMethodSignature
*
9084 method_builder_to_signature (MonoImage
*image
, MonoReflectionMethodBuilder
*method
) {
9085 MonoMethodSignature
*sig
;
9087 sig
= parameters_to_signature (image
, method
->parameters
);
9088 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
9089 sig
->ret
= method
->rtype
? mono_reflection_type_get_handle ((MonoReflectionType
*)method
->rtype
): &mono_defaults
.void_class
->byval_arg
;
9090 sig
->generic_param_count
= method
->generic_params
? mono_array_length (method
->generic_params
) : 0;
9094 static MonoMethodSignature
*
9095 dynamic_method_to_signature (MonoReflectionDynamicMethod
*method
) {
9096 MonoMethodSignature
*sig
;
9098 sig
= parameters_to_signature (NULL
, method
->parameters
);
9099 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
9100 sig
->ret
= method
->rtype
? mono_reflection_type_get_handle (method
->rtype
): &mono_defaults
.void_class
->byval_arg
;
9101 sig
->generic_param_count
= 0;
9106 get_prop_name_and_type (MonoObject
*prop
, char **name
, MonoType
**type
)
9108 MonoClass
*klass
= mono_object_class (prop
);
9109 if (strcmp (klass
->name
, "PropertyBuilder") == 0) {
9110 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*)prop
;
9111 *name
= mono_string_to_utf8 (pb
->name
);
9112 *type
= mono_reflection_type_get_handle ((MonoReflectionType
*)pb
->type
);
9114 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)prop
;
9115 *name
= g_strdup (p
->property
->name
);
9116 if (p
->property
->get
)
9117 *type
= mono_method_signature (p
->property
->get
)->ret
;
9119 *type
= mono_method_signature (p
->property
->set
)->params
[mono_method_signature (p
->property
->set
)->param_count
- 1];
9124 get_field_name_and_type (MonoObject
*field
, char **name
, MonoType
**type
)
9126 MonoClass
*klass
= mono_object_class (field
);
9127 if (strcmp (klass
->name
, "FieldBuilder") == 0) {
9128 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)field
;
9129 *name
= mono_string_to_utf8 (fb
->name
);
9130 *type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
);
9132 MonoReflectionField
*f
= (MonoReflectionField
*)field
;
9133 *name
= g_strdup (mono_field_get_name (f
->field
));
9134 *type
= f
->field
->type
;
9138 #else /* DISABLE_REFLECTION_EMIT */
9141 mono_reflection_register_with_runtime (MonoReflectionType
*type
)
9147 is_sre_type_builder (MonoClass
*class)
9153 is_sre_generic_instance (MonoClass
*class)
9158 #endif /* !DISABLE_REFLECTION_EMIT */
9162 is_sr_mono_field (MonoClass
*class)
9164 check_corlib_type_cached (class, "System.Reflection", "MonoField");
9168 is_sr_mono_property (MonoClass
*class)
9170 check_corlib_type_cached (class, "System.Reflection", "MonoProperty");
9174 is_sr_mono_method (MonoClass
*class)
9176 check_corlib_type_cached (class, "System.Reflection", "MonoMethod");
9180 is_sr_mono_cmethod (MonoClass
*class)
9182 check_corlib_type_cached (class, "System.Reflection", "MonoCMethod");
9186 is_sr_mono_generic_method (MonoClass
*class)
9188 check_corlib_type_cached (class, "System.Reflection", "MonoGenericMethod");
9192 is_sr_mono_generic_cmethod (MonoClass
*class)
9194 check_corlib_type_cached (class, "System.Reflection", "MonoGenericCMethod");
9198 mono_class_is_reflection_method_or_constructor (MonoClass
*class)
9200 return is_sr_mono_method (class) || is_sr_mono_cmethod (class) || is_sr_mono_generic_method (class) || is_sr_mono_generic_cmethod (class);
9204 is_usertype (MonoReflectionType
*ref
)
9206 MonoClass
*class = mono_object_class (ref
);
9207 return class->image
!= mono_defaults
.corlib
|| strcmp ("TypeDelegator", class->name
) == 0;
9210 static MonoReflectionType
*
9211 mono_reflection_type_resolve_user_types (MonoReflectionType
*type
)
9213 if (!type
|| type
->type
)
9216 if (is_usertype (type
)) {
9217 type
= mono_reflection_type_get_underlying_system_type (type
);
9218 if (is_usertype (type
))
9219 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
9225 * Encode a value in a custom attribute stream of bytes.
9226 * The value to encode is either supplied as an object in argument val
9227 * (valuetypes are boxed), or as a pointer to the data in the
9229 * @type represents the type of the value
9230 * @buffer is the start of the buffer
9231 * @p the current position in the buffer
9232 * @buflen contains the size of the buffer and is used to return the new buffer size
9233 * if this needs to be realloced.
9234 * @retbuffer and @retp return the start and the position of the buffer
9237 encode_cattr_value (MonoAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, MonoObject
*arg
, char *argval
)
9239 MonoTypeEnum simple_type
;
9241 if ((p
-buffer
) + 10 >= *buflen
) {
9244 newbuf
= g_realloc (buffer
, *buflen
);
9245 p
= newbuf
+ (p
-buffer
);
9249 argval
= ((char*)arg
+ sizeof (MonoObject
));
9250 simple_type
= type
->type
;
9252 switch (simple_type
) {
9253 case MONO_TYPE_BOOLEAN
:
9258 case MONO_TYPE_CHAR
:
9261 swap_with_size (p
, argval
, 2, 1);
9267 swap_with_size (p
, argval
, 4, 1);
9271 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
9281 swap_with_size (p
, argval
, 8, 1);
9287 swap_with_size (p
, argval
, 8, 1);
9290 case MONO_TYPE_VALUETYPE
:
9291 if (type
->data
.klass
->enumtype
) {
9292 simple_type
= mono_class_enum_basetype (type
->data
.klass
)->type
;
9295 g_warning ("generic valutype %s not handled in custom attr value decoding", type
->data
.klass
->name
);
9298 case MONO_TYPE_STRING
: {
9305 str
= mono_string_to_utf8 ((MonoString
*)arg
);
9306 slen
= strlen (str
);
9307 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
9311 newbuf
= g_realloc (buffer
, *buflen
);
9312 p
= newbuf
+ (p
-buffer
);
9315 mono_metadata_encode_value (slen
, p
, &p
);
9316 memcpy (p
, str
, slen
);
9321 case MONO_TYPE_CLASS
: {
9329 str
= type_get_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType
*)arg
), NULL
);
9330 slen
= strlen (str
);
9331 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
9335 newbuf
= g_realloc (buffer
, *buflen
);
9336 p
= newbuf
+ (p
-buffer
);
9339 mono_metadata_encode_value (slen
, p
, &p
);
9340 memcpy (p
, str
, slen
);
9345 case MONO_TYPE_SZARRAY
: {
9347 MonoClass
*eclass
, *arg_eclass
;
9350 *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff;
9353 len
= mono_array_length ((MonoArray
*)arg
);
9355 *p
++ = (len
>> 8) & 0xff;
9356 *p
++ = (len
>> 16) & 0xff;
9357 *p
++ = (len
>> 24) & 0xff;
9359 *retbuffer
= buffer
;
9360 eclass
= type
->data
.klass
;
9361 arg_eclass
= mono_object_class (arg
)->element_class
;
9364 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
9365 eclass
= mono_defaults
.object_class
;
9367 if (eclass
== mono_defaults
.object_class
&& arg_eclass
->valuetype
) {
9368 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
9369 int elsize
= mono_class_array_element_size (arg_eclass
);
9370 for (i
= 0; i
< len
; ++i
) {
9371 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &arg_eclass
->byval_arg
, NULL
, elptr
);
9374 } else if (eclass
->valuetype
&& arg_eclass
->valuetype
) {
9375 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
9376 int elsize
= mono_class_array_element_size (eclass
);
9377 for (i
= 0; i
< len
; ++i
) {
9378 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, NULL
, elptr
);
9382 for (i
= 0; i
< len
; ++i
) {
9383 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, mono_array_get ((MonoArray
*)arg
, MonoObject
*, i
), NULL
);
9388 case MONO_TYPE_OBJECT
: {
9394 * The parameter type is 'object' but the type of the actual
9395 * argument is not. So we have to add type information to the blob
9396 * too. This is completely undocumented in the spec.
9400 *p
++ = MONO_TYPE_STRING
; // It's same hack as MS uses
9405 klass
= mono_object_class (arg
);
9407 if (mono_object_isinst (arg
, mono_defaults
.systemtype_class
)) {
9410 } else if (klass
->enumtype
) {
9412 } else if (klass
== mono_defaults
.string_class
) {
9413 simple_type
= MONO_TYPE_STRING
;
9416 } else if (klass
->rank
== 1) {
9418 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_OBJECT
)
9419 /* See Partition II, Appendix B3 */
9422 *p
++ = klass
->element_class
->byval_arg
.type
;
9423 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &klass
->byval_arg
, arg
, NULL
);
9425 } else if (klass
->byval_arg
.type
>= MONO_TYPE_BOOLEAN
&& klass
->byval_arg
.type
<= MONO_TYPE_R8
) {
9426 *p
++ = simple_type
= klass
->byval_arg
.type
;
9429 g_error ("unhandled type in custom attr");
9431 str
= type_get_qualified_name (mono_class_get_type(klass
), NULL
);
9432 slen
= strlen (str
);
9433 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
9437 newbuf
= g_realloc (buffer
, *buflen
);
9438 p
= newbuf
+ (p
-buffer
);
9441 mono_metadata_encode_value (slen
, p
, &p
);
9442 memcpy (p
, str
, slen
);
9445 simple_type
= mono_class_enum_basetype (klass
)->type
;
9449 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type
);
9452 *retbuffer
= buffer
;
9456 encode_field_or_prop_type (MonoType
*type
, char *p
, char **retp
)
9458 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
9459 char *str
= type_get_qualified_name (type
, NULL
);
9460 int slen
= strlen (str
);
9464 * This seems to be optional...
9467 mono_metadata_encode_value (slen
, p
, &p
);
9468 memcpy (p
, str
, slen
);
9471 } else if (type
->type
== MONO_TYPE_OBJECT
) {
9473 } else if (type
->type
== MONO_TYPE_CLASS
) {
9474 /* it should be a type: encode_cattr_value () has the check */
9477 mono_metadata_encode_value (type
->type
, p
, &p
);
9478 if (type
->type
== MONO_TYPE_SZARRAY
)
9479 /* See the examples in Partition VI, Annex B */
9480 encode_field_or_prop_type (&type
->data
.klass
->byval_arg
, p
, &p
);
9486 #ifndef DISABLE_REFLECTION_EMIT
9488 encode_named_val (MonoReflectionAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, char *name
, MonoObject
*value
)
9491 /* Preallocate a large enough buffer */
9492 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
9493 char *str
= type_get_qualified_name (type
, NULL
);
9496 } else if (type
->type
== MONO_TYPE_SZARRAY
&& type
->data
.klass
->enumtype
) {
9497 char *str
= type_get_qualified_name (&type
->data
.klass
->byval_arg
, NULL
);
9503 len
+= strlen (name
);
9505 if ((p
-buffer
) + 20 + len
>= *buflen
) {
9509 newbuf
= g_realloc (buffer
, *buflen
);
9510 p
= newbuf
+ (p
-buffer
);
9514 encode_field_or_prop_type (type
, p
, &p
);
9516 len
= strlen (name
);
9517 mono_metadata_encode_value (len
, p
, &p
);
9518 memcpy (p
, name
, len
);
9520 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, buflen
, type
, value
, NULL
);
9522 *retbuffer
= buffer
;
9526 * mono_reflection_get_custom_attrs_blob:
9527 * @ctor: custom attribute constructor
9528 * @ctorArgs: arguments o the constructor
9534 * Creates the blob of data that needs to be saved in the metadata and that represents
9535 * the custom attributed described by @ctor, @ctorArgs etc.
9536 * Returns: a Byte array representing the blob of data.
9539 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
9542 MonoMethodSignature
*sig
;
9547 MONO_ARCH_SAVE_REGS
;
9549 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
9550 /* sig is freed later so allocate it in the heap */
9551 sig
= ctor_builder_to_signature (NULL
, (MonoReflectionCtorBuilder
*)ctor
);
9553 sig
= mono_method_signature (((MonoReflectionMethod
*)ctor
)->method
);
9556 g_assert (mono_array_length (ctorArgs
) == sig
->param_count
);
9558 p
= buffer
= g_malloc (buflen
);
9559 /* write the prolog */
9562 for (i
= 0; i
< sig
->param_count
; ++i
) {
9563 arg
= mono_array_get (ctorArgs
, MonoObject
*, i
);
9564 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, &buflen
, sig
->params
[i
], arg
, NULL
);
9568 i
+= mono_array_length (properties
);
9570 i
+= mono_array_length (fields
);
9572 *p
++ = (i
>> 8) & 0xff;
9575 for (i
= 0; i
< mono_array_length (properties
); ++i
) {
9579 prop
= mono_array_get (properties
, gpointer
, i
);
9580 get_prop_name_and_type (prop
, &pname
, &ptype
);
9581 *p
++ = 0x54; /* PROPERTY signature */
9582 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ptype
, pname
, (MonoObject
*)mono_array_get (propValues
, gpointer
, i
));
9589 for (i
= 0; i
< mono_array_length (fields
); ++i
) {
9593 field
= mono_array_get (fields
, gpointer
, i
);
9594 get_field_name_and_type (field
, &fname
, &ftype
);
9595 *p
++ = 0x53; /* FIELD signature */
9596 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ftype
, fname
, (MonoObject
*)mono_array_get (fieldValues
, gpointer
, i
));
9601 g_assert (p
- buffer
<= buflen
);
9602 buflen
= p
- buffer
;
9603 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
9604 p
= mono_array_addr (result
, char, 0);
9605 memcpy (p
, buffer
, buflen
);
9607 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod"))
9613 * mono_reflection_setup_internal_class:
9614 * @tb: a TypeBuilder object
9616 * Creates a MonoClass that represents the TypeBuilder.
9617 * This is a trick that lets us simplify a lot of reflection code
9618 * (and will allow us to support Build and Run assemblies easier).
9621 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
9624 MonoClass
*klass
, *parent
;
9626 MONO_ARCH_SAVE_REGS
;
9628 RESOLVE_TYPE (tb
->parent
);
9630 mono_loader_lock ();
9633 /* check so we can compile corlib correctly */
9634 if (strcmp (mono_object_class (tb
->parent
)->name
, "TypeBuilder") == 0) {
9635 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9636 parent
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
->parent
)->data
.klass
;
9638 parent
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
->parent
));
9644 /* the type has already being created: it means we just have to change the parent */
9645 if (tb
->type
.type
) {
9646 klass
= mono_class_from_mono_type (tb
->type
.type
);
9647 klass
->parent
= NULL
;
9648 /* fool mono_class_setup_parent */
9649 klass
->supertypes
= NULL
;
9650 mono_class_setup_parent (klass
, parent
);
9651 mono_class_setup_mono_type (klass
);
9652 mono_loader_unlock ();
9656 klass
= mono_image_alloc0 (&tb
->module
->dynamic_image
->image
, sizeof (MonoClass
));
9658 klass
->image
= &tb
->module
->dynamic_image
->image
;
9660 klass
->inited
= 1; /* we lie to the runtime */
9661 klass
->name
= mono_string_to_utf8_image (klass
->image
, tb
->name
, &error
);
9662 if (!mono_error_ok (&error
))
9664 klass
->name_space
= mono_string_to_utf8_image (klass
->image
, tb
->nspace
, &error
);
9665 if (!mono_error_ok (&error
))
9667 klass
->type_token
= MONO_TOKEN_TYPE_DEF
| tb
->table_idx
;
9668 klass
->flags
= tb
->attrs
;
9670 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
9672 klass
->element_class
= klass
;
9674 if (mono_class_get_ref_info (klass
) == NULL
) {
9676 mono_class_set_ref_info (klass
, tb
);
9678 /* Put into cache so mono_class_get () will find it.
9679 Skip nested types as those should not be available on the global scope. */
9680 if (!tb
->nesting_type
) {
9681 mono_image_add_to_name_cache (klass
->image
, klass
->name_space
, klass
->name
, tb
->table_idx
);
9683 klass
->image
->reflection_info_unregister_classes
=
9684 g_slist_prepend (klass
->image
->reflection_info_unregister_classes
, klass
);
9687 g_assert (mono_class_get_ref_info (klass
) == tb
);
9690 mono_g_hash_table_insert (tb
->module
->dynamic_image
->tokens
,
9691 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF
| tb
->table_idx
), tb
);
9693 if (parent
!= NULL
) {
9694 mono_class_setup_parent (klass
, parent
);
9695 } else if (strcmp (klass
->name
, "Object") == 0 && strcmp (klass
->name_space
, "System") == 0) {
9696 const char *old_n
= klass
->name
;
9697 /* trick to get relative numbering right when compiling corlib */
9698 klass
->name
= "BuildingObject";
9699 mono_class_setup_parent (klass
, mono_defaults
.object_class
);
9700 klass
->name
= old_n
;
9703 if ((!strcmp (klass
->name
, "ValueType") && !strcmp (klass
->name_space
, "System")) ||
9704 (!strcmp (klass
->name
, "Object") && !strcmp (klass
->name_space
, "System")) ||
9705 (!strcmp (klass
->name
, "Enum") && !strcmp (klass
->name_space
, "System"))) {
9706 klass
->instance_size
= sizeof (MonoObject
);
9707 klass
->size_inited
= 1;
9708 mono_class_setup_vtable_general (klass
, NULL
, 0);
9711 mono_class_setup_mono_type (klass
);
9713 mono_class_setup_supertypes (klass
);
9716 * FIXME: handle interfaces.
9719 tb
->type
.type
= &klass
->byval_arg
;
9721 if (tb
->nesting_type
) {
9722 g_assert (tb
->nesting_type
->type
);
9723 klass
->nested_in
= mono_class_from_mono_type (mono_reflection_type_get_handle (tb
->nesting_type
));
9726 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9728 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
9730 mono_loader_unlock ();
9734 mono_loader_unlock ();
9735 mono_error_raise_exception (&error
);
9739 * mono_reflection_setup_generic_class:
9740 * @tb: a TypeBuilder object
9742 * Setup the generic class before adding the first generic parameter.
9745 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
9750 * mono_reflection_create_generic_class:
9751 * @tb: a TypeBuilder object
9753 * Creates the generic class after all generic parameters have been added.
9756 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
9761 MONO_ARCH_SAVE_REGS
;
9763 klass
= mono_class_from_mono_type (tb
->type
.type
);
9765 count
= tb
->generic_params
? mono_array_length (tb
->generic_params
) : 0;
9767 if (klass
->generic_container
|| (count
== 0))
9770 g_assert (tb
->generic_container
&& (tb
->generic_container
->owner
.klass
== klass
));
9772 klass
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
9774 klass
->generic_container
->owner
.klass
= klass
;
9775 klass
->generic_container
->type_argc
= count
;
9776 klass
->generic_container
->type_params
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericParamFull
) * count
);
9778 klass
->is_generic
= 1;
9780 for (i
= 0; i
< count
; i
++) {
9781 MonoReflectionGenericParam
*gparam
= mono_array_get (tb
->generic_params
, gpointer
, i
);
9782 MonoGenericParamFull
*param
= (MonoGenericParamFull
*) mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
)->data
.generic_param
;
9783 klass
->generic_container
->type_params
[i
] = *param
;
9784 /*Make sure we are a diferent type instance */
9785 klass
->generic_container
->type_params
[i
].param
.owner
= klass
->generic_container
;
9786 klass
->generic_container
->type_params
[i
].info
.pklass
= NULL
;
9788 g_assert (klass
->generic_container
->type_params
[i
].param
.owner
);
9791 klass
->generic_container
->context
.class_inst
= mono_get_shared_generic_inst (klass
->generic_container
);
9795 * mono_reflection_create_internal_class:
9796 * @tb: a TypeBuilder object
9798 * Actually create the MonoClass that is associated with the TypeBuilder.
9801 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
9805 MONO_ARCH_SAVE_REGS
;
9807 klass
= mono_class_from_mono_type (tb
->type
.type
);
9809 mono_loader_lock ();
9810 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) == NULL
) {
9811 MonoReflectionFieldBuilder
*fb
;
9813 MonoType
*enum_basetype
;
9815 g_assert (tb
->fields
!= NULL
);
9816 g_assert (mono_array_length (tb
->fields
) >= 1);
9818 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, 0);
9820 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
))) {
9821 mono_loader_unlock ();
9825 enum_basetype
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
);
9826 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
9827 if (!klass
->element_class
)
9828 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
9831 * get the element_class from the current corlib.
9833 ec
= default_class_from_mono_type (enum_basetype
);
9834 klass
->instance_size
= ec
->instance_size
;
9835 klass
->size_inited
= 1;
9837 * this is almost safe to do with enums and it's needed to be able
9838 * to create objects of the enum type (for use in SetConstant).
9840 /* FIXME: Does this mean enums can't have method overrides ? */
9841 mono_class_setup_vtable_general (klass
, NULL
, 0);
9843 mono_loader_unlock ();
9846 static MonoMarshalSpec
*
9847 mono_marshal_spec_from_builder (MonoImage
*image
, MonoAssembly
*assembly
,
9848 MonoReflectionMarshal
*minfo
)
9850 MonoMarshalSpec
*res
;
9852 res
= image_g_new0 (image
, MonoMarshalSpec
, 1);
9853 res
->native
= minfo
->type
;
9855 switch (minfo
->type
) {
9856 case MONO_NATIVE_LPARRAY
:
9857 res
->data
.array_data
.elem_type
= minfo
->eltype
;
9858 if (minfo
->has_size
) {
9859 res
->data
.array_data
.param_num
= minfo
->param_num
;
9860 res
->data
.array_data
.num_elem
= minfo
->count
;
9861 res
->data
.array_data
.elem_mult
= minfo
->param_num
== -1 ? 0 : 1;
9864 res
->data
.array_data
.param_num
= -1;
9865 res
->data
.array_data
.num_elem
= -1;
9866 res
->data
.array_data
.elem_mult
= -1;
9870 case MONO_NATIVE_BYVALTSTR
:
9871 case MONO_NATIVE_BYVALARRAY
:
9872 res
->data
.array_data
.num_elem
= minfo
->count
;
9875 case MONO_NATIVE_CUSTOM
:
9876 if (minfo
->marshaltyperef
)
9877 res
->data
.custom_data
.custom_name
=
9878 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType
*)minfo
->marshaltyperef
));
9880 res
->data
.custom_data
.cookie
= mono_string_to_utf8 (minfo
->mcookie
);
9889 #endif /* !DISABLE_REFLECTION_EMIT */
9891 MonoReflectionMarshal
*
9892 mono_reflection_marshal_from_marshal_spec (MonoDomain
*domain
, MonoClass
*klass
,
9893 MonoMarshalSpec
*spec
)
9895 static MonoClass
*System_Reflection_Emit_UnmanagedMarshalClass
;
9896 MonoReflectionMarshal
*minfo
;
9899 if (!System_Reflection_Emit_UnmanagedMarshalClass
) {
9900 System_Reflection_Emit_UnmanagedMarshalClass
= mono_class_from_name (
9901 mono_defaults
.corlib
, "System.Reflection.Emit", "UnmanagedMarshal");
9902 g_assert (System_Reflection_Emit_UnmanagedMarshalClass
);
9905 minfo
= (MonoReflectionMarshal
*)mono_object_new (domain
, System_Reflection_Emit_UnmanagedMarshalClass
);
9906 minfo
->type
= spec
->native
;
9908 switch (minfo
->type
) {
9909 case MONO_NATIVE_LPARRAY
:
9910 minfo
->eltype
= spec
->data
.array_data
.elem_type
;
9911 minfo
->count
= spec
->data
.array_data
.num_elem
;
9912 minfo
->param_num
= spec
->data
.array_data
.param_num
;
9915 case MONO_NATIVE_BYVALTSTR
:
9916 case MONO_NATIVE_BYVALARRAY
:
9917 minfo
->count
= spec
->data
.array_data
.num_elem
;
9920 case MONO_NATIVE_CUSTOM
:
9921 if (spec
->data
.custom_data
.custom_name
) {
9922 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, klass
->image
);
9924 MONO_OBJECT_SETREF (minfo
, marshaltyperef
, mono_type_get_object (domain
, mtype
));
9926 MONO_OBJECT_SETREF (minfo
, marshaltype
, mono_string_new (domain
, spec
->data
.custom_data
.custom_name
));
9928 if (spec
->data
.custom_data
.cookie
)
9929 MONO_OBJECT_SETREF (minfo
, mcookie
, mono_string_new (domain
, spec
->data
.custom_data
.cookie
));
9939 #ifndef DISABLE_REFLECTION_EMIT
9941 reflection_methodbuilder_to_mono_method (MonoClass
*klass
,
9942 ReflectionMethodBuilder
*rmb
,
9943 MonoMethodSignature
*sig
)
9947 MonoMethodWrapper
*wrapperm
;
9948 MonoMarshalSpec
**specs
;
9949 MonoReflectionMethodAux
*method_aux
;
9954 mono_error_init (&error
);
9956 * Methods created using a MethodBuilder should have their memory allocated
9957 * inside the image mempool, while dynamic methods should have their memory
9960 dynamic
= rmb
->refs
!= NULL
;
9961 image
= dynamic
? NULL
: klass
->image
;
9964 g_assert (!klass
->generic_class
);
9966 mono_loader_lock ();
9968 if ((rmb
->attrs
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
9969 (rmb
->iattrs
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
))
9970 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodPInvoke
, 1);
9972 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodWrapper
, 1);
9974 wrapperm
= (MonoMethodWrapper
*)m
;
9976 m
->dynamic
= dynamic
;
9978 m
->flags
= rmb
->attrs
;
9979 m
->iflags
= rmb
->iattrs
;
9980 m
->name
= mono_string_to_utf8_image (image
, rmb
->name
, &error
);
9981 g_assert (mono_error_ok (&error
));
9984 m
->sre_method
= TRUE
;
9985 m
->skip_visibility
= rmb
->skip_visibility
;
9987 m
->token
= MONO_TOKEN_METHOD_DEF
| (*rmb
->table_idx
);
9989 if (m
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) {
9990 if (klass
== mono_defaults
.string_class
&& !strcmp (m
->name
, ".ctor"))
9993 m
->signature
->pinvoke
= 1;
9994 } else if (m
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
9995 m
->signature
->pinvoke
= 1;
9997 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9999 method_aux
->dllentry
= rmb
->dllentry
? mono_string_to_utf8_image (image
, rmb
->dllentry
, &error
) : image_strdup (image
, m
->name
);
10000 g_assert (mono_error_ok (&error
));
10001 method_aux
->dll
= mono_string_to_utf8_image (image
, rmb
->dll
, &error
);
10002 g_assert (mono_error_ok (&error
));
10004 ((MonoMethodPInvoke
*)m
)->piflags
= (rmb
->native_cc
<< 8) | (rmb
->charset
? (rmb
->charset
- 1) * 2 : 0) | rmb
->extra_flags
;
10006 if (klass
->image
->dynamic
)
10007 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
10009 mono_loader_unlock ();
10012 } else if (!(m
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) &&
10013 !(m
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
10014 MonoMethodHeader
*header
;
10016 gint32 max_stack
, i
;
10017 gint32 num_locals
= 0;
10018 gint32 num_clauses
= 0;
10022 code
= mono_array_addr (rmb
->ilgen
->code
, guint8
, 0);
10023 code_size
= rmb
->ilgen
->code_len
;
10024 max_stack
= rmb
->ilgen
->max_stack
;
10025 num_locals
= rmb
->ilgen
->locals
? mono_array_length (rmb
->ilgen
->locals
) : 0;
10026 if (rmb
->ilgen
->ex_handlers
)
10027 num_clauses
= method_count_clauses (rmb
->ilgen
);
10030 code
= mono_array_addr (rmb
->code
, guint8
, 0);
10031 code_size
= mono_array_length (rmb
->code
);
10032 /* we probably need to run a verifier on the code... */
10042 header
= image_g_malloc0 (image
, MONO_SIZEOF_METHOD_HEADER
+ num_locals
* sizeof (MonoType
*));
10043 header
->code_size
= code_size
;
10044 header
->code
= image_g_malloc (image
, code_size
);
10045 memcpy ((char*)header
->code
, code
, code_size
);
10046 header
->max_stack
= max_stack
;
10047 header
->init_locals
= rmb
->init_locals
;
10048 header
->num_locals
= num_locals
;
10050 for (i
= 0; i
< num_locals
; ++i
) {
10051 MonoReflectionLocalBuilder
*lb
=
10052 mono_array_get (rmb
->ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
10054 header
->locals
[i
] = image_g_new0 (image
, MonoType
, 1);
10055 memcpy (header
->locals
[i
], mono_reflection_type_get_handle ((MonoReflectionType
*)lb
->type
), MONO_SIZEOF_TYPE
);
10058 header
->num_clauses
= num_clauses
;
10060 header
->clauses
= method_encode_clauses (image
, (MonoDynamicImage
*)klass
->image
,
10061 rmb
->ilgen
, num_clauses
);
10064 wrapperm
->header
= header
;
10067 if (rmb
->generic_params
) {
10068 int count
= mono_array_length (rmb
->generic_params
);
10069 MonoGenericContainer
*container
= rmb
->generic_container
;
10071 g_assert (container
);
10073 container
->type_argc
= count
;
10074 container
->type_params
= image_g_new0 (image
, MonoGenericParamFull
, count
);
10075 container
->owner
.method
= m
;
10077 m
->is_generic
= TRUE
;
10078 mono_method_set_generic_container (m
, container
);
10080 for (i
= 0; i
< count
; i
++) {
10081 MonoReflectionGenericParam
*gp
=
10082 mono_array_get (rmb
->generic_params
, MonoReflectionGenericParam
*, i
);
10083 MonoGenericParamFull
*param
= (MonoGenericParamFull
*) mono_reflection_type_get_handle ((MonoReflectionType
*)gp
)->data
.generic_param
;
10084 container
->type_params
[i
] = *param
;
10087 if (klass
->generic_container
) {
10088 container
->parent
= klass
->generic_container
;
10089 container
->context
.class_inst
= klass
->generic_container
->context
.class_inst
;
10091 container
->context
.method_inst
= mono_get_shared_generic_inst (container
);
10095 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)m
;
10099 m
->wrapper_type
= MONO_WRAPPER_DYNAMIC_METHOD
;
10101 mw
->method_data
= data
= image_g_new (image
, gpointer
, rmb
->nrefs
+ 1);
10102 data
[0] = GUINT_TO_POINTER (rmb
->nrefs
);
10103 for (i
= 0; i
< rmb
->nrefs
; ++i
)
10104 data
[i
+ 1] = rmb
->refs
[i
];
10109 /* Parameter info */
10112 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
10113 method_aux
->param_names
= image_g_new0 (image
, char *, mono_method_signature (m
)->param_count
+ 1);
10114 for (i
= 0; i
<= m
->signature
->param_count
; ++i
) {
10115 MonoReflectionParamBuilder
*pb
;
10116 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
10117 if ((i
> 0) && (pb
->attrs
)) {
10118 /* Make a copy since it might point to a shared type structure */
10119 m
->signature
->params
[i
- 1] = mono_metadata_type_dup (klass
->image
, m
->signature
->params
[i
- 1]);
10120 m
->signature
->params
[i
- 1]->attrs
= pb
->attrs
;
10123 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
10124 MonoDynamicImage
*assembly
;
10125 guint32 idx
, def_type
, len
;
10129 if (!method_aux
->param_defaults
) {
10130 method_aux
->param_defaults
= image_g_new0 (image
, guint8
*, m
->signature
->param_count
+ 1);
10131 method_aux
->param_default_types
= image_g_new0 (image
, guint32
, m
->signature
->param_count
+ 1);
10133 assembly
= (MonoDynamicImage
*)klass
->image
;
10134 idx
= encode_constant (assembly
, pb
->def_value
, &def_type
);
10135 /* Copy the data from the blob since it might get realloc-ed */
10136 p
= assembly
->blob
.data
+ idx
;
10137 len
= mono_metadata_decode_blob_size (p
, &p2
);
10139 method_aux
->param_defaults
[i
] = image_g_malloc (image
, len
);
10140 method_aux
->param_default_types
[i
] = def_type
;
10141 memcpy ((gpointer
)method_aux
->param_defaults
[i
], p
, len
);
10145 method_aux
->param_names
[i
] = mono_string_to_utf8_image (image
, pb
->name
, &error
);
10146 g_assert (mono_error_ok (&error
));
10149 if (!method_aux
->param_cattr
)
10150 method_aux
->param_cattr
= image_g_new0 (image
, MonoCustomAttrInfo
*, m
->signature
->param_count
+ 1);
10151 method_aux
->param_cattr
[i
] = mono_custom_attrs_from_builders (image
, klass
->image
, pb
->cattrs
);
10157 /* Parameter marshalling */
10160 for (i
= 0; i
< mono_array_length (rmb
->pinfo
); ++i
) {
10161 MonoReflectionParamBuilder
*pb
;
10162 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
10163 if (pb
->marshal_info
) {
10165 specs
= image_g_new0 (image
, MonoMarshalSpec
*, sig
->param_count
+ 1);
10166 specs
[pb
->position
] =
10167 mono_marshal_spec_from_builder (image
, klass
->image
->assembly
, pb
->marshal_info
);
10171 if (specs
!= NULL
) {
10173 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
10174 method_aux
->param_marshall
= specs
;
10177 if (klass
->image
->dynamic
&& method_aux
)
10178 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
10180 mono_loader_unlock ();
10186 ctorbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionCtorBuilder
* mb
)
10188 ReflectionMethodBuilder rmb
;
10189 MonoMethodSignature
*sig
;
10191 mono_loader_lock ();
10192 sig
= ctor_builder_to_signature (klass
->image
, mb
);
10193 mono_loader_unlock ();
10195 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
10197 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
10198 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
10200 /* If we are in a generic class, we might be called multiple times from inflate_method */
10201 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
10202 /* ilgen is no longer needed */
10206 return mb
->mhandle
;
10210 methodbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionMethodBuilder
* mb
)
10212 ReflectionMethodBuilder rmb
;
10213 MonoMethodSignature
*sig
;
10215 mono_loader_lock ();
10216 sig
= method_builder_to_signature (klass
->image
, mb
);
10217 mono_loader_unlock ();
10219 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
10221 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
10222 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
10224 /* If we are in a generic class, we might be called multiple times from inflate_method */
10225 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
10226 /* ilgen is no longer needed */
10229 return mb
->mhandle
;
10232 static MonoClassField
*
10233 fieldbuilder_to_mono_class_field (MonoClass
*klass
, MonoReflectionFieldBuilder
* fb
)
10235 MonoClassField
*field
;
10238 field
= g_new0 (MonoClassField
, 1);
10240 field
->name
= mono_string_to_utf8 (fb
->name
);
10241 if (fb
->attrs
|| fb
->modreq
|| fb
->modopt
) {
10242 field
->type
= mono_metadata_type_dup (NULL
, mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
));
10243 field
->type
->attrs
= fb
->attrs
;
10245 g_assert (klass
->image
->dynamic
);
10246 custom
= add_custom_modifiers ((MonoDynamicImage
*)klass
->image
, field
->type
, fb
->modreq
, fb
->modopt
);
10247 g_free (field
->type
);
10248 field
->type
= custom
;
10250 field
->type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
);
10252 if (fb
->offset
!= -1)
10253 field
->offset
= fb
->offset
;
10254 field
->parent
= klass
;
10255 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
10257 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
10264 mono_reflection_bind_generic_parameters (MonoReflectionType
*type
, int type_argc
, MonoType
**types
)
10267 MonoReflectionTypeBuilder
*tb
= NULL
;
10268 gboolean is_dynamic
= FALSE
;
10269 MonoDomain
*domain
;
10270 MonoClass
*geninst
;
10272 mono_loader_lock ();
10274 domain
= mono_object_domain (type
);
10276 if (is_sre_type_builder (mono_object_class (type
))) {
10277 tb
= (MonoReflectionTypeBuilder
*) type
;
10280 } else if (is_sre_generic_instance (mono_object_class (type
))) {
10281 MonoReflectionGenericClass
*rgi
= (MonoReflectionGenericClass
*) type
;
10282 MonoReflectionType
*gtd
= rgi
->generic_type
;
10284 if (is_sre_type_builder (mono_object_class (gtd
))) {
10285 tb
= (MonoReflectionTypeBuilder
*)gtd
;
10290 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
10291 if (tb
&& tb
->generic_container
)
10292 mono_reflection_create_generic_class (tb
);
10294 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle (type
));
10295 if (!klass
->generic_container
) {
10296 mono_loader_unlock ();
10300 if (klass
->wastypebuilder
) {
10301 tb
= (MonoReflectionTypeBuilder
*) mono_class_get_ref_info (klass
);
10306 mono_loader_unlock ();
10308 geninst
= mono_class_bind_generic_parameters (klass
, type_argc
, types
, is_dynamic
);
10310 return &geninst
->byval_arg
;
10314 mono_class_bind_generic_parameters (MonoClass
*klass
, int type_argc
, MonoType
**types
, gboolean is_dynamic
)
10316 MonoGenericClass
*gclass
;
10317 MonoGenericInst
*inst
;
10319 g_assert (klass
->generic_container
);
10321 inst
= mono_metadata_get_generic_inst (type_argc
, types
);
10322 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, is_dynamic
);
10324 return mono_generic_class_get_class (gclass
);
10327 MonoReflectionMethod
*
10328 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod
*rmethod
, MonoArray
*types
)
10331 MonoMethod
*method
, *inflated
;
10332 MonoMethodInflated
*imethod
;
10333 MonoGenericContext tmp_context
;
10334 MonoGenericInst
*ginst
;
10335 MonoType
**type_argv
;
10338 MONO_ARCH_SAVE_REGS
;
10340 /*FIXME but this no longer should happen*/
10341 if (!strcmp (rmethod
->object
.vtable
->klass
->name
, "MethodBuilder")) {
10342 #ifndef DISABLE_REFLECTION_EMIT
10343 MonoReflectionMethodBuilder
*mb
= NULL
;
10344 MonoReflectionTypeBuilder
*tb
;
10347 mb
= (MonoReflectionMethodBuilder
*) rmethod
;
10348 tb
= (MonoReflectionTypeBuilder
*) mb
->type
;
10349 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
));
10351 method
= methodbuilder_to_mono_method (klass
, mb
);
10353 g_assert_not_reached ();
10357 method
= rmethod
->method
;
10360 klass
= method
->klass
;
10362 if (method
->is_inflated
)
10363 method
= ((MonoMethodInflated
*) method
)->declaring
;
10365 count
= mono_method_signature (method
)->generic_param_count
;
10366 if (count
!= mono_array_length (types
))
10369 type_argv
= g_new0 (MonoType
*, count
);
10370 for (i
= 0; i
< count
; i
++) {
10371 MonoReflectionType
*garg
= mono_array_get (types
, gpointer
, i
);
10372 type_argv
[i
] = mono_reflection_type_get_handle (garg
);
10374 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
10375 g_free (type_argv
);
10377 tmp_context
.class_inst
= klass
->generic_class
? klass
->generic_class
->context
.class_inst
: NULL
;
10378 tmp_context
.method_inst
= ginst
;
10380 inflated
= mono_class_inflate_generic_method (method
, &tmp_context
);
10381 imethod
= (MonoMethodInflated
*) inflated
;
10383 /*FIXME but I think this is no longer necessary*/
10384 if (method
->klass
->image
->dynamic
) {
10385 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
10387 * This table maps metadata structures representing inflated methods/fields
10388 * to the reflection objects representing their generic definitions.
10390 mono_loader_lock ();
10391 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, rmethod
);
10392 mono_loader_unlock ();
10395 return mono_method_get_object (mono_object_domain (rmethod
), inflated
, NULL
);
10398 #ifndef DISABLE_REFLECTION_EMIT
10400 static MonoMethod
*
10401 inflate_mono_method (MonoClass
*klass
, MonoMethod
*method
, MonoObject
*obj
)
10403 MonoMethodInflated
*imethod
;
10404 MonoGenericContext
*context
;
10408 * With generic code sharing the klass might not be inflated.
10409 * This can happen because classes inflated with their own
10410 * type arguments are "normalized" to the uninflated class.
10412 if (!klass
->generic_class
)
10415 context
= mono_class_get_context (klass
);
10417 if (klass
->method
.count
) {
10418 /* Find the already created inflated method */
10419 for (i
= 0; i
< klass
->method
.count
; ++i
) {
10420 g_assert (klass
->methods
[i
]->is_inflated
);
10421 if (((MonoMethodInflated
*)klass
->methods
[i
])->declaring
== method
)
10424 g_assert (i
< klass
->method
.count
);
10425 imethod
= (MonoMethodInflated
*)klass
->methods
[i
];
10427 imethod
= (MonoMethodInflated
*) mono_class_inflate_generic_method_full (method
, klass
, context
);
10430 if (method
->is_generic
&& method
->klass
->image
->dynamic
) {
10431 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
10433 mono_loader_lock ();
10434 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, obj
);
10435 mono_loader_unlock ();
10437 return (MonoMethod
*) imethod
;
10440 static MonoMethod
*
10441 inflate_method (MonoReflectionType
*type
, MonoObject
*obj
)
10443 MonoMethod
*method
;
10446 MonoClass
*type_class
= mono_object_class (type
);
10448 if (is_sre_generic_instance (type_class
)) {
10449 MonoReflectionGenericClass
*mgc
= (MonoReflectionGenericClass
*)type
;
10450 gklass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)mgc
->generic_type
));
10451 } else if (is_sre_type_builder (type_class
)) {
10452 gklass
= mono_class_from_mono_type (mono_reflection_type_get_handle (type
));
10453 } else if (type
->type
) {
10454 gklass
= mono_class_from_mono_type (type
->type
);
10455 gklass
= mono_class_get_generic_type_definition (gklass
);
10457 g_error ("Can't handle type %s", mono_type_get_full_name (mono_object_class (type
)));
10460 if (!strcmp (obj
->vtable
->klass
->name
, "MethodBuilder"))
10461 if (((MonoReflectionMethodBuilder
*)obj
)->mhandle
)
10462 method
= ((MonoReflectionMethodBuilder
*)obj
)->mhandle
;
10464 method
= methodbuilder_to_mono_method (gklass
, (MonoReflectionMethodBuilder
*) obj
);
10465 else if (!strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder"))
10466 method
= ctorbuilder_to_mono_method (gklass
, (MonoReflectionCtorBuilder
*) obj
);
10467 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoMethod") || !strcmp (obj
->vtable
->klass
->name
, "MonoCMethod"))
10468 method
= ((MonoReflectionMethod
*) obj
)->method
;
10470 method
= NULL
; /* prevent compiler warning */
10471 g_error ("can't handle type %s", obj
->vtable
->klass
->name
);
10474 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)type
)), method
, obj
);
10477 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
10479 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
10480 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
10483 MonoGenericClass
*gclass
;
10484 MonoDynamicGenericClass
*dgclass
;
10485 MonoClass
*klass
, *gklass
;
10489 MONO_ARCH_SAVE_REGS
;
10491 gtype
= mono_reflection_type_get_handle ((MonoReflectionType
*)type
);
10492 klass
= mono_class_from_mono_type (gtype
);
10493 g_assert (gtype
->type
== MONO_TYPE_GENERICINST
);
10494 gclass
= gtype
->data
.generic_class
;
10496 if (!gclass
->is_dynamic
)
10499 dgclass
= (MonoDynamicGenericClass
*) gclass
;
10501 if (dgclass
->initialized
)
10504 gklass
= gclass
->container_class
;
10505 mono_class_init (gklass
);
10507 dgclass
->count_methods
= methods
? mono_array_length (methods
) : 0;
10508 dgclass
->count_ctors
= ctors
? mono_array_length (ctors
) : 0;
10509 dgclass
->count_fields
= fields
? mono_array_length (fields
) : 0;
10511 dgclass
->methods
= g_new0 (MonoMethod
*, dgclass
->count_methods
);
10512 dgclass
->ctors
= g_new0 (MonoMethod
*, dgclass
->count_ctors
);
10513 dgclass
->fields
= g_new0 (MonoClassField
, dgclass
->count_fields
);
10514 dgclass
->field_objects
= g_new0 (MonoObject
*, dgclass
->count_fields
);
10515 dgclass
->field_generic_types
= g_new0 (MonoType
*, dgclass
->count_fields
);
10517 for (i
= 0; i
< dgclass
->count_methods
; i
++) {
10518 MonoObject
*obj
= mono_array_get (methods
, gpointer
, i
);
10520 dgclass
->methods
[i
] = inflate_method ((MonoReflectionType
*)type
, obj
);
10523 for (i
= 0; i
< dgclass
->count_ctors
; i
++) {
10524 MonoObject
*obj
= mono_array_get (ctors
, gpointer
, i
);
10526 dgclass
->ctors
[i
] = inflate_method ((MonoReflectionType
*)type
, obj
);
10529 for (i
= 0; i
< dgclass
->count_fields
; i
++) {
10530 MonoObject
*obj
= mono_array_get (fields
, gpointer
, i
);
10531 MonoClassField
*field
, *inflated_field
= NULL
;
10533 if (!strcmp (obj
->vtable
->klass
->name
, "FieldBuilder"))
10534 inflated_field
= field
= fieldbuilder_to_mono_class_field (klass
, (MonoReflectionFieldBuilder
*) obj
);
10535 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoField"))
10536 field
= ((MonoReflectionField
*) obj
)->field
;
10538 field
= NULL
; /* prevent compiler warning */
10539 g_assert_not_reached ();
10542 dgclass
->fields
[i
] = *field
;
10543 dgclass
->fields
[i
].parent
= klass
;
10544 dgclass
->fields
[i
].type
= mono_class_inflate_generic_type (
10545 field
->type
, mono_generic_class_get_context ((MonoGenericClass
*) dgclass
));
10546 dgclass
->field_generic_types
[i
] = field
->type
;
10547 MOVING_GC_REGISTER (&dgclass
->field_objects
[i
]);
10548 dgclass
->field_objects
[i
] = obj
;
10550 if (inflated_field
) {
10551 g_free (inflated_field
);
10553 dgclass
->fields
[i
].name
= g_strdup (dgclass
->fields
[i
].name
);
10557 dgclass
->initialized
= TRUE
;
10561 fix_partial_generic_class (MonoClass
*klass
)
10563 MonoClass
*gklass
= klass
->generic_class
->container_class
;
10564 MonoDynamicGenericClass
*dgclass
;
10567 if (klass
->wastypebuilder
)
10570 dgclass
= (MonoDynamicGenericClass
*) klass
->generic_class
;
10572 if (!dgclass
->initialized
)
10575 if (klass
->method
.count
!= gklass
->method
.count
) {
10576 klass
->method
.count
= gklass
->method
.count
;
10577 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * (klass
->method
.count
+ 1));
10579 for (i
= 0; i
< klass
->method
.count
; i
++) {
10580 klass
->methods
[i
] = mono_class_inflate_generic_method_full (
10581 gklass
->methods
[i
], klass
, mono_class_get_context (klass
));
10585 if (klass
->interface_count
&& klass
->interface_count
!= gklass
->interface_count
) {
10586 klass
->interface_count
= gklass
->interface_count
;
10587 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * gklass
->interface_count
);
10588 klass
->interfaces_packed
= NULL
; /*make setup_interface_offsets happy*/
10590 for (i
= 0; i
< gklass
->interface_count
; ++i
) {
10591 MonoType
*iface_type
= mono_class_inflate_generic_type (&gklass
->interfaces
[i
]->byval_arg
, mono_class_get_context (klass
));
10592 klass
->interfaces
[i
] = mono_class_from_mono_type (iface_type
);
10593 mono_metadata_free_type (iface_type
);
10595 ensure_runtime_vtable (klass
->interfaces
[i
]);
10597 klass
->interfaces_inited
= 1;
10600 if (klass
->field
.count
!= gklass
->field
.count
) {
10601 klass
->field
.count
= gklass
->field
.count
;
10602 klass
->fields
= image_g_new0 (klass
->image
, MonoClassField
, klass
->field
.count
);
10604 for (i
= 0; i
< klass
->field
.count
; i
++) {
10605 klass
->fields
[i
] = gklass
->fields
[i
];
10606 klass
->fields
[i
].parent
= klass
;
10607 klass
->fields
[i
].type
= mono_class_inflate_generic_type (gklass
->fields
[i
].type
, mono_class_get_context (klass
));
10611 /*We can only finish with this klass once it's parent has as well*/
10612 if (gklass
->wastypebuilder
)
10613 klass
->wastypebuilder
= TRUE
;
10618 ensure_generic_class_runtime_vtable (MonoClass
*klass
)
10620 MonoClass
*gklass
= klass
->generic_class
->container_class
;
10622 ensure_runtime_vtable (gklass
);
10624 fix_partial_generic_class (klass
);
10628 ensure_runtime_vtable (MonoClass
*klass
)
10630 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info (klass
);
10633 if (!klass
->image
->dynamic
|| (!tb
&& !klass
->generic_class
) || klass
->wastypebuilder
)
10636 ensure_runtime_vtable (klass
->parent
);
10639 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
10640 num
+= tb
->num_methods
;
10641 klass
->method
.count
= num
;
10642 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * num
);
10643 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
10644 for (i
= 0; i
< num
; ++i
)
10645 klass
->methods
[i
] = ctorbuilder_to_mono_method (klass
, mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
));
10646 num
= tb
->num_methods
;
10648 for (i
= 0; i
< num
; ++i
)
10649 klass
->methods
[j
++] = methodbuilder_to_mono_method (klass
, mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
));
10651 if (tb
->interfaces
) {
10652 klass
->interface_count
= mono_array_length (tb
->interfaces
);
10653 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
10654 for (i
= 0; i
< klass
->interface_count
; ++i
) {
10655 MonoType
*iface
= mono_type_array_get_and_resolve (tb
->interfaces
, i
);
10656 klass
->interfaces
[i
] = mono_class_from_mono_type (iface
);
10657 ensure_runtime_vtable (klass
->interfaces
[i
]);
10659 klass
->interfaces_inited
= 1;
10661 } else if (klass
->generic_class
){
10662 ensure_generic_class_runtime_vtable (klass
);
10665 if (klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
10666 for (i
= 0; i
< klass
->method
.count
; ++i
)
10667 klass
->methods
[i
]->slot
= i
;
10669 klass
->interfaces_packed
= NULL
; /*make setup_interface_offsets happy*/
10670 mono_class_setup_interface_offsets (klass
);
10671 mono_class_setup_interface_id (klass
);
10675 * The generic vtable is needed even if image->run is not set since some
10676 * runtime code like ves_icall_Type_GetMethodsByName depends on
10677 * method->slot being defined.
10681 * tb->methods could not be freed since it is used for determining
10682 * overrides during dynamic vtable construction.
10687 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
10689 MonoReflectionTypeBuilder
*tb
;
10693 *num_overrides
= 0;
10695 g_assert (klass
->image
->dynamic
);
10697 if (!mono_class_get_ref_info (klass
))
10700 g_assert (strcmp (((MonoObject
*)mono_class_get_ref_info (klass
))->vtable
->klass
->name
, "TypeBuilder") == 0);
10702 tb
= (MonoReflectionTypeBuilder
*)mono_class_get_ref_info (klass
);
10706 for (i
= 0; i
< tb
->num_methods
; ++i
) {
10707 MonoReflectionMethodBuilder
*mb
=
10708 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
10709 if (mb
->override_method
)
10715 *overrides
= g_new0 (MonoMethod
*, onum
* 2);
10718 for (i
= 0; i
< tb
->num_methods
; ++i
) {
10719 MonoReflectionMethodBuilder
*mb
=
10720 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
10721 if (mb
->override_method
) {
10722 (*overrides
) [onum
* 2] =
10723 mb
->override_method
->method
;
10724 (*overrides
) [onum
* 2 + 1] =
10727 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10728 g_assert (mb
->override_method
->method
);
10729 g_assert (mb
->mhandle
);
10736 *num_overrides
= onum
;
10740 typebuilder_setup_fields (MonoClass
*klass
, MonoError
*error
)
10742 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info (klass
);
10743 MonoReflectionFieldBuilder
*fb
;
10744 MonoClassField
*field
;
10745 MonoImage
*image
= klass
->image
;
10746 const char *p
, *p2
;
10748 guint32 len
, idx
, real_size
= 0;
10750 klass
->field
.count
= tb
->num_fields
;
10751 klass
->field
.first
= 0;
10753 mono_error_init (error
);
10755 if (tb
->class_size
) {
10756 g_assert ((tb
->packing_size
& 0xfffffff0) == 0);
10757 klass
->packing_size
= tb
->packing_size
;
10758 real_size
= klass
->instance_size
+ tb
->class_size
;
10761 if (!klass
->field
.count
) {
10762 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10766 klass
->fields
= image_g_new0 (image
, MonoClassField
, klass
->field
.count
);
10767 mono_class_alloc_ext (klass
);
10768 klass
->ext
->field_def_values
= image_g_new0 (image
, MonoFieldDefaultValue
, klass
->field
.count
);
10770 This is, guess what, a hack.
10771 The issue is that the runtime doesn't know how to setup the fields of a typebuider and crash.
10772 On the static path no field class is resolved, only types are built. This is the right thing to do
10774 Setting size_inited is harmless because we're doing the same job as mono_class_setup_fields anyway.
10776 klass
->size_inited
= 1;
10778 for (i
= 0; i
< klass
->field
.count
; ++i
) {
10779 fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10780 field
= &klass
->fields
[i
];
10781 field
->name
= mono_string_to_utf8_image (image
, fb
->name
, error
);
10782 if (!mono_error_ok (error
))
10785 field
->type
= mono_metadata_type_dup (klass
->image
, mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
));
10786 field
->type
->attrs
= fb
->attrs
;
10788 field
->type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
);
10790 if ((fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) && fb
->rva_data
)
10791 klass
->ext
->field_def_values
[i
].data
= mono_array_addr (fb
->rva_data
, char, 0);
10792 if (fb
->offset
!= -1)
10793 field
->offset
= fb
->offset
;
10794 field
->parent
= klass
;
10795 fb
->handle
= field
;
10796 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
10798 if (fb
->def_value
) {
10799 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)klass
->image
;
10800 field
->type
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
10801 idx
= encode_constant (assembly
, fb
->def_value
, &klass
->ext
->field_def_values
[i
].def_type
);
10802 /* Copy the data from the blob since it might get realloc-ed */
10803 p
= assembly
->blob
.data
+ idx
;
10804 len
= mono_metadata_decode_blob_size (p
, &p2
);
10806 klass
->ext
->field_def_values
[i
].data
= mono_image_alloc (image
, len
);
10807 memcpy ((gpointer
)klass
->ext
->field_def_values
[i
].data
, p
, len
);
10811 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10812 mono_class_layout_fields (klass
);
10816 typebuilder_setup_properties (MonoClass
*klass
, MonoError
*error
)
10818 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info (klass
);
10819 MonoReflectionPropertyBuilder
*pb
;
10820 MonoImage
*image
= klass
->image
;
10821 MonoProperty
*properties
;
10824 mono_error_init (error
);
10827 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
10829 klass
->ext
->property
.count
= tb
->properties
? mono_array_length (tb
->properties
) : 0;
10830 klass
->ext
->property
.first
= 0;
10832 properties
= image_g_new0 (image
, MonoProperty
, klass
->ext
->property
.count
);
10833 klass
->ext
->properties
= properties
;
10834 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
10835 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
10836 properties
[i
].parent
= klass
;
10837 properties
[i
].attrs
= pb
->attrs
;
10838 properties
[i
].name
= mono_string_to_utf8_image (image
, pb
->name
, error
);
10839 if (!mono_error_ok (error
))
10841 if (pb
->get_method
)
10842 properties
[i
].get
= pb
->get_method
->mhandle
;
10843 if (pb
->set_method
)
10844 properties
[i
].set
= pb
->set_method
->mhandle
;
10846 mono_save_custom_attrs (klass
->image
, &properties
[i
], pb
->cattrs
);
10850 MonoReflectionEvent
*
10851 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
10853 MonoEvent
*event
= g_new0 (MonoEvent
, 1);
10856 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
));
10858 event
->parent
= klass
;
10859 event
->attrs
= eb
->attrs
;
10860 event
->name
= mono_string_to_utf8 (eb
->name
);
10861 if (eb
->add_method
)
10862 event
->add
= eb
->add_method
->mhandle
;
10863 if (eb
->remove_method
)
10864 event
->remove
= eb
->remove_method
->mhandle
;
10865 if (eb
->raise_method
)
10866 event
->raise
= eb
->raise_method
->mhandle
;
10868 #ifndef MONO_SMALL_CONFIG
10869 if (eb
->other_methods
) {
10871 event
->other
= g_new0 (MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10872 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10873 MonoReflectionMethodBuilder
*mb
=
10874 mono_array_get (eb
->other_methods
,
10875 MonoReflectionMethodBuilder
*, j
);
10876 event
->other
[j
] = mb
->mhandle
;
10881 return mono_event_get_object (mono_object_domain (tb
), klass
, event
);
10885 typebuilder_setup_events (MonoClass
*klass
, MonoError
*error
)
10887 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info (klass
);
10888 MonoReflectionEventBuilder
*eb
;
10889 MonoImage
*image
= klass
->image
;
10893 mono_error_init (error
);
10896 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
10898 klass
->ext
->event
.count
= tb
->events
? mono_array_length (tb
->events
) : 0;
10899 klass
->ext
->event
.first
= 0;
10901 events
= image_g_new0 (image
, MonoEvent
, klass
->ext
->event
.count
);
10902 klass
->ext
->events
= events
;
10903 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
10904 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
10905 events
[i
].parent
= klass
;
10906 events
[i
].attrs
= eb
->attrs
;
10907 events
[i
].name
= mono_string_to_utf8_image (image
, eb
->name
, error
);
10908 if (!mono_error_ok (error
))
10910 if (eb
->add_method
)
10911 events
[i
].add
= eb
->add_method
->mhandle
;
10912 if (eb
->remove_method
)
10913 events
[i
].remove
= eb
->remove_method
->mhandle
;
10914 if (eb
->raise_method
)
10915 events
[i
].raise
= eb
->raise_method
->mhandle
;
10917 #ifndef MONO_SMALL_CONFIG
10918 if (eb
->other_methods
) {
10920 events
[i
].other
= image_g_new0 (image
, MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10921 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10922 MonoReflectionMethodBuilder
*mb
=
10923 mono_array_get (eb
->other_methods
,
10924 MonoReflectionMethodBuilder
*, j
);
10925 events
[i
].other
[j
] = mb
->mhandle
;
10929 mono_save_custom_attrs (klass
->image
, &events
[i
], eb
->cattrs
);
10934 remove_instantiations_of_and_ensure_contents (gpointer key
,
10936 gpointer user_data
)
10938 MonoType
*type
= (MonoType
*)key
;
10939 MonoClass
*klass
= (MonoClass
*)user_data
;
10941 if ((type
->type
== MONO_TYPE_GENERICINST
) && (type
->data
.generic_class
->container_class
== klass
)) {
10942 fix_partial_generic_class (mono_class_from_mono_type (type
)); //Ensure it's safe to use it.
10949 check_array_for_usertypes (MonoArray
*arr
)
10956 for (i
= 0; i
< mono_array_length (arr
); ++i
)
10957 RESOLVE_ARRAY_TYPE_ELEMENT (arr
, i
);
10960 MonoReflectionType
*
10961 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
10965 MonoDomain
* domain
;
10966 MonoReflectionType
* res
;
10969 MONO_ARCH_SAVE_REGS
;
10971 domain
= mono_object_domain (tb
);
10972 klass
= mono_class_from_mono_type (tb
->type
.type
);
10975 * Check for user defined Type subclasses.
10977 RESOLVE_TYPE (tb
->parent
);
10978 check_array_for_usertypes (tb
->interfaces
);
10980 for (i
= 0; i
< mono_array_length (tb
->fields
); ++i
) {
10981 MonoReflectionFieldBuilder
*fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10983 RESOLVE_TYPE (fb
->type
);
10984 check_array_for_usertypes (fb
->modreq
);
10985 check_array_for_usertypes (fb
->modopt
);
10986 if (fb
->marshal_info
&& fb
->marshal_info
->marshaltyperef
)
10987 RESOLVE_TYPE (fb
->marshal_info
->marshaltyperef
);
10992 for (i
= 0; i
< mono_array_length (tb
->methods
); ++i
) {
10993 MonoReflectionMethodBuilder
*mb
= mono_array_get (tb
->methods
, gpointer
, i
);
10995 RESOLVE_TYPE (mb
->rtype
);
10996 check_array_for_usertypes (mb
->return_modreq
);
10997 check_array_for_usertypes (mb
->return_modopt
);
10998 check_array_for_usertypes (mb
->parameters
);
10999 if (mb
->param_modreq
)
11000 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
)
11001 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
));
11002 if (mb
->param_modopt
)
11003 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
)
11004 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
));
11009 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
11010 MonoReflectionCtorBuilder
*mb
= mono_array_get (tb
->ctors
, gpointer
, i
);
11012 check_array_for_usertypes (mb
->parameters
);
11013 if (mb
->param_modreq
)
11014 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
)
11015 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
));
11016 if (mb
->param_modopt
)
11017 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
)
11018 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
));
11023 mono_save_custom_attrs (klass
->image
, klass
, tb
->cattrs
);
11026 * we need to lock the domain because the lock will be taken inside
11027 * So, we need to keep the locking order correct.
11029 mono_loader_lock ();
11030 mono_domain_lock (domain
);
11031 if (klass
->wastypebuilder
) {
11032 mono_domain_unlock (domain
);
11033 mono_loader_unlock ();
11034 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
11037 * Fields to set in klass:
11038 * the various flags: delegate/unicode/contextbound etc.
11040 klass
->flags
= tb
->attrs
;
11041 klass
->has_cctor
= 1;
11042 klass
->has_finalize
= 1;
11045 if (!((MonoDynamicImage
*)klass
->image
)->run
) {
11046 if (klass
->generic_container
) {
11047 /* FIXME: The code below can't handle generic classes */
11048 klass
->wastypebuilder
= TRUE
;
11049 mono_loader_unlock ();
11050 mono_domain_unlock (domain
);
11051 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
11056 /* enums are done right away */
11057 if (!klass
->enumtype
)
11058 ensure_runtime_vtable (klass
);
11060 if (tb
->subtypes
) {
11061 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
11062 MonoReflectionTypeBuilder
*subtb
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
11063 mono_class_alloc_ext (klass
);
11064 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
)));
11068 klass
->nested_classes_inited
= TRUE
;
11070 /* fields and object layout */
11071 if (klass
->parent
) {
11072 if (!klass
->parent
->size_inited
)
11073 mono_class_init (klass
->parent
);
11074 klass
->instance_size
= klass
->parent
->instance_size
;
11075 klass
->sizes
.class_size
= 0;
11076 klass
->min_align
= klass
->parent
->min_align
;
11077 /* if the type has no fields we won't call the field_setup
11078 * routine which sets up klass->has_references.
11080 klass
->has_references
|= klass
->parent
->has_references
;
11082 klass
->instance_size
= sizeof (MonoObject
);
11083 klass
->min_align
= 1;
11086 /* FIXME: handle packing_size and instance_size */
11087 typebuilder_setup_fields (klass
, &error
);
11088 if (!mono_error_ok (&error
))
11090 typebuilder_setup_properties (klass
, &error
);
11091 if (!mono_error_ok (&error
))
11094 typebuilder_setup_events (klass
, &error
);
11095 if (!mono_error_ok (&error
))
11098 klass
->wastypebuilder
= TRUE
;
11101 * If we are a generic TypeBuilder, there might be instantiations in the type cache
11102 * which have type System.Reflection.MonoGenericClass, but after the type is created,
11103 * we want to return normal System.MonoType objects, so clear these out from the cache.
11105 * Together with this we must ensure the contents of all instances to match the created type.
11107 if (domain
->type_hash
&& klass
->generic_container
)
11108 mono_g_hash_table_foreach_remove (domain
->type_hash
, remove_instantiations_of_and_ensure_contents
, klass
);
11110 mono_domain_unlock (domain
);
11111 mono_loader_unlock ();
11113 if (klass
->enumtype
&& !mono_class_is_valid_enum (klass
)) {
11114 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
11115 mono_raise_exception (mono_get_exception_type_load (tb
->name
, NULL
));
11118 res
= mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
11119 g_assert (res
!= (MonoReflectionType
*)tb
);
11124 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
11125 klass
->wastypebuilder
= TRUE
;
11126 mono_domain_unlock (domain
);
11127 mono_loader_unlock ();
11128 mono_error_raise_exception (&error
);
11133 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
11135 MonoGenericParamFull
*param
;
11139 MONO_ARCH_SAVE_REGS
;
11141 param
= g_new0 (MonoGenericParamFull
, 1);
11143 if (gparam
->mbuilder
) {
11144 if (!gparam
->mbuilder
->generic_container
) {
11145 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)gparam
->mbuilder
->type
;
11146 MonoClass
*klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
));
11147 gparam
->mbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
11148 gparam
->mbuilder
->generic_container
->is_method
= TRUE
;
11150 * Cannot set owner.method, since the MonoMethod is not created yet.
11151 * Set the image field instead, so type_in_image () works.
11153 gparam
->mbuilder
->generic_container
->image
= klass
->image
;
11155 param
->param
.owner
= gparam
->mbuilder
->generic_container
;
11156 } else if (gparam
->tbuilder
) {
11157 if (!gparam
->tbuilder
->generic_container
) {
11158 MonoClass
*klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
->tbuilder
));
11159 gparam
->tbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
11160 gparam
->tbuilder
->generic_container
->owner
.klass
= klass
;
11162 param
->param
.owner
= gparam
->tbuilder
->generic_container
;
11165 param
->info
.name
= mono_string_to_utf8 (gparam
->name
);
11166 param
->param
.num
= gparam
->index
;
11168 image
= &gparam
->tbuilder
->module
->dynamic_image
->image
;
11169 pklass
= mono_class_from_generic_parameter ((MonoGenericParam
*) param
, image
, gparam
->mbuilder
!= NULL
);
11171 gparam
->type
.type
= &pklass
->byval_arg
;
11173 mono_class_set_ref_info (pklass
, gparam
);
11174 mono_image_lock (image
);
11175 image
->reflection_info_unregister_classes
= g_slist_prepend (image
->reflection_info_unregister_classes
, pklass
);
11176 mono_image_unlock (image
);
11180 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
11182 MonoReflectionModuleBuilder
*module
= sig
->module
;
11183 MonoDynamicImage
*assembly
= module
!= NULL
? module
->dynamic_image
: NULL
;
11184 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
11189 check_array_for_usertypes (sig
->arguments
);
11191 sigbuffer_init (&buf
, 32);
11193 sigbuffer_add_value (&buf
, 0x07);
11194 sigbuffer_add_value (&buf
, na
);
11195 if (assembly
!= NULL
){
11196 for (i
= 0; i
< na
; ++i
) {
11197 MonoReflectionType
*type
= mono_array_get (sig
->arguments
, MonoReflectionType
*, i
);
11198 encode_reflection_type (assembly
, type
, &buf
);
11202 buflen
= buf
.p
- buf
.buf
;
11203 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
11204 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
11205 sigbuffer_free (&buf
);
11211 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
11213 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
11214 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
11219 check_array_for_usertypes (sig
->arguments
);
11221 sigbuffer_init (&buf
, 32);
11223 sigbuffer_add_value (&buf
, 0x06);
11224 for (i
= 0; i
< na
; ++i
) {
11225 MonoReflectionType
*type
= mono_array_get (sig
->arguments
, MonoReflectionType
*, i
);
11226 encode_reflection_type (assembly
, type
, &buf
);
11229 buflen
= buf
.p
- buf
.buf
;
11230 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
11231 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
11232 sigbuffer_free (&buf
);
11238 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
11240 ReflectionMethodBuilder rmb
;
11241 MonoMethodSignature
*sig
;
11246 sig
= dynamic_method_to_signature (mb
);
11248 reflection_methodbuilder_from_dynamic_method (&rmb
, mb
);
11251 * Resolve references.
11254 * Every second entry in the refs array is reserved for storing handle_class,
11255 * which is needed by the ldtoken implementation in the JIT.
11257 rmb
.nrefs
= mb
->nrefs
;
11258 rmb
.refs
= g_new0 (gpointer
, mb
->nrefs
+ 1);
11259 for (i
= 0; i
< mb
->nrefs
; i
+= 2) {
11260 MonoClass
*handle_class
;
11262 MonoObject
*obj
= mono_array_get (mb
->refs
, MonoObject
*, i
);
11264 if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
11265 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
11267 * The referenced DynamicMethod should already be created by the managed
11268 * code, except in the case of circular references. In that case, we store
11269 * method in the refs array, and fix it up later when the referenced
11270 * DynamicMethod is created.
11272 if (method
->mhandle
) {
11273 ref
= method
->mhandle
;
11275 /* FIXME: GC object stored in unmanaged memory */
11278 /* FIXME: GC object stored in unmanaged memory */
11279 method
->referenced_by
= g_slist_append (method
->referenced_by
, mb
);
11281 handle_class
= mono_defaults
.methodhandle_class
;
11283 MonoException
*ex
= NULL
;
11284 ref
= resolve_object (mb
->module
->image
, obj
, &handle_class
, NULL
);
11286 ex
= mono_get_exception_type_load (NULL
, NULL
);
11287 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
11288 ex
= mono_security_core_clr_ensure_dynamic_method_resolved_object (ref
, handle_class
);
11292 mono_raise_exception (ex
);
11297 rmb
.refs
[i
] = ref
; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
11298 rmb
.refs
[i
+ 1] = handle_class
;
11301 klass
= mb
->owner
? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)mb
->owner
)) : mono_defaults
.object_class
;
11303 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
11305 /* Fix up refs entries pointing at us */
11306 for (l
= mb
->referenced_by
; l
; l
= l
->next
) {
11307 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)l
->data
;
11308 MonoMethodWrapper
*wrapper
= (MonoMethodWrapper
*)method
->mhandle
;
11311 g_assert (method
->mhandle
);
11313 data
= (gpointer
*)wrapper
->method_data
;
11314 for (i
= 0; i
< GPOINTER_TO_UINT (data
[0]); i
+= 2) {
11315 if ((data
[i
+ 1] == mb
) && (data
[i
+ 1 + 1] == mono_defaults
.methodhandle_class
))
11316 data
[i
+ 1] = mb
->mhandle
;
11319 g_slist_free (mb
->referenced_by
);
11323 /* ilgen is no longer needed */
11327 #endif /* DISABLE_REFLECTION_EMIT */
11330 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod
*mb
)
11335 mono_runtime_free_method (
11336 mono_object_get_domain ((MonoObject
*)mb
), mb
->mhandle
);
11341 * mono_reflection_is_valid_dynamic_token:
11343 * Returns TRUE if token is valid.
11347 mono_reflection_is_valid_dynamic_token (MonoDynamicImage
*image
, guint32 token
)
11349 return mono_g_hash_table_lookup (image
->tokens
, GUINT_TO_POINTER (token
)) != NULL
;
11352 #ifndef DISABLE_REFLECTION_EMIT
11355 * mono_reflection_lookup_dynamic_token:
11357 * Finish the Builder object pointed to by TOKEN and return the corresponding
11358 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
11359 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
11362 * LOCKING: Take the loader lock
11365 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
11367 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)image
;
11371 mono_loader_lock ();
11372 obj
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
11373 mono_loader_unlock ();
11376 g_error ("Could not find required dynamic token 0x%08x", token
);
11382 handle_class
= &klass
;
11383 return resolve_object (image
, obj
, handle_class
, context
);
11387 * ensure_complete_type:
11389 * Ensure that KLASS is completed if it is a dynamic type, or references
11393 ensure_complete_type (MonoClass
*klass
)
11395 if (klass
->image
->dynamic
&& !klass
->wastypebuilder
&& mono_class_get_ref_info (klass
)) {
11396 MonoReflectionTypeBuilder
*tb
= mono_class_get_ref_info (klass
);
11398 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
11400 // Asserting here could break a lot of code
11401 //g_assert (klass->wastypebuilder);
11404 if (klass
->generic_class
) {
11405 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
11408 for (i
= 0; i
< inst
->type_argc
; ++i
) {
11409 ensure_complete_type (mono_class_from_mono_type (inst
->type_argv
[i
]));
11415 resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
)
11417 gpointer result
= NULL
;
11419 if (strcmp (obj
->vtable
->klass
->name
, "String") == 0) {
11420 result
= mono_string_intern ((MonoString
*)obj
);
11421 *handle_class
= mono_defaults
.string_class
;
11423 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoType") == 0) {
11424 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
11426 MonoType
*inflated
= mono_class_inflate_generic_type (type
, context
);
11427 result
= mono_class_from_mono_type (inflated
);
11428 mono_metadata_free_type (inflated
);
11430 result
= mono_class_from_mono_type (type
);
11432 *handle_class
= mono_defaults
.typehandle_class
;
11434 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoMethod") == 0 ||
11435 strcmp (obj
->vtable
->klass
->name
, "MonoCMethod") == 0 ||
11436 strcmp (obj
->vtable
->klass
->name
, "MonoGenericCMethod") == 0 ||
11437 strcmp (obj
->vtable
->klass
->name
, "MonoGenericMethod") == 0) {
11438 result
= ((MonoReflectionMethod
*)obj
)->method
;
11440 result
= mono_class_inflate_generic_method (result
, context
);
11441 *handle_class
= mono_defaults
.methodhandle_class
;
11443 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodBuilder") == 0) {
11444 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
11445 result
= mb
->mhandle
;
11447 /* Type is not yet created */
11448 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
11450 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
11453 * Hopefully this has been filled in by calling CreateType() on the
11457 * TODO: This won't work if the application finishes another
11458 * TypeBuilder instance instead of this one.
11460 result
= mb
->mhandle
;
11463 result
= mono_class_inflate_generic_method (result
, context
);
11464 *handle_class
= mono_defaults
.methodhandle_class
;
11465 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder") == 0) {
11466 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
11468 result
= cb
->mhandle
;
11470 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)cb
->type
;
11472 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
11473 result
= cb
->mhandle
;
11476 result
= mono_class_inflate_generic_method (result
, context
);
11477 *handle_class
= mono_defaults
.methodhandle_class
;
11478 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoField") == 0) {
11479 MonoClassField
*field
= ((MonoReflectionField
*)obj
)->field
;
11481 ensure_complete_type (field
->parent
);
11483 MonoType
*inflated
= mono_class_inflate_generic_type (&field
->parent
->byval_arg
, context
);
11484 MonoClass
*class = mono_class_from_mono_type (inflated
);
11485 MonoClassField
*inflated_field
;
11486 gpointer iter
= NULL
;
11487 mono_metadata_free_type (inflated
);
11488 while ((inflated_field
= mono_class_get_fields (class, &iter
))) {
11489 if (!strcmp (field
->name
, inflated_field
->name
))
11492 g_assert (inflated_field
&& !strcmp (field
->name
, inflated_field
->name
));
11493 result
= inflated_field
;
11497 *handle_class
= mono_defaults
.fieldhandle_class
;
11499 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldBuilder") == 0) {
11500 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
11501 result
= fb
->handle
;
11504 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
11506 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
11507 result
= fb
->handle
;
11510 if (fb
->handle
&& fb
->handle
->parent
->generic_container
) {
11511 MonoClass
*klass
= fb
->handle
->parent
;
11512 MonoType
*type
= mono_class_inflate_generic_type (&klass
->byval_arg
, context
);
11513 MonoClass
*inflated
= mono_class_from_mono_type (type
);
11515 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (fb
->handle
));
11517 mono_metadata_free_type (type
);
11519 *handle_class
= mono_defaults
.fieldhandle_class
;
11520 } else if (strcmp (obj
->vtable
->klass
->name
, "TypeBuilder") == 0) {
11521 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
11522 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
);
11525 klass
= type
->data
.klass
;
11526 if (klass
->wastypebuilder
) {
11527 /* Already created */
11531 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
11532 result
= type
->data
.klass
;
11535 *handle_class
= mono_defaults
.typehandle_class
;
11536 } else if (strcmp (obj
->vtable
->klass
->name
, "SignatureHelper") == 0) {
11537 MonoReflectionSigHelper
*helper
= (MonoReflectionSigHelper
*)obj
;
11538 MonoMethodSignature
*sig
;
11541 if (helper
->arguments
)
11542 nargs
= mono_array_length (helper
->arguments
);
11546 sig
= mono_metadata_signature_alloc (image
, nargs
);
11547 sig
->explicit_this
= helper
->call_conv
& 64 ? 1 : 0;
11548 sig
->hasthis
= helper
->call_conv
& 32 ? 1 : 0;
11550 if (helper
->unmanaged_call_conv
) { /* unmanaged */
11551 sig
->call_convention
= helper
->unmanaged_call_conv
- 1;
11552 sig
->pinvoke
= TRUE
;
11553 } else if (helper
->call_conv
& 0x02) {
11554 sig
->call_convention
= MONO_CALL_VARARG
;
11556 sig
->call_convention
= MONO_CALL_DEFAULT
;
11559 sig
->param_count
= nargs
;
11560 /* TODO: Copy type ? */
11561 sig
->ret
= helper
->return_type
->type
;
11562 for (i
= 0; i
< nargs
; ++i
)
11563 sig
->params
[i
] = mono_type_array_get_and_resolve (helper
->arguments
, i
);
11566 *handle_class
= NULL
;
11567 } else if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
11568 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
11569 /* Already created by the managed code */
11570 g_assert (method
->mhandle
);
11571 result
= method
->mhandle
;
11572 *handle_class
= mono_defaults
.methodhandle_class
;
11573 } else if (strcmp (obj
->vtable
->klass
->name
, "GenericTypeParameterBuilder") == 0) {
11574 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
11575 type
= mono_class_inflate_generic_type (type
, context
);
11576 result
= mono_class_from_mono_type (type
);
11577 *handle_class
= mono_defaults
.typehandle_class
;
11579 mono_metadata_free_type (type
);
11580 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoGenericClass") == 0) {
11581 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
11582 type
= mono_class_inflate_generic_type (type
, context
);
11583 result
= mono_class_from_mono_type (type
);
11584 *handle_class
= mono_defaults
.typehandle_class
;
11586 mono_metadata_free_type (type
);
11587 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldOnTypeBuilderInst") == 0) {
11588 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
11589 MonoClass
*inflated
;
11591 MonoClassField
*field
;
11593 if (is_sre_field_builder (mono_object_class (f
->fb
)))
11594 field
= ((MonoReflectionFieldBuilder
*)f
->fb
)->handle
;
11595 else if (is_sr_mono_field (mono_object_class (f
->fb
)))
11596 field
= ((MonoReflectionField
*)f
->fb
)->field
;
11598 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
)));
11600 type
= mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType
*)f
->inst
), context
);
11601 inflated
= mono_class_from_mono_type (type
);
11603 result
= field
= mono_class_get_field_from_name (inflated
, mono_field_get_name (field
));
11604 ensure_complete_type (field
->parent
);
11606 mono_metadata_free_type (type
);
11607 *handle_class
= mono_defaults
.fieldhandle_class
;
11608 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
11609 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
11610 MonoType
*type
= mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType
*)c
->inst
), context
);
11611 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
11612 MonoMethod
*method
;
11614 if (is_sre_ctor_builder (mono_object_class (c
->cb
)))
11615 method
= ((MonoReflectionCtorBuilder
*)c
->cb
)->mhandle
;
11616 else if (is_sr_mono_cmethod (mono_object_class (c
->cb
)))
11617 method
= ((MonoReflectionMethod
*)c
->cb
)->method
;
11619 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
)));
11621 result
= inflate_mono_method (inflated_klass
, method
, (MonoObject
*)c
->cb
);
11622 *handle_class
= mono_defaults
.methodhandle_class
;
11623 mono_metadata_free_type (type
);
11624 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodOnTypeBuilderInst") == 0) {
11625 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
11626 if (m
->method_args
) {
11627 result
= mono_reflection_method_on_tb_inst_get_handle (m
);
11629 MonoType
*type
= mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
), context
);
11630 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
11631 MonoMethod
*method
;
11633 if (is_sre_method_builder (mono_object_class (m
->mb
)))
11634 method
= ((MonoReflectionMethodBuilder
*)m
->mb
)->mhandle
;
11635 else if (is_sr_mono_method (mono_object_class (m
->mb
)))
11636 method
= ((MonoReflectionMethod
*)m
->mb
)->method
;
11638 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
)));
11640 result
= inflate_mono_method (inflated_klass
, method
, (MonoObject
*)m
->mb
);
11641 mono_metadata_free_type (type
);
11643 *handle_class
= mono_defaults
.methodhandle_class
;
11644 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoArrayMethod") == 0) {
11645 MonoReflectionArrayMethod
*m
= (MonoReflectionArrayMethod
*)obj
;
11648 MonoMethod
*method
;
11652 mtype
= mono_reflection_type_get_handle (m
->parent
);
11653 klass
= mono_class_from_mono_type (mtype
);
11655 /* Find the method */
11657 name
= mono_string_to_utf8 (m
->name
);
11659 while ((method
= mono_class_get_methods (klass
, &iter
))) {
11660 if (!strcmp (method
->name
, name
))
11667 // FIXME: Check parameters/return value etc. match
11670 *handle_class
= mono_defaults
.methodhandle_class
;
11671 } else if (is_sre_array (mono_object_get_class(obj
)) ||
11672 is_sre_byref (mono_object_get_class(obj
)) ||
11673 is_sre_pointer (mono_object_get_class(obj
))) {
11674 MonoReflectionType
*ref_type
= (MonoReflectionType
*)obj
;
11675 MonoType
*type
= mono_reflection_type_get_handle (ref_type
);
11676 result
= mono_class_from_mono_type (type
);
11677 *handle_class
= mono_defaults
.typehandle_class
;
11679 g_print ("%s\n", obj
->vtable
->klass
->name
);
11680 g_assert_not_reached ();
11685 #else /* DISABLE_REFLECTION_EMIT */
11688 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
11690 g_assert_not_reached ();
11695 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
11697 g_assert_not_reached ();
11701 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
11703 g_assert_not_reached ();
11707 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
11709 g_assert_not_reached ();
11713 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
11715 g_assert_not_reached ();
11719 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
11721 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11725 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
11727 g_assert_not_reached ();
11731 mono_image_set_wrappers_type (MonoReflectionModuleBuilder
*moduleb
, MonoReflectionType
*type
)
11733 g_assert_not_reached ();
11736 MonoReflectionModule
*
11737 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
11739 g_assert_not_reached ();
11744 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
11746 g_assert_not_reached ();
11751 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
11753 g_assert_not_reached ();
11758 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
11759 gboolean create_methodspec
, gboolean register_token
)
11761 g_assert_not_reached ();
11766 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
11771 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
11772 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
11775 g_assert_not_reached ();
11779 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
11782 *num_overrides
= 0;
11785 MonoReflectionEvent
*
11786 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
11788 g_assert_not_reached ();
11792 MonoReflectionType
*
11793 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
11795 g_assert_not_reached ();
11800 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
11802 g_assert_not_reached ();
11806 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
11808 g_assert_not_reached ();
11813 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
11815 g_assert_not_reached ();
11820 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
11825 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
11831 mono_reflection_type_get_handle (MonoReflectionType
* ref
)
11838 #endif /* DISABLE_REFLECTION_EMIT */
11840 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11841 const static guint32 declsec_flags_map
[] = {
11842 0x00000000, /* empty */
11843 MONO_DECLSEC_FLAG_REQUEST
, /* SECURITY_ACTION_REQUEST (x01) */
11844 MONO_DECLSEC_FLAG_DEMAND
, /* SECURITY_ACTION_DEMAND (x02) */
11845 MONO_DECLSEC_FLAG_ASSERT
, /* SECURITY_ACTION_ASSERT (x03) */
11846 MONO_DECLSEC_FLAG_DENY
, /* SECURITY_ACTION_DENY (x04) */
11847 MONO_DECLSEC_FLAG_PERMITONLY
, /* SECURITY_ACTION_PERMITONLY (x05) */
11848 MONO_DECLSEC_FLAG_LINKDEMAND
, /* SECURITY_ACTION_LINKDEMAND (x06) */
11849 MONO_DECLSEC_FLAG_INHERITANCEDEMAND
, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11850 MONO_DECLSEC_FLAG_REQUEST_MINIMUM
, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11851 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL
, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11852 MONO_DECLSEC_FLAG_REQUEST_REFUSE
, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11853 MONO_DECLSEC_FLAG_PREJIT_GRANT
, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11854 MONO_DECLSEC_FLAG_PREJIT_DENY
, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11855 MONO_DECLSEC_FLAG_NONCAS_DEMAND
, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11856 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11857 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11858 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11859 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11860 MONO_DECLSEC_FLAG_DEMAND_CHOICE
, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11864 * Returns flags that includes all available security action associated to the handle.
11865 * @token: metadata token (either for a class or a method)
11866 * @image: image where resides the metadata.
11869 mono_declsec_get_flags (MonoImage
*image
, guint32 token
)
11871 int index
= mono_metadata_declsec_from_index (image
, token
);
11872 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11873 guint32 result
= 0;
11877 /* HasSecurity can be present for other, not specially encoded, attributes,
11878 e.g. SuppressUnmanagedCodeSecurityAttribute */
11882 for (i
= index
; i
< t
->rows
; i
++) {
11883 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11885 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11886 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
11889 action
= cols
[MONO_DECL_SECURITY_ACTION
];
11890 if ((action
>= MONO_DECLSEC_ACTION_MIN
) && (action
<= MONO_DECLSEC_ACTION_MAX
)) {
11891 result
|= declsec_flags_map
[action
];
11893 g_assert_not_reached ();
11900 * Get the security actions (in the form of flags) associated with the specified method.
11902 * @method: The method for which we want the declarative security flags.
11903 * Return the declarative security flags for the method (only).
11905 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11906 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11909 mono_declsec_flags_from_method (MonoMethod
*method
)
11911 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11912 /* FIXME: No cache (for the moment) */
11913 guint32 idx
= mono_method_get_index (method
);
11914 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11915 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11916 return mono_declsec_get_flags (method
->klass
->image
, idx
);
11922 * Get the security actions (in the form of flags) associated with the specified class.
11924 * @klass: The class for which we want the declarative security flags.
11925 * Return the declarative security flags for the class.
11927 * Note: We cache the flags inside the MonoClass structure as this will get
11928 * called very often (at least for each method).
11931 mono_declsec_flags_from_class (MonoClass
*klass
)
11933 if (klass
->flags
& TYPE_ATTRIBUTE_HAS_SECURITY
) {
11934 if (!klass
->ext
|| !klass
->ext
->declsec_flags
) {
11937 idx
= mono_metadata_token_index (klass
->type_token
);
11938 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11939 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11940 mono_loader_lock ();
11941 mono_class_alloc_ext (klass
);
11942 mono_loader_unlock ();
11943 /* we cache the flags on classes */
11944 klass
->ext
->declsec_flags
= mono_declsec_get_flags (klass
->image
, idx
);
11946 return klass
->ext
->declsec_flags
;
11952 * Get the security actions (in the form of flags) associated with the specified assembly.
11954 * @assembly: The assembly for which we want the declarative security flags.
11955 * Return the declarative security flags for the assembly.
11958 mono_declsec_flags_from_assembly (MonoAssembly
*assembly
)
11960 guint32 idx
= 1; /* there is only one assembly */
11961 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11962 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
11963 return mono_declsec_get_flags (assembly
->image
, idx
);
11968 * Fill actions for the specific index (which may either be an encoded class token or
11969 * an encoded method token) from the metadata image.
11970 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11973 fill_actions_from_index (MonoImage
*image
, guint32 token
, MonoDeclSecurityActions
* actions
,
11974 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11976 MonoBoolean result
= FALSE
;
11978 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11979 int index
= mono_metadata_declsec_from_index (image
, token
);
11982 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11983 for (i
= index
; i
< t
->rows
; i
++) {
11984 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11986 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
11989 /* if present only replace (class) permissions with method permissions */
11990 /* if empty accept either class or method permissions */
11991 if (cols
[MONO_DECL_SECURITY_ACTION
] == id_std
) {
11992 if (!actions
->demand
.blob
) {
11993 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11994 actions
->demand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11995 actions
->demand
.blob
= (char*) (blob
+ 2);
11996 actions
->demand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11999 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_noncas
) {
12000 if (!actions
->noncasdemand
.blob
) {
12001 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
12002 actions
->noncasdemand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
12003 actions
->noncasdemand
.blob
= (char*) (blob
+ 2);
12004 actions
->noncasdemand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
12007 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_choice
) {
12008 if (!actions
->demandchoice
.blob
) {
12009 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
12010 actions
->demandchoice
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
12011 actions
->demandchoice
.blob
= (char*) (blob
+ 2);
12012 actions
->demandchoice
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
12022 mono_declsec_get_class_demands_params (MonoClass
*klass
, MonoDeclSecurityActions
* demands
,
12023 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
12025 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
12026 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
12027 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
12028 return fill_actions_from_index (klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
12032 mono_declsec_get_method_demands_params (MonoMethod
*method
, MonoDeclSecurityActions
* demands
,
12033 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
12035 guint32 idx
= mono_method_get_index (method
);
12036 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
12037 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
12038 return fill_actions_from_index (method
->klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
12042 * Collect all actions (that requires to generate code in mini) assigned for
12043 * the specified method.
12044 * Note: Don't use the content of actions if the function return FALSE.
12047 mono_declsec_get_demands (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
12049 guint32 mask
= MONO_DECLSEC_FLAG_DEMAND
| MONO_DECLSEC_FLAG_NONCAS_DEMAND
|
12050 MONO_DECLSEC_FLAG_DEMAND_CHOICE
;
12051 MonoBoolean result
= FALSE
;
12054 /* quick exit if no declarative security is present in the metadata */
12055 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
12058 /* we want the original as the wrapper is "free" of the security informations */
12059 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
12060 method
= mono_marshal_method_from_wrapper (method
);
12065 /* First we look for method-level attributes */
12066 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
12067 mono_class_init (method
->klass
);
12068 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
12070 result
= mono_declsec_get_method_demands_params (method
, demands
,
12071 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
12074 /* Here we use (or create) the class declarative cache to look for demands */
12075 flags
= mono_declsec_flags_from_class (method
->klass
);
12076 if (flags
& mask
) {
12078 mono_class_init (method
->klass
);
12079 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
12081 result
|= mono_declsec_get_class_demands_params (method
->klass
, demands
,
12082 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
12085 /* The boolean return value is used as a shortcut in case nothing needs to
12086 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
12092 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
12094 * Note: Don't use the content of actions if the function return FALSE.
12097 mono_declsec_get_linkdemands (MonoMethod
*method
, MonoDeclSecurityActions
* klass
, MonoDeclSecurityActions
*cmethod
)
12099 MonoBoolean result
= FALSE
;
12102 /* quick exit if no declarative security is present in the metadata */
12103 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
12106 /* we want the original as the wrapper is "free" of the security informations */
12107 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
12108 method
= mono_marshal_method_from_wrapper (method
);
12113 /* results are independant - zeroize both */
12114 memset (cmethod
, 0, sizeof (MonoDeclSecurityActions
));
12115 memset (klass
, 0, sizeof (MonoDeclSecurityActions
));
12117 /* First we look for method-level attributes */
12118 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
12119 mono_class_init (method
->klass
);
12121 result
= mono_declsec_get_method_demands_params (method
, cmethod
,
12122 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
12125 /* Here we use (or create) the class declarative cache to look for demands */
12126 flags
= mono_declsec_flags_from_class (method
->klass
);
12127 if (flags
& (MONO_DECLSEC_FLAG_LINKDEMAND
| MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
| MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
)) {
12128 mono_class_init (method
->klass
);
12130 result
|= mono_declsec_get_class_demands_params (method
->klass
, klass
,
12131 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
12138 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12140 * @klass The inherited class - this is the class that provides the security check (attributes)
12142 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
12144 * Note: Don't use the content of actions if the function return FALSE.
12147 mono_declsec_get_inheritdemands_class (MonoClass
*klass
, MonoDeclSecurityActions
* demands
)
12149 MonoBoolean result
= FALSE
;
12152 /* quick exit if no declarative security is present in the metadata */
12153 if (!klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
12156 /* Here we use (or create) the class declarative cache to look for demands */
12157 flags
= mono_declsec_flags_from_class (klass
);
12158 if (flags
& (MONO_DECLSEC_FLAG_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
)) {
12159 mono_class_init (klass
);
12160 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
12162 result
|= mono_declsec_get_class_demands_params (klass
, demands
,
12163 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
12170 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
12172 * Note: Don't use the content of actions if the function return FALSE.
12175 mono_declsec_get_inheritdemands_method (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
12177 /* quick exit if no declarative security is present in the metadata */
12178 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
12181 /* we want the original as the wrapper is "free" of the security informations */
12182 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
12183 method
= mono_marshal_method_from_wrapper (method
);
12188 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
12189 mono_class_init (method
->klass
);
12190 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
12192 return mono_declsec_get_method_demands_params (method
, demands
,
12193 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
12200 get_declsec_action (MonoImage
*image
, guint32 token
, guint32 action
, MonoDeclSecurityEntry
*entry
)
12202 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
12206 int index
= mono_metadata_declsec_from_index (image
, token
);
12210 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
12211 for (i
= index
; i
< t
->rows
; i
++) {
12212 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
12214 /* shortcut - index are ordered */
12215 if (token
!= cols
[MONO_DECL_SECURITY_PARENT
])
12218 if (cols
[MONO_DECL_SECURITY_ACTION
] == action
) {
12219 const char *metadata
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
12220 entry
->blob
= (char*) (metadata
+ 2);
12221 entry
->size
= mono_metadata_decode_blob_size (metadata
, &metadata
);
12230 mono_declsec_get_method_action (MonoMethod
*method
, guint32 action
, MonoDeclSecurityEntry
*entry
)
12232 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
12233 guint32 idx
= mono_method_get_index (method
);
12234 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
12235 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
12236 return get_declsec_action (method
->klass
->image
, idx
, action
, entry
);
12242 mono_declsec_get_class_action (MonoClass
*klass
, guint32 action
, MonoDeclSecurityEntry
*entry
)
12245 guint32 flags
= mono_declsec_flags_from_class (klass
);
12246 if (declsec_flags_map
[action
] & flags
) {
12247 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
12248 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
12249 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
12250 return get_declsec_action (klass
->image
, idx
, action
, entry
);
12256 mono_declsec_get_assembly_action (MonoAssembly
*assembly
, guint32 action
, MonoDeclSecurityEntry
*entry
)
12258 guint32 idx
= 1; /* there is only one assembly */
12259 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
12260 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
12262 return get_declsec_action (assembly
->image
, idx
, action
, entry
);
12266 mono_reflection_call_is_assignable_to (MonoClass
*klass
, MonoClass
*oklass
)
12268 MonoObject
*res
, *exc
;
12270 static MonoClass
*System_Reflection_Emit_TypeBuilder
= NULL
;
12271 static MonoMethod
*method
= NULL
;
12273 if (!System_Reflection_Emit_TypeBuilder
) {
12274 System_Reflection_Emit_TypeBuilder
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection.Emit", "TypeBuilder");
12275 g_assert (System_Reflection_Emit_TypeBuilder
);
12277 if (method
== NULL
) {
12278 method
= mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder
, "IsAssignableTo", 1);
12283 * The result of mono_type_get_object () might be a System.MonoType but we
12284 * need a TypeBuilder so use mono_class_get_ref_info (klass).
12286 g_assert (mono_class_get_ref_info (klass
));
12287 g_assert (!strcmp (((MonoObject
*)(mono_class_get_ref_info (klass
)))->vtable
->klass
->name
, "TypeBuilder"));
12289 params
[0] = mono_type_get_object (mono_domain_get (), &oklass
->byval_arg
);
12291 res
= mono_runtime_invoke (method
, (MonoObject
*)(mono_class_get_ref_info (klass
)), params
, &exc
);
12295 return *(MonoBoolean
*)mono_object_unbox (res
);