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>
43 static void* reflection_info_desc
= NULL
;
44 #define MOVING_GC_REGISTER(addr) do { \
45 if (!reflection_info_desc) { \
47 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
49 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
52 #define MOVING_GC_REGISTER(addr)
61 #define TEXT_OFFSET 512
62 #define CLI_H_SIZE 136
63 #define FILE_ALIGN 512
64 #define VIRT_ALIGN 8192
65 #define START_TEXT_RVA 0x00002000
68 MonoReflectionILGen
*ilgen
;
69 MonoReflectionType
*rtype
;
70 MonoArray
*parameters
;
71 MonoArray
*generic_params
;
72 MonoGenericContainer
*generic_container
;
78 guint32
*table_idx
; /* note: it's a pointer */
82 MonoBoolean init_locals
;
83 MonoBoolean skip_visibility
;
84 MonoArray
*return_modreq
;
85 MonoArray
*return_modopt
;
86 MonoArray
*param_modreq
;
87 MonoArray
*param_modopt
;
88 MonoArray
*permissions
;
93 int charset
, extra_flags
, native_cc
;
94 MonoString
*dll
, *dllentry
;
95 } ReflectionMethodBuilder
;
99 MonoReflectionGenericParam
*gparam
;
100 } GenericParamTableEntry
;
102 const unsigned char table_sizes
[MONO_TABLE_NUM
] = {
112 MONO_INTERFACEIMPL_SIZE
,
113 MONO_MEMBERREF_SIZE
, /* 0x0A */
115 MONO_CUSTOM_ATTR_SIZE
,
116 MONO_FIELD_MARSHAL_SIZE
,
117 MONO_DECL_SECURITY_SIZE
,
118 MONO_CLASS_LAYOUT_SIZE
,
119 MONO_FIELD_LAYOUT_SIZE
, /* 0x10 */
120 MONO_STAND_ALONE_SIGNATURE_SIZE
,
124 MONO_PROPERTY_MAP_SIZE
,
127 MONO_METHOD_SEMA_SIZE
,
128 MONO_METHODIMPL_SIZE
,
129 MONO_MODULEREF_SIZE
, /* 0x1A */
135 MONO_ASSEMBLY_SIZE
, /* 0x20 */
136 MONO_ASSEMBLY_PROCESSOR_SIZE
,
137 MONO_ASSEMBLYOS_SIZE
,
138 MONO_ASSEMBLYREF_SIZE
,
139 MONO_ASSEMBLYREFPROC_SIZE
,
140 MONO_ASSEMBLYREFOS_SIZE
,
144 MONO_NESTED_CLASS_SIZE
,
146 MONO_GENERICPARAM_SIZE
, /* 0x2A */
147 MONO_METHODSPEC_SIZE
,
148 MONO_GENPARCONSTRAINT_SIZE
152 #ifndef DISABLE_REFLECTION_EMIT
153 static guint32
mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
);
154 static guint32
mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
);
155 static guint32
mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*cb
);
156 static guint32
mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
);
157 static void ensure_runtime_vtable (MonoClass
*klass
);
158 static gpointer
resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
);
159 static guint32
mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
);
160 static guint32
encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
);
161 static gpointer
register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
);
164 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
);
165 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
);
166 static guint32
mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
);
167 static guint32
mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
);
168 static void mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
);
169 static guint32
encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
);
170 static guint32
encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
);
171 static char* type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
);
172 static void encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
);
173 static void get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
);
174 static MonoObject
*mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
);
175 static MonoReflectionType
*mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
);
176 static MonoType
* mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
);
177 static MonoReflectionType
* mono_reflection_type_resolve_user_types (MonoReflectionType
*type
);
178 static gboolean
is_sre_array (MonoClass
*class);
179 static gboolean
is_sre_byref (MonoClass
*class);
180 static gboolean
is_sre_pointer (MonoClass
*class);
182 #define RESOLVE_TYPE(type) do { type = (void*)mono_reflection_type_resolve_user_types ((MonoReflectionType*)type); } while (0)
183 #define RESOLVE_ARRAY_TYPE_ELEMENT(array, index) do { \
184 MonoReflectionType *__type = mono_array_get (array, MonoReflectionType*, index); \
185 __type = mono_reflection_type_resolve_user_types (__type); \
186 mono_array_set (arr, MonoReflectionType*, index, __type); \
189 #define mono_type_array_get_and_resolve(array, index) mono_reflection_type_get_handle ((MonoReflectionType*)mono_array_get (array, gpointer, index))
192 mono_reflection_init (void)
197 sigbuffer_init (SigBuffer
*buf
, int size
)
199 buf
->buf
= g_malloc (size
);
201 buf
->end
= buf
->buf
+ size
;
205 sigbuffer_make_room (SigBuffer
*buf
, int size
)
207 if (buf
->end
- buf
->p
< size
) {
208 int new_size
= buf
->end
- buf
->buf
+ size
+ 32;
209 char *p
= g_realloc (buf
->buf
, new_size
);
210 size
= buf
->p
- buf
->buf
;
213 buf
->end
= buf
->buf
+ new_size
;
218 sigbuffer_add_value (SigBuffer
*buf
, guint32 val
)
220 sigbuffer_make_room (buf
, 6);
221 mono_metadata_encode_value (val
, buf
->p
, &buf
->p
);
225 sigbuffer_add_byte (SigBuffer
*buf
, guint8 val
)
227 sigbuffer_make_room (buf
, 1);
233 sigbuffer_add_mem (SigBuffer
*buf
, char *p
, guint32 size
)
235 sigbuffer_make_room (buf
, size
);
236 memcpy (buf
->p
, p
, size
);
241 sigbuffer_free (SigBuffer
*buf
)
246 #ifndef DISABLE_REFLECTION_EMIT
250 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
254 image_g_malloc (MonoImage
*image
, guint size
)
257 return mono_image_alloc (image
, size
);
259 return g_malloc (size
);
261 #endif /* !DISABLE_REFLECTION_EMIT */
266 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
270 image_g_malloc0 (MonoImage
*image
, guint size
)
273 return mono_image_alloc0 (image
, size
);
275 return g_malloc0 (size
);
278 #ifndef DISABLE_REFLECTION_EMIT
280 image_strdup (MonoImage
*image
, const char *s
)
283 return mono_image_strdup (image
, s
);
289 #define image_g_new(image,struct_type, n_structs) \
290 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
292 #define image_g_new0(image,struct_type, n_structs) \
293 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
297 alloc_table (MonoDynamicTable
*table
, guint nrows
)
300 g_assert (table
->columns
);
301 if (nrows
+ 1 >= table
->alloc_rows
) {
302 while (nrows
+ 1 >= table
->alloc_rows
) {
303 if (table
->alloc_rows
== 0)
304 table
->alloc_rows
= 16;
306 table
->alloc_rows
*= 2;
309 table
->values
= g_renew (guint32
, table
->values
, (table
->alloc_rows
) * table
->columns
);
314 make_room_in_stream (MonoDynamicStream
*stream
, int size
)
316 if (size
<= stream
->alloc_size
)
319 while (stream
->alloc_size
<= size
) {
320 if (stream
->alloc_size
< 4096)
321 stream
->alloc_size
= 4096;
323 stream
->alloc_size
*= 2;
326 stream
->data
= g_realloc (stream
->data
, stream
->alloc_size
);
330 string_heap_insert (MonoDynamicStream
*sh
, const char *str
)
334 gpointer oldkey
, oldval
;
336 if (g_hash_table_lookup_extended (sh
->hash
, str
, &oldkey
, &oldval
))
337 return GPOINTER_TO_UINT (oldval
);
339 len
= strlen (str
) + 1;
342 make_room_in_stream (sh
, idx
+ len
);
345 * We strdup the string even if we already copy them in sh->data
346 * so that the string pointers in the hash remain valid even if
347 * we need to realloc sh->data. We may want to avoid that later.
349 g_hash_table_insert (sh
->hash
, g_strdup (str
), GUINT_TO_POINTER (idx
));
350 memcpy (sh
->data
+ idx
, str
, len
);
356 string_heap_insert_mstring (MonoDynamicStream
*sh
, MonoString
*str
)
358 char *name
= mono_string_to_utf8 (str
);
360 idx
= string_heap_insert (sh
, name
);
365 #ifndef DISABLE_REFLECTION_EMIT
367 string_heap_init (MonoDynamicStream
*sh
)
370 sh
->alloc_size
= 4096;
371 sh
->data
= g_malloc (4096);
372 sh
->hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
373 string_heap_insert (sh
, "");
378 mono_image_add_stream_data (MonoDynamicStream
*stream
, const char *data
, guint32 len
)
382 make_room_in_stream (stream
, stream
->index
+ len
);
383 memcpy (stream
->data
+ stream
->index
, data
, len
);
385 stream
->index
+= len
;
387 * align index? Not without adding an additional param that controls it since
388 * we may store a blob value in pieces.
394 mono_image_add_stream_zero (MonoDynamicStream
*stream
, guint32 len
)
398 make_room_in_stream (stream
, stream
->index
+ len
);
399 memset (stream
->data
+ stream
->index
, 0, len
);
401 stream
->index
+= len
;
406 stream_data_align (MonoDynamicStream
*stream
)
409 guint32 count
= stream
->index
% 4;
411 /* we assume the stream data will be aligned */
413 mono_image_add_stream_data (stream
, buf
, 4 - count
);
416 #ifndef DISABLE_REFLECTION_EMIT
418 mono_blob_entry_hash (const char* str
)
422 len
= mono_metadata_decode_blob_size (str
, &str
);
426 for (str
+= 1; str
< end
; str
++)
427 h
= (h
<< 5) - h
+ *str
;
435 mono_blob_entry_equal (const char *str1
, const char *str2
) {
439 len
= mono_metadata_decode_blob_size (str1
, &end1
);
440 len2
= mono_metadata_decode_blob_size (str2
, &end2
);
443 return memcmp (end1
, end2
, len
) == 0;
447 add_to_blob_cached (MonoDynamicImage
*assembly
, char *b1
, int s1
, char *b2
, int s2
)
451 gpointer oldkey
, oldval
;
453 copy
= g_malloc (s1
+s2
);
454 memcpy (copy
, b1
, s1
);
455 memcpy (copy
+ s1
, b2
, s2
);
456 if (g_hash_table_lookup_extended (assembly
->blob_cache
, copy
, &oldkey
, &oldval
)) {
458 idx
= GPOINTER_TO_UINT (oldval
);
460 idx
= mono_image_add_stream_data (&assembly
->blob
, b1
, s1
);
461 mono_image_add_stream_data (&assembly
->blob
, b2
, s2
);
462 g_hash_table_insert (assembly
->blob_cache
, copy
, GUINT_TO_POINTER (idx
));
468 sigbuffer_add_to_blob_cached (MonoDynamicImage
*assembly
, SigBuffer
*buf
)
472 guint32 size
= buf
->p
- buf
->buf
;
474 g_assert (size
<= (buf
->end
- buf
->buf
));
475 mono_metadata_encode_value (size
, b
, &b
);
476 return add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, buf
->buf
, size
);
480 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
481 * dest may be misaligned.
484 swap_with_size (char *dest
, const char* val
, int len
, int nelem
) {
485 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
488 for (elem
= 0; elem
< nelem
; ++elem
) {
514 g_assert_not_reached ();
520 memcpy (dest
, val
, len
* nelem
);
525 add_mono_string_to_blob_cached (MonoDynamicImage
*assembly
, MonoString
*str
)
529 guint32 idx
= 0, len
;
531 len
= str
->length
* 2;
532 mono_metadata_encode_value (len
, b
, &b
);
533 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
535 char *swapped
= g_malloc (2 * mono_string_length (str
));
536 const char *p
= (const char*)mono_string_chars (str
);
538 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
539 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
543 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
548 #ifndef DISABLE_REFLECTION_EMIT
550 default_class_from_mono_type (MonoType
*type
)
552 switch (type
->type
) {
553 case MONO_TYPE_OBJECT
:
554 return mono_defaults
.object_class
;
556 return mono_defaults
.void_class
;
557 case MONO_TYPE_BOOLEAN
:
558 return mono_defaults
.boolean_class
;
560 return mono_defaults
.char_class
;
562 return mono_defaults
.sbyte_class
;
564 return mono_defaults
.byte_class
;
566 return mono_defaults
.int16_class
;
568 return mono_defaults
.uint16_class
;
570 return mono_defaults
.int32_class
;
572 return mono_defaults
.uint32_class
;
574 return mono_defaults
.int_class
;
576 return mono_defaults
.uint_class
;
578 return mono_defaults
.int64_class
;
580 return mono_defaults
.uint64_class
;
582 return mono_defaults
.single_class
;
584 return mono_defaults
.double_class
;
585 case MONO_TYPE_STRING
:
586 return mono_defaults
.string_class
;
588 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type
->type
);
589 g_assert_not_reached ();
597 encode_generic_class (MonoDynamicImage
*assembly
, MonoGenericClass
*gclass
, SigBuffer
*buf
)
600 MonoGenericInst
*class_inst
;
605 class_inst
= gclass
->context
.class_inst
;
607 sigbuffer_add_value (buf
, MONO_TYPE_GENERICINST
);
608 klass
= gclass
->container_class
;
609 sigbuffer_add_value (buf
, klass
->byval_arg
.type
);
610 sigbuffer_add_value (buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
612 sigbuffer_add_value (buf
, class_inst
->type_argc
);
613 for (i
= 0; i
< class_inst
->type_argc
; ++i
)
614 encode_type (assembly
, class_inst
->type_argv
[i
], buf
);
619 encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
)
622 g_assert_not_reached ();
627 sigbuffer_add_value (buf
, MONO_TYPE_BYREF
);
631 case MONO_TYPE_BOOLEAN
:
645 case MONO_TYPE_STRING
:
646 case MONO_TYPE_OBJECT
:
647 case MONO_TYPE_TYPEDBYREF
:
648 sigbuffer_add_value (buf
, type
->type
);
651 sigbuffer_add_value (buf
, type
->type
);
652 encode_type (assembly
, type
->data
.type
, buf
);
654 case MONO_TYPE_SZARRAY
:
655 sigbuffer_add_value (buf
, type
->type
);
656 encode_type (assembly
, &type
->data
.klass
->byval_arg
, buf
);
658 case MONO_TYPE_VALUETYPE
:
659 case MONO_TYPE_CLASS
: {
660 MonoClass
*k
= mono_class_from_mono_type (type
);
662 if (k
->generic_container
) {
663 MonoGenericClass
*gclass
= mono_metadata_lookup_generic_class (k
, k
->generic_container
->context
.class_inst
, TRUE
);
664 encode_generic_class (assembly
, gclass
, buf
);
667 * Make sure we use the correct type.
669 sigbuffer_add_value (buf
, k
->byval_arg
.type
);
671 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
672 * otherwise two typerefs could point to the same type, leading to
673 * verification errors.
675 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, &k
->byval_arg
));
679 case MONO_TYPE_ARRAY
:
680 sigbuffer_add_value (buf
, type
->type
);
681 encode_type (assembly
, &type
->data
.array
->eklass
->byval_arg
, buf
);
682 sigbuffer_add_value (buf
, type
->data
.array
->rank
);
683 sigbuffer_add_value (buf
, 0); /* FIXME: set to 0 for now */
684 sigbuffer_add_value (buf
, 0);
686 case MONO_TYPE_GENERICINST
:
687 encode_generic_class (assembly
, type
->data
.generic_class
, buf
);
691 sigbuffer_add_value (buf
, type
->type
);
692 sigbuffer_add_value (buf
, mono_type_get_generic_param_num (type
));
695 g_error ("need to encode type %x", type
->type
);
700 encode_reflection_type (MonoDynamicImage
*assembly
, MonoReflectionType
*type
, SigBuffer
*buf
)
703 sigbuffer_add_value (buf
, MONO_TYPE_VOID
);
707 encode_type (assembly
, mono_reflection_type_get_handle (type
), buf
);
711 encode_custom_modifiers (MonoDynamicImage
*assembly
, MonoArray
*modreq
, MonoArray
*modopt
, SigBuffer
*buf
)
716 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
717 MonoType
*mod
= mono_type_array_get_and_resolve (modreq
, i
);
718 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_REQD
);
719 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
));
723 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
724 MonoType
*mod
= mono_type_array_get_and_resolve (modopt
, i
);
725 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_OPT
);
726 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
));
731 #ifndef DISABLE_REFLECTION_EMIT
733 method_encode_signature (MonoDynamicImage
*assembly
, MonoMethodSignature
*sig
)
737 guint32 nparams
= sig
->param_count
;
743 sigbuffer_init (&buf
, 32);
745 * FIXME: vararg, explicit_this, differenc call_conv values...
747 idx
= sig
->call_convention
;
749 idx
|= 0x20; /* hasthis */
750 if (sig
->generic_param_count
)
751 idx
|= 0x10; /* generic */
752 sigbuffer_add_byte (&buf
, idx
);
753 if (sig
->generic_param_count
)
754 sigbuffer_add_value (&buf
, sig
->generic_param_count
);
755 sigbuffer_add_value (&buf
, nparams
);
756 encode_type (assembly
, sig
->ret
, &buf
);
757 for (i
= 0; i
< nparams
; ++i
) {
758 if (i
== sig
->sentinelpos
)
759 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
760 encode_type (assembly
, sig
->params
[i
], &buf
);
762 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
763 sigbuffer_free (&buf
);
769 method_builder_encode_signature (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
772 * FIXME: reuse code from method_encode_signature().
776 guint32 nparams
= mb
->parameters
? mono_array_length (mb
->parameters
): 0;
777 guint32 ngparams
= mb
->generic_params
? mono_array_length (mb
->generic_params
): 0;
778 guint32 notypes
= mb
->opt_types
? mono_array_length (mb
->opt_types
): 0;
781 sigbuffer_init (&buf
, 32);
782 /* LAMESPEC: all the call conv spec is foobared */
783 idx
= mb
->call_conv
& 0x60; /* has-this, explicit-this */
784 if (mb
->call_conv
& 2)
785 idx
|= 0x5; /* vararg */
786 if (!(mb
->attrs
& METHOD_ATTRIBUTE_STATIC
))
787 idx
|= 0x20; /* hasthis */
789 idx
|= 0x10; /* generic */
790 sigbuffer_add_byte (&buf
, idx
);
792 sigbuffer_add_value (&buf
, ngparams
);
793 sigbuffer_add_value (&buf
, nparams
+ notypes
);
794 encode_custom_modifiers (assembly
, mb
->return_modreq
, mb
->return_modopt
, &buf
);
795 encode_reflection_type (assembly
, mb
->rtype
, &buf
);
796 for (i
= 0; i
< nparams
; ++i
) {
797 MonoArray
*modreq
= NULL
;
798 MonoArray
*modopt
= NULL
;
799 MonoReflectionType
*pt
;
801 if (mb
->param_modreq
&& (i
< mono_array_length (mb
->param_modreq
)))
802 modreq
= mono_array_get (mb
->param_modreq
, MonoArray
*, i
);
803 if (mb
->param_modopt
&& (i
< mono_array_length (mb
->param_modopt
)))
804 modopt
= mono_array_get (mb
->param_modopt
, MonoArray
*, i
);
805 encode_custom_modifiers (assembly
, modreq
, modopt
, &buf
);
806 pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
807 encode_reflection_type (assembly
, pt
, &buf
);
810 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
811 for (i
= 0; i
< notypes
; ++i
) {
812 MonoReflectionType
*pt
;
814 pt
= mono_array_get (mb
->opt_types
, MonoReflectionType
*, i
);
815 encode_reflection_type (assembly
, pt
, &buf
);
818 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
819 sigbuffer_free (&buf
);
824 encode_locals (MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
)
826 MonoDynamicTable
*table
;
828 guint32 idx
, sig_idx
;
829 guint nl
= mono_array_length (ilgen
->locals
);
833 sigbuffer_init (&buf
, 32);
834 sigbuffer_add_value (&buf
, 0x07);
835 sigbuffer_add_value (&buf
, nl
);
836 for (i
= 0; i
< nl
; ++i
) {
837 MonoReflectionLocalBuilder
*lb
= mono_array_get (ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
840 sigbuffer_add_value (&buf
, MONO_TYPE_PINNED
);
842 encode_reflection_type (assembly
, (MonoReflectionType
*)lb
->type
, &buf
);
844 sig_idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
845 sigbuffer_free (&buf
);
847 if (assembly
->standalonesig_cache
== NULL
)
848 assembly
->standalonesig_cache
= g_hash_table_new (NULL
, NULL
);
849 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
)));
853 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
854 idx
= table
->next_idx
++;
856 alloc_table (table
, table
->rows
);
857 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
859 values
[MONO_STAND_ALONE_SIGNATURE
] = sig_idx
;
861 g_hash_table_insert (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
), GUINT_TO_POINTER (idx
));
867 method_count_clauses (MonoReflectionILGen
*ilgen
)
869 guint32 num_clauses
= 0;
872 MonoILExceptionInfo
*ex_info
;
873 for (i
= 0; i
< mono_array_length (ilgen
->ex_handlers
); ++i
) {
874 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
875 if (ex_info
->handlers
)
876 num_clauses
+= mono_array_length (ex_info
->handlers
);
884 #ifndef DISABLE_REFLECTION_EMIT
885 static MonoExceptionClause
*
886 method_encode_clauses (MonoImage
*image
, MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
, guint32 num_clauses
)
888 MonoExceptionClause
*clauses
;
889 MonoExceptionClause
*clause
;
890 MonoILExceptionInfo
*ex_info
;
891 MonoILExceptionBlock
*ex_block
;
892 guint32 finally_start
;
893 int i
, j
, clause_index
;;
895 clauses
= image_g_new0 (image
, MonoExceptionClause
, num_clauses
);
898 for (i
= mono_array_length (ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
899 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
900 finally_start
= ex_info
->start
+ ex_info
->len
;
901 if (!ex_info
->handlers
)
903 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
904 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
905 clause
= &(clauses
[clause_index
]);
907 clause
->flags
= ex_block
->type
;
908 clause
->try_offset
= ex_info
->start
;
910 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
911 clause
->try_len
= finally_start
- ex_info
->start
;
913 clause
->try_len
= ex_info
->len
;
914 clause
->handler_offset
= ex_block
->start
;
915 clause
->handler_len
= ex_block
->len
;
916 if (ex_block
->extype
) {
917 clause
->data
.catch_class
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)ex_block
->extype
));
919 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
920 clause
->data
.filter_offset
= ex_block
->filter_offset
;
922 clause
->data
.filter_offset
= 0;
924 finally_start
= ex_block
->start
+ ex_block
->len
;
932 #endif /* !DISABLE_REFLECTION_EMIT */
935 method_encode_code (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
941 gint32 num_locals
= 0;
942 gint32 num_exception
= 0;
945 char fat_header
[12];
948 guint32 local_sig
= 0;
949 guint32 header_size
= 12;
952 if ((mb
->attrs
& (METHOD_ATTRIBUTE_PINVOKE_IMPL
| METHOD_ATTRIBUTE_ABSTRACT
)) ||
953 (mb
->iattrs
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)))
957 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
959 code
= mb
->ilgen
->code
;
960 code_size
= mb
->ilgen
->code_len
;
961 max_stack
= mb
->ilgen
->max_stack
;
962 num_locals
= mb
->ilgen
->locals
? mono_array_length (mb
->ilgen
->locals
) : 0;
963 if (mb
->ilgen
->ex_handlers
)
964 num_exception
= method_count_clauses (mb
->ilgen
);
968 char *name
= mono_string_to_utf8 (mb
->name
);
969 char *str
= g_strdup_printf ("Method %s does not have any IL associated", name
);
970 MonoException
*exception
= mono_get_exception_argument (NULL
, "a method does not have any IL associated");
973 mono_raise_exception (exception
);
976 code_size
= mono_array_length (code
);
977 max_stack
= 8; /* we probably need to run a verifier on the code... */
980 stream_data_align (&assembly
->code
);
982 /* check for exceptions, maxstack, locals */
983 maybe_small
= (max_stack
<= 8) && (!num_locals
) && (!num_exception
);
985 if (code_size
< 64 && !(code_size
& 1)) {
986 flags
= (code_size
<< 2) | 0x2;
987 } else if (code_size
< 32 && (code_size
& 1)) {
988 flags
= (code_size
<< 2) | 0x6; /* LAMESPEC: see metadata.c */
992 idx
= mono_image_add_stream_data (&assembly
->code
, &flags
, 1);
993 /* add to the fixup todo list */
994 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
995 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 1));
996 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
997 return assembly
->text_rva
+ idx
;
1001 local_sig
= MONO_TOKEN_SIGNATURE
| encode_locals (assembly
, mb
->ilgen
);
1003 * FIXME: need to set also the header size in fat_flags.
1004 * (and more sects and init locals flags)
1008 fat_flags
|= METHOD_HEADER_MORE_SECTS
;
1009 if (mb
->init_locals
)
1010 fat_flags
|= METHOD_HEADER_INIT_LOCALS
;
1011 fat_header
[0] = fat_flags
;
1012 fat_header
[1] = (header_size
/ 4 ) << 4;
1013 short_value
= GUINT16_TO_LE (max_stack
);
1014 memcpy (fat_header
+ 2, &short_value
, 2);
1015 int_value
= GUINT32_TO_LE (code_size
);
1016 memcpy (fat_header
+ 4, &int_value
, 4);
1017 int_value
= GUINT32_TO_LE (local_sig
);
1018 memcpy (fat_header
+ 8, &int_value
, 4);
1019 idx
= mono_image_add_stream_data (&assembly
->code
, fat_header
, 12);
1020 /* add to the fixup todo list */
1021 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1022 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 12));
1024 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1025 if (num_exception
) {
1026 unsigned char sheader
[4];
1027 MonoILExceptionInfo
* ex_info
;
1028 MonoILExceptionBlock
* ex_block
;
1031 stream_data_align (&assembly
->code
);
1032 /* always use fat format for now */
1033 sheader
[0] = METHOD_HEADER_SECTION_FAT_FORMAT
| METHOD_HEADER_SECTION_EHTABLE
;
1034 num_exception
*= 6 * sizeof (guint32
);
1035 num_exception
+= 4; /* include the size of the header */
1036 sheader
[1] = num_exception
& 0xff;
1037 sheader
[2] = (num_exception
>> 8) & 0xff;
1038 sheader
[3] = (num_exception
>> 16) & 0xff;
1039 mono_image_add_stream_data (&assembly
->code
, (char*)sheader
, 4);
1040 /* fat header, so we are already aligned */
1042 for (i
= mono_array_length (mb
->ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
1043 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (mb
->ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
1044 if (ex_info
->handlers
) {
1045 int finally_start
= ex_info
->start
+ ex_info
->len
;
1046 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
1048 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
1050 val
= GUINT32_TO_LE (ex_block
->type
);
1051 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1053 val
= GUINT32_TO_LE (ex_info
->start
);
1054 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1055 /* need fault, too, probably */
1056 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
1057 val
= GUINT32_TO_LE (finally_start
- ex_info
->start
);
1059 val
= GUINT32_TO_LE (ex_info
->len
);
1060 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1061 /* handler offset */
1062 val
= GUINT32_TO_LE (ex_block
->start
);
1063 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1065 val
= GUINT32_TO_LE (ex_block
->len
);
1066 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1067 finally_start
= ex_block
->start
+ ex_block
->len
;
1068 if (ex_block
->extype
) {
1069 val
= mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)ex_block
->extype
)));
1071 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
1072 val
= ex_block
->filter_offset
;
1076 val
= GUINT32_TO_LE (val
);
1077 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1078 /*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",
1079 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);*/
1082 g_error ("No clauses for ex info block %d", i
);
1086 return assembly
->text_rva
+ idx
;
1090 find_index_in_table (MonoDynamicImage
*assembly
, int table_idx
, int col
, guint32 token
)
1093 MonoDynamicTable
*table
;
1096 table
= &assembly
->tables
[table_idx
];
1098 g_assert (col
< table
->columns
);
1100 values
= table
->values
+ table
->columns
;
1101 for (i
= 1; i
<= table
->rows
; ++i
) {
1102 if (values
[col
] == token
)
1104 values
+= table
->columns
;
1110 * LOCKING: Acquires the loader lock.
1112 static MonoCustomAttrInfo
*
1113 lookup_custom_attr (MonoImage
*image
, gpointer member
)
1115 MonoCustomAttrInfo
* res
;
1117 res
= mono_image_property_lookup (image
, member
, MONO_PROP_DYNAMIC_CATTR
);
1122 return g_memdup (res
, sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (res
->num_attrs
- MONO_ZERO_LEN_ARRAY
));
1126 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttr
*cattr
)
1128 /* FIXME: Need to do more checks */
1129 if (cattr
->ctor
->method
&& (cattr
->ctor
->method
->klass
->image
!= image
)) {
1130 int visibility
= cattr
->ctor
->method
->klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
1132 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
1139 static MonoCustomAttrInfo
*
1140 mono_custom_attrs_from_builders (MonoImage
*alloc_img
, MonoImage
*image
, MonoArray
*cattrs
)
1142 int i
, index
, count
, not_visible
;
1143 MonoCustomAttrInfo
*ainfo
;
1144 MonoReflectionCustomAttr
*cattr
;
1148 /* FIXME: check in assembly the Run flag is set */
1150 count
= mono_array_length (cattrs
);
1152 /* Skip nonpublic attributes since MS.NET seems to do the same */
1153 /* FIXME: This needs to be done more globally */
1155 for (i
= 0; i
< count
; ++i
) {
1156 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1157 if (!custom_attr_visible (image
, cattr
))
1160 count
-= not_visible
;
1162 ainfo
= image_g_malloc0 (alloc_img
, sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (count
- MONO_ZERO_LEN_ARRAY
));
1164 ainfo
->image
= image
;
1165 ainfo
->num_attrs
= count
;
1166 ainfo
->cached
= alloc_img
!= NULL
;
1168 for (i
= 0; i
< count
; ++i
) {
1169 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1170 if (custom_attr_visible (image
, cattr
)) {
1171 unsigned char *saved
= mono_image_alloc (image
, mono_array_length (cattr
->data
));
1172 memcpy (saved
, mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1173 ainfo
->attrs
[index
].ctor
= cattr
->ctor
->method
;
1174 ainfo
->attrs
[index
].data
= saved
;
1175 ainfo
->attrs
[index
].data_size
= mono_array_length (cattr
->data
);
1183 #ifndef DISABLE_REFLECTION_EMIT
1185 * LOCKING: Acquires the loader lock.
1188 mono_save_custom_attrs (MonoImage
*image
, void *obj
, MonoArray
*cattrs
)
1190 MonoCustomAttrInfo
*ainfo
, *tmp
;
1192 if (!cattrs
|| !mono_array_length (cattrs
))
1195 ainfo
= mono_custom_attrs_from_builders (image
, image
, cattrs
);
1197 mono_loader_lock ();
1198 tmp
= mono_image_property_lookup (image
, obj
, MONO_PROP_DYNAMIC_CATTR
);
1200 mono_custom_attrs_free (tmp
);
1201 mono_image_property_insert (image
, obj
, MONO_PROP_DYNAMIC_CATTR
, ainfo
);
1202 mono_loader_unlock ();
1208 mono_custom_attrs_free (MonoCustomAttrInfo
*ainfo
)
1215 * idx is the table index of the object
1216 * type is one of MONO_CUSTOM_ATTR_*
1219 mono_image_add_cattrs (MonoDynamicImage
*assembly
, guint32 idx
, guint32 type
, MonoArray
*cattrs
)
1221 MonoDynamicTable
*table
;
1222 MonoReflectionCustomAttr
*cattr
;
1224 guint32 count
, i
, token
;
1226 char *p
= blob_size
;
1228 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1231 count
= mono_array_length (cattrs
);
1232 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1233 table
->rows
+= count
;
1234 alloc_table (table
, table
->rows
);
1235 values
= table
->values
+ table
->next_idx
* MONO_CUSTOM_ATTR_SIZE
;
1236 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1238 for (i
= 0; i
< count
; ++i
) {
1239 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1240 values
[MONO_CUSTOM_ATTR_PARENT
] = idx
;
1241 token
= mono_image_create_token (assembly
, (MonoObject
*)cattr
->ctor
, FALSE
, FALSE
);
1242 type
= mono_metadata_token_index (token
);
1243 type
<<= MONO_CUSTOM_ATTR_TYPE_BITS
;
1244 switch (mono_metadata_token_table (token
)) {
1245 case MONO_TABLE_METHOD
:
1246 type
|= MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
1248 case MONO_TABLE_MEMBERREF
:
1249 type
|= MONO_CUSTOM_ATTR_TYPE_MEMBERREF
;
1252 g_warning ("got wrong token in custom attr");
1255 values
[MONO_CUSTOM_ATTR_TYPE
] = type
;
1257 mono_metadata_encode_value (mono_array_length (cattr
->data
), p
, &p
);
1258 values
[MONO_CUSTOM_ATTR_VALUE
] = add_to_blob_cached (assembly
, blob_size
, p
- blob_size
,
1259 mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1260 values
+= MONO_CUSTOM_ATTR_SIZE
;
1266 mono_image_add_decl_security (MonoDynamicImage
*assembly
, guint32 parent_token
, MonoArray
*permissions
)
1268 MonoDynamicTable
*table
;
1270 guint32 count
, i
, idx
;
1271 MonoReflectionPermissionSet
*perm
;
1276 count
= mono_array_length (permissions
);
1277 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
1278 table
->rows
+= count
;
1279 alloc_table (table
, table
->rows
);
1281 for (i
= 0; i
< mono_array_length (permissions
); ++i
) {
1282 perm
= (MonoReflectionPermissionSet
*)mono_array_addr (permissions
, MonoReflectionPermissionSet
, i
);
1284 values
= table
->values
+ table
->next_idx
* MONO_DECL_SECURITY_SIZE
;
1286 idx
= mono_metadata_token_index (parent_token
);
1287 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
1288 switch (mono_metadata_token_table (parent_token
)) {
1289 case MONO_TABLE_TYPEDEF
:
1290 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
1292 case MONO_TABLE_METHOD
:
1293 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
1295 case MONO_TABLE_ASSEMBLY
:
1296 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
1299 g_assert_not_reached ();
1302 values
[MONO_DECL_SECURITY_ACTION
] = perm
->action
;
1303 values
[MONO_DECL_SECURITY_PARENT
] = idx
;
1304 values
[MONO_DECL_SECURITY_PERMISSIONSET
] = add_mono_string_to_blob_cached (assembly
, perm
->pset
);
1311 * Fill in the MethodDef and ParamDef tables for a method.
1312 * This is used for both normal methods and constructors.
1315 mono_image_basic_method (ReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1317 MonoDynamicTable
*table
;
1321 /* room in this table is already allocated */
1322 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
1323 *mb
->table_idx
= table
->next_idx
++;
1324 g_hash_table_insert (assembly
->method_to_table_idx
, mb
->mhandle
, GUINT_TO_POINTER ((*mb
->table_idx
)));
1325 values
= table
->values
+ *mb
->table_idx
* MONO_METHOD_SIZE
;
1326 values
[MONO_METHOD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1327 values
[MONO_METHOD_FLAGS
] = mb
->attrs
;
1328 values
[MONO_METHOD_IMPLFLAGS
] = mb
->iattrs
;
1329 values
[MONO_METHOD_SIGNATURE
] = method_builder_encode_signature (assembly
, mb
);
1330 values
[MONO_METHOD_RVA
] = method_encode_code (assembly
, mb
);
1332 table
= &assembly
->tables
[MONO_TABLE_PARAM
];
1333 values
[MONO_METHOD_PARAMLIST
] = table
->next_idx
;
1335 mono_image_add_decl_security (assembly
,
1336 mono_metadata_make_token (MONO_TABLE_METHOD
, *mb
->table_idx
), mb
->permissions
);
1339 MonoDynamicTable
*mtable
;
1342 mtable
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1343 mvalues
= mtable
->values
+ mtable
->next_idx
* MONO_FIELD_MARSHAL_SIZE
;
1346 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1347 if (mono_array_get (mb
->pinfo
, gpointer
, i
))
1350 table
->rows
+= count
;
1351 alloc_table (table
, table
->rows
);
1352 values
= table
->values
+ table
->next_idx
* MONO_PARAM_SIZE
;
1353 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1354 MonoReflectionParamBuilder
*pb
;
1355 if ((pb
= mono_array_get (mb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
1356 values
[MONO_PARAM_FLAGS
] = pb
->attrs
;
1357 values
[MONO_PARAM_SEQUENCE
] = i
;
1358 if (pb
->name
!= NULL
) {
1359 values
[MONO_PARAM_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1361 values
[MONO_PARAM_NAME
] = 0;
1363 values
+= MONO_PARAM_SIZE
;
1364 if (pb
->marshal_info
) {
1366 alloc_table (mtable
, mtable
->rows
);
1367 mvalues
= mtable
->values
+ mtable
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1368 mvalues
[MONO_FIELD_MARSHAL_PARENT
] = (table
->next_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_PARAMDEF
;
1369 mvalues
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, pb
->marshal_info
);
1371 pb
->table_idx
= table
->next_idx
++;
1372 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
1373 guint32 field_type
= 0;
1374 mtable
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1376 alloc_table (mtable
, mtable
->rows
);
1377 mvalues
= mtable
->values
+ mtable
->rows
* MONO_CONSTANT_SIZE
;
1378 mvalues
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_PARAM
| (pb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1379 mvalues
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, pb
->def_value
, &field_type
);
1380 mvalues
[MONO_CONSTANT_TYPE
] = field_type
;
1381 mvalues
[MONO_CONSTANT_PADDING
] = 0;
1389 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
)
1391 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1393 rmb
->ilgen
= mb
->ilgen
;
1394 rmb
->rtype
= mono_reflection_type_resolve_user_types ((MonoReflectionType
*)mb
->rtype
);
1395 rmb
->parameters
= mb
->parameters
;
1396 rmb
->generic_params
= mb
->generic_params
;
1397 rmb
->generic_container
= mb
->generic_container
;
1398 rmb
->opt_types
= NULL
;
1399 rmb
->pinfo
= mb
->pinfo
;
1400 rmb
->attrs
= mb
->attrs
;
1401 rmb
->iattrs
= mb
->iattrs
;
1402 rmb
->call_conv
= mb
->call_conv
;
1403 rmb
->code
= mb
->code
;
1404 rmb
->type
= mb
->type
;
1405 rmb
->name
= mb
->name
;
1406 rmb
->table_idx
= &mb
->table_idx
;
1407 rmb
->init_locals
= mb
->init_locals
;
1408 rmb
->skip_visibility
= FALSE
;
1409 rmb
->return_modreq
= mb
->return_modreq
;
1410 rmb
->return_modopt
= mb
->return_modopt
;
1411 rmb
->param_modreq
= mb
->param_modreq
;
1412 rmb
->param_modopt
= mb
->param_modopt
;
1413 rmb
->permissions
= mb
->permissions
;
1414 rmb
->mhandle
= mb
->mhandle
;
1419 rmb
->charset
= mb
->charset
;
1420 rmb
->extra_flags
= mb
->extra_flags
;
1421 rmb
->native_cc
= mb
->native_cc
;
1422 rmb
->dllentry
= mb
->dllentry
;
1428 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
)
1430 const char *name
= mb
->attrs
& METHOD_ATTRIBUTE_STATIC
? ".cctor": ".ctor";
1432 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1434 rmb
->ilgen
= mb
->ilgen
;
1435 rmb
->rtype
= mono_type_get_object (mono_domain_get (), &mono_defaults
.void_class
->byval_arg
);
1436 rmb
->parameters
= mb
->parameters
;
1437 rmb
->generic_params
= NULL
;
1438 rmb
->generic_container
= NULL
;
1439 rmb
->opt_types
= NULL
;
1440 rmb
->pinfo
= mb
->pinfo
;
1441 rmb
->attrs
= mb
->attrs
;
1442 rmb
->iattrs
= mb
->iattrs
;
1443 rmb
->call_conv
= mb
->call_conv
;
1445 rmb
->type
= mb
->type
;
1446 rmb
->name
= mono_string_new (mono_domain_get (), name
);
1447 rmb
->table_idx
= &mb
->table_idx
;
1448 rmb
->init_locals
= mb
->init_locals
;
1449 rmb
->skip_visibility
= FALSE
;
1450 rmb
->return_modreq
= NULL
;
1451 rmb
->return_modopt
= NULL
;
1452 rmb
->param_modreq
= mb
->param_modreq
;
1453 rmb
->param_modopt
= mb
->param_modopt
;
1454 rmb
->permissions
= mb
->permissions
;
1455 rmb
->mhandle
= mb
->mhandle
;
1460 #ifndef DISABLE_REFLECTION_EMIT
1462 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder
*rmb
, MonoReflectionDynamicMethod
*mb
)
1464 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1466 rmb
->ilgen
= mb
->ilgen
;
1467 rmb
->rtype
= mb
->rtype
;
1468 rmb
->parameters
= mb
->parameters
;
1469 rmb
->generic_params
= NULL
;
1470 rmb
->generic_container
= NULL
;
1471 rmb
->opt_types
= NULL
;
1473 rmb
->attrs
= mb
->attrs
;
1475 rmb
->call_conv
= mb
->call_conv
;
1477 rmb
->type
= (MonoObject
*) mb
->owner
;
1478 rmb
->name
= mb
->name
;
1479 rmb
->table_idx
= NULL
;
1480 rmb
->init_locals
= mb
->init_locals
;
1481 rmb
->skip_visibility
= mb
->skip_visibility
;
1482 rmb
->return_modreq
= NULL
;
1483 rmb
->return_modopt
= NULL
;
1484 rmb
->param_modreq
= NULL
;
1485 rmb
->param_modopt
= NULL
;
1486 rmb
->permissions
= NULL
;
1487 rmb
->mhandle
= mb
->mhandle
;
1494 mono_image_add_methodimpl (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
1496 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
1497 MonoDynamicTable
*table
;
1501 if (!mb
->override_method
)
1504 table
= &assembly
->tables
[MONO_TABLE_METHODIMPL
];
1506 alloc_table (table
, table
->rows
);
1507 values
= table
->values
+ table
->rows
* MONO_METHODIMPL_SIZE
;
1508 values
[MONO_METHODIMPL_CLASS
] = tb
->table_idx
;
1509 values
[MONO_METHODIMPL_BODY
] = MONO_METHODDEFORREF_METHODDEF
| (mb
->table_idx
<< MONO_METHODDEFORREF_BITS
);
1511 tok
= mono_image_create_token (assembly
, (MonoObject
*)mb
->override_method
, FALSE
, FALSE
);
1512 switch (mono_metadata_token_table (tok
)) {
1513 case MONO_TABLE_MEMBERREF
:
1514 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
1516 case MONO_TABLE_METHOD
:
1517 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
1520 g_assert_not_reached ();
1522 values
[MONO_METHODIMPL_DECLARATION
] = tok
;
1526 mono_image_get_method_info (MonoReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1528 MonoDynamicTable
*table
;
1530 ReflectionMethodBuilder rmb
;
1533 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
1535 mono_image_basic_method (&rmb
, assembly
);
1536 mb
->table_idx
= *rmb
.table_idx
;
1538 if (mb
->dll
) { /* It's a P/Invoke method */
1540 /* map CharSet values to on-disk values */
1541 int ncharset
= (mb
->charset
? (mb
->charset
- 1) * 2 : 0);
1542 int extra_flags
= mb
->extra_flags
;
1543 table
= &assembly
->tables
[MONO_TABLE_IMPLMAP
];
1545 alloc_table (table
, table
->rows
);
1546 values
= table
->values
+ table
->rows
* MONO_IMPLMAP_SIZE
;
1548 values
[MONO_IMPLMAP_FLAGS
] = (mb
->native_cc
<< 8) | ncharset
| extra_flags
;
1549 values
[MONO_IMPLMAP_MEMBER
] = (mb
->table_idx
<< 1) | 1; /* memberforwarded: method */
1551 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->dllentry
);
1553 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1554 moduleref
= string_heap_insert_mstring (&assembly
->sheap
, mb
->dll
);
1555 if (!(values
[MONO_IMPLMAP_SCOPE
] = find_index_in_table (assembly
, MONO_TABLE_MODULEREF
, MONO_MODULEREF_NAME
, moduleref
))) {
1556 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
1558 alloc_table (table
, table
->rows
);
1559 table
->values
[table
->rows
* MONO_MODULEREF_SIZE
+ MONO_MODULEREF_NAME
] = moduleref
;
1560 values
[MONO_IMPLMAP_SCOPE
] = table
->rows
;
1564 if (mb
->generic_params
) {
1565 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
1566 table
->rows
+= mono_array_length (mb
->generic_params
);
1567 alloc_table (table
, table
->rows
);
1568 for (i
= 0; i
< mono_array_length (mb
->generic_params
); ++i
) {
1569 guint32 owner
= MONO_TYPEORMETHOD_METHOD
| (mb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
1571 mono_image_get_generic_param_info (
1572 mono_array_get (mb
->generic_params
, gpointer
, i
), owner
, assembly
);
1579 mono_image_get_ctor_info (MonoDomain
*domain
, MonoReflectionCtorBuilder
*mb
, MonoDynamicImage
*assembly
)
1581 ReflectionMethodBuilder rmb
;
1583 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
1585 mono_image_basic_method (&rmb
, assembly
);
1586 mb
->table_idx
= *rmb
.table_idx
;
1590 type_get_fully_qualified_name (MonoType
*type
)
1592 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1596 type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
) {
1600 klass
= mono_class_from_mono_type (type
);
1602 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1603 ta
= klass
->image
->assembly
;
1604 if (ta
->dynamic
|| (ta
== ass
)) {
1605 if (klass
->generic_class
|| klass
->generic_container
)
1606 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1607 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_FULL_NAME
);
1609 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1612 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1615 #ifndef DISABLE_REFLECTION_EMIT
1617 fieldref_encode_signature (MonoDynamicImage
*assembly
, MonoType
*type
)
1622 if (!assembly
->save
)
1625 sigbuffer_init (&buf
, 32);
1627 sigbuffer_add_value (&buf
, 0x06);
1628 /* encode custom attributes before the type */
1629 /* FIXME: This should probably go in encode_type () */
1630 if (type
->num_mods
) {
1631 for (i
= 0; i
< type
->num_mods
; ++i
) {
1632 if (type
->modifiers
[i
].required
)
1633 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_REQD
);
1635 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_OPT
);
1636 sigbuffer_add_value (&buf
, type
->modifiers
[i
].token
);
1639 encode_type (assembly
, type
, &buf
);
1640 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1641 sigbuffer_free (&buf
);
1647 field_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
1652 sigbuffer_init (&buf
, 32);
1654 sigbuffer_add_value (&buf
, 0x06);
1655 encode_custom_modifiers (assembly
, fb
->modreq
, fb
->modopt
, &buf
);
1656 /* encode custom attributes before the type */
1657 encode_reflection_type (assembly
, (MonoReflectionType
*)fb
->type
, &buf
);
1658 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1659 sigbuffer_free (&buf
);
1664 encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
) {
1665 char blob_size
[64];
1666 char *b
= blob_size
;
1669 guint32 idx
= 0, len
= 0, dummy
= 0;
1671 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1672 guint32 fpa_double
[2];
1677 p
= buf
= g_malloc (64);
1679 *ret_type
= MONO_TYPE_CLASS
;
1681 box_val
= (char*)&dummy
;
1683 box_val
= ((char*)val
) + sizeof (MonoObject
);
1684 *ret_type
= val
->vtable
->klass
->byval_arg
.type
;
1687 switch (*ret_type
) {
1688 case MONO_TYPE_BOOLEAN
:
1693 case MONO_TYPE_CHAR
:
1710 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1711 fpa_p
= (guint32
*)box_val
;
1712 fpa_double
[0] = fpa_p
[1];
1713 fpa_double
[1] = fpa_p
[0];
1714 box_val
= (char*)fpa_double
;
1718 case MONO_TYPE_VALUETYPE
:
1719 if (val
->vtable
->klass
->enumtype
) {
1720 *ret_type
= mono_class_enum_basetype (val
->vtable
->klass
)->type
;
1723 g_error ("we can't encode valuetypes");
1724 case MONO_TYPE_CLASS
:
1726 case MONO_TYPE_STRING
: {
1727 MonoString
*str
= (MonoString
*)val
;
1728 /* there is no signature */
1729 len
= str
->length
* 2;
1730 mono_metadata_encode_value (len
, b
, &b
);
1731 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1733 char *swapped
= g_malloc (2 * mono_string_length (str
));
1734 const char *p
= (const char*)mono_string_chars (str
);
1736 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
1737 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
1741 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
1747 case MONO_TYPE_GENERICINST
:
1748 *ret_type
= val
->vtable
->klass
->generic_class
->container_class
->byval_arg
.type
;
1751 g_error ("we don't encode constant type 0x%02x yet", *ret_type
);
1754 /* there is no signature */
1755 mono_metadata_encode_value (len
, b
, &b
);
1756 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1757 idx
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
1758 swap_with_size (blob_size
, box_val
, len
, 1);
1759 mono_image_add_stream_data (&assembly
->blob
, blob_size
, len
);
1761 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, box_val
, len
);
1769 encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
) {
1774 sigbuffer_init (&buf
, 32);
1776 sigbuffer_add_value (&buf
, minfo
->type
);
1778 switch (minfo
->type
) {
1779 case MONO_NATIVE_BYVALTSTR
:
1780 case MONO_NATIVE_BYVALARRAY
:
1781 sigbuffer_add_value (&buf
, minfo
->count
);
1783 case MONO_NATIVE_LPARRAY
:
1784 if (minfo
->eltype
|| minfo
->has_size
) {
1785 sigbuffer_add_value (&buf
, minfo
->eltype
);
1786 if (minfo
->has_size
) {
1787 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? minfo
->param_num
: 0);
1788 sigbuffer_add_value (&buf
, minfo
->count
!= -1? minfo
->count
: 0);
1790 /* LAMESPEC: ElemMult is undocumented */
1791 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? 1: 0);
1795 case MONO_NATIVE_SAFEARRAY
:
1797 sigbuffer_add_value (&buf
, minfo
->eltype
);
1799 case MONO_NATIVE_CUSTOM
:
1801 str
= mono_string_to_utf8 (minfo
->guid
);
1803 sigbuffer_add_value (&buf
, len
);
1804 sigbuffer_add_mem (&buf
, str
, len
);
1807 sigbuffer_add_value (&buf
, 0);
1809 /* native type name */
1810 sigbuffer_add_value (&buf
, 0);
1811 /* custom marshaler type name */
1812 if (minfo
->marshaltype
|| minfo
->marshaltyperef
) {
1813 if (minfo
->marshaltyperef
)
1814 str
= type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType
*)minfo
->marshaltyperef
));
1816 str
= mono_string_to_utf8 (minfo
->marshaltype
);
1818 sigbuffer_add_value (&buf
, len
);
1819 sigbuffer_add_mem (&buf
, str
, len
);
1822 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1823 sigbuffer_add_value (&buf
, 0);
1825 if (minfo
->mcookie
) {
1826 str
= mono_string_to_utf8 (minfo
->mcookie
);
1828 sigbuffer_add_value (&buf
, len
);
1829 sigbuffer_add_mem (&buf
, str
, len
);
1832 sigbuffer_add_value (&buf
, 0);
1838 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1839 sigbuffer_free (&buf
);
1844 mono_image_get_field_info (MonoReflectionFieldBuilder
*fb
, MonoDynamicImage
*assembly
)
1846 MonoDynamicTable
*table
;
1849 /* maybe this fixup should be done in the C# code */
1850 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
)
1851 fb
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
1852 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
1853 fb
->table_idx
= table
->next_idx
++;
1854 g_hash_table_insert (assembly
->field_to_table_idx
, fb
->handle
, GUINT_TO_POINTER (fb
->table_idx
));
1855 values
= table
->values
+ fb
->table_idx
* MONO_FIELD_SIZE
;
1856 values
[MONO_FIELD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, fb
->name
);
1857 values
[MONO_FIELD_FLAGS
] = fb
->attrs
;
1858 values
[MONO_FIELD_SIGNATURE
] = field_encode_signature (assembly
, fb
);
1860 if (fb
->offset
!= -1) {
1861 table
= &assembly
->tables
[MONO_TABLE_FIELDLAYOUT
];
1863 alloc_table (table
, table
->rows
);
1864 values
= table
->values
+ table
->rows
* MONO_FIELD_LAYOUT_SIZE
;
1865 values
[MONO_FIELD_LAYOUT_FIELD
] = fb
->table_idx
;
1866 values
[MONO_FIELD_LAYOUT_OFFSET
] = fb
->offset
;
1868 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
) {
1869 guint32 field_type
= 0;
1870 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1872 alloc_table (table
, table
->rows
);
1873 values
= table
->values
+ table
->rows
* MONO_CONSTANT_SIZE
;
1874 values
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_FIEDDEF
| (fb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1875 values
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, fb
->def_value
, &field_type
);
1876 values
[MONO_CONSTANT_TYPE
] = field_type
;
1877 values
[MONO_CONSTANT_PADDING
] = 0;
1879 if (fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
1881 table
= &assembly
->tables
[MONO_TABLE_FIELDRVA
];
1883 alloc_table (table
, table
->rows
);
1884 values
= table
->values
+ table
->rows
* MONO_FIELD_RVA_SIZE
;
1885 values
[MONO_FIELD_RVA_FIELD
] = fb
->table_idx
;
1887 * We store it in the code section because it's simpler for now.
1890 if (mono_array_length (fb
->rva_data
) >= 10)
1891 stream_data_align (&assembly
->code
);
1892 rva_idx
= mono_image_add_stream_data (&assembly
->code
, mono_array_addr (fb
->rva_data
, char, 0), mono_array_length (fb
->rva_data
));
1894 rva_idx
= mono_image_add_stream_zero (&assembly
->code
, mono_class_value_size (fb
->handle
->parent
, NULL
));
1895 values
[MONO_FIELD_RVA_RVA
] = rva_idx
+ assembly
->text_rva
;
1897 if (fb
->marshal_info
) {
1898 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1900 alloc_table (table
, table
->rows
);
1901 values
= table
->values
+ table
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1902 values
[MONO_FIELD_MARSHAL_PARENT
] = (fb
->table_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_FIELDSREF
;
1903 values
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, fb
->marshal_info
);
1908 property_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionPropertyBuilder
*fb
)
1911 guint32 nparams
= 0;
1912 MonoReflectionMethodBuilder
*mb
= fb
->get_method
;
1913 MonoReflectionMethodBuilder
*smb
= fb
->set_method
;
1916 if (mb
&& mb
->parameters
)
1917 nparams
= mono_array_length (mb
->parameters
);
1918 if (!mb
&& smb
&& smb
->parameters
)
1919 nparams
= mono_array_length (smb
->parameters
) - 1;
1920 sigbuffer_init (&buf
, 32);
1921 sigbuffer_add_byte (&buf
, 0x08);
1922 sigbuffer_add_value (&buf
, nparams
);
1924 encode_reflection_type (assembly
, (MonoReflectionType
*)mb
->rtype
, &buf
);
1925 for (i
= 0; i
< nparams
; ++i
) {
1926 MonoReflectionType
*pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
1927 encode_reflection_type (assembly
, pt
, &buf
);
1929 } else if (smb
&& smb
->parameters
) {
1930 /* the property type is the last param */
1931 encode_reflection_type (assembly
, mono_array_get (smb
->parameters
, MonoReflectionType
*, nparams
), &buf
);
1932 for (i
= 0; i
< nparams
; ++i
) {
1933 MonoReflectionType
*pt
= mono_array_get (smb
->parameters
, MonoReflectionType
*, i
);
1934 encode_reflection_type (assembly
, pt
, &buf
);
1937 encode_reflection_type (assembly
, (MonoReflectionType
*)fb
->type
, &buf
);
1940 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1941 sigbuffer_free (&buf
);
1946 mono_image_get_property_info (MonoReflectionPropertyBuilder
*pb
, MonoDynamicImage
*assembly
)
1948 MonoDynamicTable
*table
;
1950 guint num_methods
= 0;
1954 * we need to set things in the following tables:
1955 * PROPERTYMAP (info already filled in _get_type_info ())
1956 * PROPERTY (rows already preallocated in _get_type_info ())
1957 * METHOD (method info already done with the generic method code)
1960 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
1961 pb
->table_idx
= table
->next_idx
++;
1962 values
= table
->values
+ pb
->table_idx
* MONO_PROPERTY_SIZE
;
1963 values
[MONO_PROPERTY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1964 values
[MONO_PROPERTY_FLAGS
] = pb
->attrs
;
1965 values
[MONO_PROPERTY_TYPE
] = property_encode_signature (assembly
, pb
);
1967 /* FIXME: we still don't handle 'other' methods */
1968 if (pb
->get_method
) num_methods
++;
1969 if (pb
->set_method
) num_methods
++;
1971 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
1972 table
->rows
+= num_methods
;
1973 alloc_table (table
, table
->rows
);
1975 if (pb
->get_method
) {
1976 semaidx
= table
->next_idx
++;
1977 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
1978 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_GETTER
;
1979 values
[MONO_METHOD_SEMA_METHOD
] = pb
->get_method
->table_idx
;
1980 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
1982 if (pb
->set_method
) {
1983 semaidx
= table
->next_idx
++;
1984 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
1985 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_SETTER
;
1986 values
[MONO_METHOD_SEMA_METHOD
] = pb
->set_method
->table_idx
;
1987 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
1992 mono_image_get_event_info (MonoReflectionEventBuilder
*eb
, MonoDynamicImage
*assembly
)
1994 MonoDynamicTable
*table
;
1996 guint num_methods
= 0;
2000 * we need to set things in the following tables:
2001 * EVENTMAP (info already filled in _get_type_info ())
2002 * EVENT (rows already preallocated in _get_type_info ())
2003 * METHOD (method info already done with the generic method code)
2006 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
2007 eb
->table_idx
= table
->next_idx
++;
2008 values
= table
->values
+ eb
->table_idx
* MONO_EVENT_SIZE
;
2009 values
[MONO_EVENT_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, eb
->name
);
2010 values
[MONO_EVENT_FLAGS
] = eb
->attrs
;
2011 values
[MONO_EVENT_TYPE
] = mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle (eb
->type
));
2014 * FIXME: we still don't handle 'other' methods
2016 if (eb
->add_method
) num_methods
++;
2017 if (eb
->remove_method
) num_methods
++;
2018 if (eb
->raise_method
) num_methods
++;
2020 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
2021 table
->rows
+= num_methods
;
2022 alloc_table (table
, table
->rows
);
2024 if (eb
->add_method
) {
2025 semaidx
= table
->next_idx
++;
2026 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2027 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_ADD_ON
;
2028 values
[MONO_METHOD_SEMA_METHOD
] = eb
->add_method
->table_idx
;
2029 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2031 if (eb
->remove_method
) {
2032 semaidx
= table
->next_idx
++;
2033 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2034 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_REMOVE_ON
;
2035 values
[MONO_METHOD_SEMA_METHOD
] = eb
->remove_method
->table_idx
;
2036 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2038 if (eb
->raise_method
) {
2039 semaidx
= table
->next_idx
++;
2040 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2041 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_FIRE
;
2042 values
[MONO_METHOD_SEMA_METHOD
] = eb
->raise_method
->table_idx
;
2043 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2048 encode_constraints (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2050 MonoDynamicTable
*table
;
2051 guint32 num_constraints
, i
;
2055 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
2056 num_constraints
= gparam
->iface_constraints
?
2057 mono_array_length (gparam
->iface_constraints
) : 0;
2058 table
->rows
+= num_constraints
;
2059 if (gparam
->base_type
)
2061 alloc_table (table
, table
->rows
);
2063 if (gparam
->base_type
) {
2064 table_idx
= table
->next_idx
++;
2065 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2067 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2068 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2069 assembly
, mono_reflection_type_get_handle (gparam
->base_type
));
2072 for (i
= 0; i
< num_constraints
; i
++) {
2073 MonoReflectionType
*constraint
= mono_array_get (
2074 gparam
->iface_constraints
, gpointer
, i
);
2076 table_idx
= table
->next_idx
++;
2077 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2079 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2080 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2081 assembly
, mono_reflection_type_get_handle (constraint
));
2086 mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2088 GenericParamTableEntry
*entry
;
2091 * The GenericParam table must be sorted according to the `owner' field.
2092 * We need to do this sorting prior to writing the GenericParamConstraint
2093 * table, since we have to use the final GenericParam table indices there
2094 * and they must also be sorted.
2097 entry
= g_new0 (GenericParamTableEntry
, 1);
2098 entry
->owner
= owner
;
2099 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2100 MOVING_GC_REGISTER (&entry
->gparam
);
2101 entry
->gparam
= gparam
;
2103 g_ptr_array_add (assembly
->gen_params
, entry
);
2107 write_generic_param_entry (MonoDynamicImage
*assembly
, GenericParamTableEntry
*entry
)
2109 MonoDynamicTable
*table
;
2110 MonoGenericParam
*param
;
2114 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
2115 table_idx
= table
->next_idx
++;
2116 values
= table
->values
+ table_idx
* MONO_GENERICPARAM_SIZE
;
2118 param
= mono_reflection_type_get_handle ((MonoReflectionType
*)entry
->gparam
)->data
.generic_param
;
2120 values
[MONO_GENERICPARAM_OWNER
] = entry
->owner
;
2121 values
[MONO_GENERICPARAM_FLAGS
] = entry
->gparam
->attrs
;
2122 values
[MONO_GENERICPARAM_NUMBER
] = mono_generic_param_num (param
);
2123 values
[MONO_GENERICPARAM_NAME
] = string_heap_insert (&assembly
->sheap
, mono_generic_param_info (param
)->name
);
2125 mono_image_add_cattrs (assembly
, table_idx
, MONO_CUSTOM_ATTR_GENERICPAR
, entry
->gparam
->cattrs
);
2127 encode_constraints (entry
->gparam
, table_idx
, assembly
);
2131 resolution_scope_from_image (MonoDynamicImage
*assembly
, MonoImage
*image
)
2133 MonoDynamicTable
*table
;
2136 guint32 cols
[MONO_ASSEMBLY_SIZE
];
2140 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, image
))))
2143 if (image
->assembly
->dynamic
&& (image
->assembly
== assembly
->image
.assembly
)) {
2144 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
2145 token
= table
->next_idx
++;
2147 alloc_table (table
, table
->rows
);
2148 values
= table
->values
+ token
* MONO_MODULEREF_SIZE
;
2149 values
[MONO_MODULEREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->module_name
);
2151 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2152 token
|= MONO_RESOLTION_SCOPE_MODULEREF
;
2153 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2158 if (image
->assembly
->dynamic
)
2160 memset (cols
, 0, sizeof (cols
));
2162 /* image->assembly->image is the manifest module */
2163 image
= image
->assembly
->image
;
2164 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_ASSEMBLY
], 0, cols
, MONO_ASSEMBLY_SIZE
);
2167 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLYREF
];
2168 token
= table
->next_idx
++;
2170 alloc_table (table
, table
->rows
);
2171 values
= table
->values
+ token
* MONO_ASSEMBLYREF_SIZE
;
2172 values
[MONO_ASSEMBLYREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->assembly_name
);
2173 values
[MONO_ASSEMBLYREF_MAJOR_VERSION
] = cols
[MONO_ASSEMBLY_MAJOR_VERSION
];
2174 values
[MONO_ASSEMBLYREF_MINOR_VERSION
] = cols
[MONO_ASSEMBLY_MINOR_VERSION
];
2175 values
[MONO_ASSEMBLYREF_BUILD_NUMBER
] = cols
[MONO_ASSEMBLY_BUILD_NUMBER
];
2176 values
[MONO_ASSEMBLYREF_REV_NUMBER
] = cols
[MONO_ASSEMBLY_REV_NUMBER
];
2177 values
[MONO_ASSEMBLYREF_FLAGS
] = 0;
2178 values
[MONO_ASSEMBLYREF_CULTURE
] = 0;
2179 values
[MONO_ASSEMBLYREF_HASH_VALUE
] = 0;
2181 if (strcmp ("", image
->assembly
->aname
.culture
)) {
2182 values
[MONO_ASSEMBLYREF_CULTURE
] = string_heap_insert (&assembly
->sheap
,
2183 image
->assembly
->aname
.culture
);
2186 if ((pubkey
= mono_image_get_public_key (image
, &publen
))) {
2187 guchar pubtoken
[9];
2189 mono_digest_get_public_token (pubtoken
+ 1, (guchar
*)pubkey
, publen
);
2190 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = mono_image_add_stream_data (&assembly
->blob
, (char*)pubtoken
, 9);
2192 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = 0;
2194 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2195 token
|= MONO_RESOLTION_SCOPE_ASSEMBLYREF
;
2196 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2201 create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
)
2203 MonoDynamicTable
*table
;
2208 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
))))
2211 sigbuffer_init (&buf
, 32);
2212 switch (type
->type
) {
2213 case MONO_TYPE_FNPTR
:
2215 case MONO_TYPE_SZARRAY
:
2216 case MONO_TYPE_ARRAY
:
2218 case MONO_TYPE_MVAR
:
2219 case MONO_TYPE_GENERICINST
:
2220 encode_type (assembly
, type
, &buf
);
2222 case MONO_TYPE_CLASS
:
2223 case MONO_TYPE_VALUETYPE
: {
2224 MonoClass
*k
= mono_class_from_mono_type (type
);
2225 if (!k
|| !k
->generic_container
) {
2226 sigbuffer_free (&buf
);
2229 encode_type (assembly
, type
, &buf
);
2233 sigbuffer_free (&buf
);
2237 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2238 if (assembly
->save
) {
2239 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2240 alloc_table (table
, table
->rows
+ 1);
2241 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2242 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2244 sigbuffer_free (&buf
);
2246 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2247 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
2253 mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
)
2255 MonoDynamicTable
*table
;
2257 guint32 token
, scope
, enclosing
;
2260 /* if the type requires a typespec, we must try that first*/
2261 if (try_typespec
&& (token
= create_typespec (assembly
, type
)))
2263 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typeref
, type
));
2266 klass
= mono_class_from_mono_type (type
);
2268 klass
= mono_class_from_mono_type (type
);
2271 * If it's in the same module and not a generic type parameter:
2273 if ((klass
->image
== &assembly
->image
) && (type
->type
!= MONO_TYPE_VAR
) &&
2274 (type
->type
!= MONO_TYPE_MVAR
)) {
2275 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
2276 token
= MONO_TYPEDEFORREF_TYPEDEF
| (tb
->table_idx
<< MONO_TYPEDEFORREF_BITS
);
2277 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), klass
->reflection_info
);
2281 if (klass
->nested_in
) {
2282 enclosing
= mono_image_typedef_or_ref_full (assembly
, &klass
->nested_in
->byval_arg
, FALSE
);
2283 /* get the typeref idx of the enclosing type */
2284 enclosing
>>= MONO_TYPEDEFORREF_BITS
;
2285 scope
= (enclosing
<< MONO_RESOLTION_SCOPE_BITS
) | MONO_RESOLTION_SCOPE_TYPEREF
;
2287 scope
= resolution_scope_from_image (assembly
, klass
->image
);
2289 table
= &assembly
->tables
[MONO_TABLE_TYPEREF
];
2290 if (assembly
->save
) {
2291 alloc_table (table
, table
->rows
+ 1);
2292 values
= table
->values
+ table
->next_idx
* MONO_TYPEREF_SIZE
;
2293 values
[MONO_TYPEREF_SCOPE
] = scope
;
2294 values
[MONO_TYPEREF_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
2295 values
[MONO_TYPEREF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
2297 token
= MONO_TYPEDEFORREF_TYPEREF
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
); /* typeref */
2298 g_hash_table_insert (assembly
->typeref
, type
, GUINT_TO_POINTER(token
));
2300 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), klass
->reflection_info
);
2305 * Despite the name, we handle also TypeSpec (with the above helper).
2308 mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
)
2310 return mono_image_typedef_or_ref_full (assembly
, type
, TRUE
);
2313 #ifndef DISABLE_REFLECTION_EMIT
2315 * Insert a memberef row into the metadata: the token that point to the memberref
2316 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2317 * mono_image_get_fieldref_token()).
2318 * The sig param is an index to an already built signature.
2321 mono_image_get_memberref_token (MonoDynamicImage
*assembly
, MonoType
*type
, const char *name
, guint32 sig
)
2323 MonoDynamicTable
*table
;
2325 guint32 token
, pclass
;
2328 parent
= mono_image_typedef_or_ref (assembly
, type
);
2329 switch (parent
& MONO_TYPEDEFORREF_MASK
) {
2330 case MONO_TYPEDEFORREF_TYPEREF
:
2331 pclass
= MONO_MEMBERREF_PARENT_TYPEREF
;
2333 case MONO_TYPEDEFORREF_TYPESPEC
:
2334 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2336 case MONO_TYPEDEFORREF_TYPEDEF
:
2337 pclass
= MONO_MEMBERREF_PARENT_TYPEDEF
;
2340 g_warning ("unknown typeref or def token 0x%08x for %s", parent
, name
);
2343 /* extract the index */
2344 parent
>>= MONO_TYPEDEFORREF_BITS
;
2346 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2348 if (assembly
->save
) {
2349 alloc_table (table
, table
->rows
+ 1);
2350 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2351 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2352 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2353 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2356 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2363 mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
)
2366 MonoMethodSignature
*sig
;
2368 create_typespec
= create_typespec
&& method
->is_generic
&& method
->klass
->image
!= &assembly
->image
;
2370 if (create_typespec
) {
2371 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1)));
2376 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2377 if (token
&& !create_typespec
)
2380 g_assert (!method
->is_inflated
);
2383 * A methodref signature can't contain an unmanaged calling convention.
2385 sig
= mono_metadata_signature_dup (mono_method_signature (method
));
2386 if ((sig
->call_convention
!= MONO_CALL_DEFAULT
) && (sig
->call_convention
!= MONO_CALL_VARARG
))
2387 sig
->call_convention
= MONO_CALL_DEFAULT
;
2388 token
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
,
2389 method
->name
, method_encode_signature (assembly
, sig
));
2391 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2394 if (create_typespec
) {
2395 MonoDynamicTable
*table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2396 g_assert (mono_metadata_token_table (token
) == MONO_TABLE_MEMBERREF
);
2397 token
= (mono_metadata_token_index (token
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2399 if (assembly
->save
) {
2402 alloc_table (table
, table
->rows
+ 1);
2403 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2404 values
[MONO_METHODSPEC_METHOD
] = token
;
2405 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_sig (assembly
, &mono_method_get_generic_container (method
)->context
);
2408 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2410 /*methodspec and memberef tokens are diferent, */
2411 g_hash_table_insert (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1), GUINT_TO_POINTER (token
));
2418 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
)
2421 ReflectionMethodBuilder rmb
;
2424 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2428 name
= mono_string_to_utf8 (method
->name
);
2429 reflection_methodbuilder_from_method_builder (&rmb
, method
);
2432 * A methodref signature can't contain an unmanaged calling convention.
2433 * Since some flags are encoded as part of call_conv, we need to check against it.
2435 if ((rmb
.call_conv
& ~0x60) != MONO_CALL_DEFAULT
&& (rmb
.call_conv
& ~0x60) != MONO_CALL_VARARG
)
2436 rmb
.call_conv
= (rmb
.call_conv
& 0x60) | MONO_CALL_DEFAULT
;
2437 token
= mono_image_get_memberref_token (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)rmb
.type
),
2438 name
, method_builder_encode_signature (assembly
, &rmb
));
2441 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2446 mono_image_get_varargs_method_token (MonoDynamicImage
*assembly
, guint32 original
,
2447 const gchar
*name
, guint32 sig
)
2449 MonoDynamicTable
*table
;
2453 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2455 if (assembly
->save
) {
2456 alloc_table (table
, table
->rows
+ 1);
2457 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2458 values
[MONO_MEMBERREF_CLASS
] = original
;
2459 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2460 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2463 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2470 encode_generic_method_definition_sig (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2474 guint32 nparams
= mono_array_length (mb
->generic_params
);
2477 if (!assembly
->save
)
2480 sigbuffer_init (&buf
, 32);
2482 sigbuffer_add_value (&buf
, 0xa);
2483 sigbuffer_add_value (&buf
, nparams
);
2485 for (i
= 0; i
< nparams
; i
++) {
2486 sigbuffer_add_value (&buf
, MONO_TYPE_MVAR
);
2487 sigbuffer_add_value (&buf
, i
);
2490 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2491 sigbuffer_free (&buf
);
2496 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2498 MonoDynamicTable
*table
;
2500 guint32 token
, mtoken
= 0;
2502 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->methodspec
, mb
));
2506 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2508 mtoken
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2509 switch (mono_metadata_token_table (mtoken
)) {
2510 case MONO_TABLE_MEMBERREF
:
2511 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2513 case MONO_TABLE_METHOD
:
2514 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2517 g_assert_not_reached ();
2520 if (assembly
->save
) {
2521 alloc_table (table
, table
->rows
+ 1);
2522 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2523 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2524 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_definition_sig (assembly
, mb
);
2527 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2530 mono_g_hash_table_insert (assembly
->methodspec
, mb
, GUINT_TO_POINTER(token
));
2535 mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
)
2539 if (mb
->generic_params
&& create_methodspec
)
2540 return mono_image_get_methodspec_token_for_generic_method_definition (assembly
, mb
);
2542 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, mb
));
2546 token
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2547 g_hash_table_insert (assembly
->handleref
, mb
, GUINT_TO_POINTER(token
));
2552 mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*mb
)
2555 ReflectionMethodBuilder rmb
;
2558 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, mb
));
2562 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
2564 name
= mono_string_to_utf8 (rmb
.name
);
2565 token
= mono_image_get_memberref_token (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)rmb
.type
),
2566 name
, method_builder_encode_signature (assembly
, &rmb
));
2569 g_hash_table_insert (assembly
->handleref
, mb
, GUINT_TO_POINTER(token
));
2575 is_field_on_inst (MonoClassField
*field
)
2577 return (field
->parent
->generic_class
&& field
->parent
->generic_class
->is_dynamic
&& ((MonoDynamicGenericClass
*)field
->parent
->generic_class
)->fields
);
2581 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2584 get_field_on_inst_generic_type (MonoClassField
*field
)
2586 MonoDynamicGenericClass
*dgclass
;
2589 g_assert (is_field_on_inst (field
));
2591 dgclass
= (MonoDynamicGenericClass
*)field
->parent
->generic_class
;
2592 field_index
= field
- dgclass
->fields
;
2594 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
2595 return dgclass
->field_generic_types
[field_index
];
2598 #ifndef DISABLE_REFLECTION_EMIT
2600 mono_image_get_fieldref_token (MonoDynamicImage
*assembly
, MonoReflectionField
*f
)
2604 MonoClassField
*field
;
2606 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, f
));
2609 g_assert (f
->field
->parent
);
2612 if (field
->parent
->generic_class
&& field
->parent
->generic_class
->container_class
&& field
->parent
->generic_class
->container_class
->fields
) {
2613 int index
= field
- field
->parent
->fields
;
2614 type
= field
->parent
->generic_class
->container_class
->fields
[index
].type
;
2616 if (is_field_on_inst (f
->field
))
2617 type
= get_field_on_inst_generic_type (f
->field
);
2619 type
= f
->field
->type
;
2621 token
= mono_image_get_memberref_token (assembly
, &f
->field
->parent
->byval_arg
,
2622 mono_field_get_name (f
->field
),
2623 fieldref_encode_signature (assembly
, type
));
2624 g_hash_table_insert (assembly
->handleref
, f
, GUINT_TO_POINTER(token
));
2629 mono_image_get_field_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionFieldOnTypeBuilderInst
*f
)
2633 MonoGenericClass
*gclass
;
2634 MonoDynamicGenericClass
*dgclass
;
2635 MonoReflectionFieldBuilder
*fb
= f
->fb
;
2639 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, f
));
2642 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)f
->inst
);
2643 klass
= mono_class_from_mono_type (type
);
2644 gclass
= type
->data
.generic_class
;
2645 g_assert (gclass
->is_dynamic
);
2646 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2648 name
= mono_string_to_utf8 (fb
->name
);
2649 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
,
2650 field_encode_signature (assembly
, fb
));
2652 g_hash_table_insert (assembly
->handleref
, f
, GUINT_TO_POINTER (token
));
2657 mono_image_get_ctor_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionCtorOnTypeBuilderInst
*c
, gboolean create_methodspec
)
2661 MonoGenericClass
*gclass
;
2662 MonoDynamicGenericClass
*dgclass
;
2663 MonoReflectionCtorBuilder
*cb
= c
->cb
;
2664 ReflectionMethodBuilder rmb
;
2668 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2670 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, c
));
2673 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)c
->inst
);
2674 klass
= mono_class_from_mono_type (type
);
2675 gclass
= type
->data
.generic_class
;
2676 g_assert (gclass
->is_dynamic
);
2677 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2679 reflection_methodbuilder_from_ctor_builder (&rmb
, cb
);
2681 name
= mono_string_to_utf8 (rmb
.name
);
2683 sig
= method_builder_encode_signature (assembly
, &rmb
);
2685 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2688 g_hash_table_insert (assembly
->handleref
, c
, GUINT_TO_POINTER (token
));
2693 mono_image_get_method_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionMethodOnTypeBuilderInst
*m
, gboolean create_methodspec
)
2697 MonoGenericClass
*gclass
;
2698 MonoReflectionMethodBuilder
*mb
= m
->mb
;
2699 ReflectionMethodBuilder rmb
;
2703 if (create_methodspec
&& mb
->generic_params
)
2705 g_assert_not_reached ();
2707 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, m
));
2710 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
);
2711 klass
= mono_class_from_mono_type (type
);
2712 gclass
= type
->data
.generic_class
;
2713 g_assert (gclass
->is_dynamic
);
2715 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
2717 name
= mono_string_to_utf8 (rmb
.name
);
2719 sig
= method_builder_encode_signature (assembly
, &rmb
);
2721 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2724 g_hash_table_insert (assembly
->handleref
, m
, GUINT_TO_POINTER (token
));
2729 encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
)
2733 guint32 nparams
= context
->method_inst
->type_argc
;
2736 if (!assembly
->save
)
2739 sigbuffer_init (&buf
, 32);
2741 * FIXME: vararg, explicit_this, differenc call_conv values...
2743 sigbuffer_add_value (&buf
, 0xa); /* FIXME FIXME FIXME */
2744 sigbuffer_add_value (&buf
, nparams
);
2746 for (i
= 0; i
< nparams
; i
++)
2747 encode_type (assembly
, context
->method_inst
->type_argv
[i
], &buf
);
2749 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2750 sigbuffer_free (&buf
);
2755 method_encode_methodspec (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2757 MonoDynamicTable
*table
;
2759 guint32 token
, mtoken
= 0, sig
;
2760 MonoMethodInflated
*imethod
;
2761 MonoMethod
*declaring
;
2763 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2765 g_assert (method
->is_inflated
);
2766 imethod
= (MonoMethodInflated
*) method
;
2767 declaring
= imethod
->declaring
;
2769 sig
= method_encode_signature (assembly
, mono_method_signature (declaring
));
2770 mtoken
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
, declaring
->name
, sig
);
2772 if (!mono_method_signature (declaring
)->generic_param_count
)
2775 switch (mono_metadata_token_table (mtoken
)) {
2776 case MONO_TABLE_MEMBERREF
:
2777 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2779 case MONO_TABLE_METHOD
:
2780 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2783 g_assert_not_reached ();
2786 sig
= encode_generic_method_sig (assembly
, mono_method_get_context (method
));
2788 if (assembly
->save
) {
2789 alloc_table (table
, table
->rows
+ 1);
2790 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2791 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2792 values
[MONO_METHODSPEC_SIGNATURE
] = sig
;
2795 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2802 mono_image_get_methodspec_token (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2804 MonoMethodInflated
*imethod
;
2807 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2811 g_assert (method
->is_inflated
);
2812 imethod
= (MonoMethodInflated
*) method
;
2814 if (mono_method_signature (imethod
->declaring
)->generic_param_count
) {
2815 token
= method_encode_methodspec (assembly
, method
);
2817 guint32 sig
= method_encode_signature (
2818 assembly
, mono_method_signature (imethod
->declaring
));
2819 token
= mono_image_get_memberref_token (
2820 assembly
, &method
->klass
->byval_arg
, method
->name
, sig
);
2823 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2828 mono_image_get_inflated_method_token (MonoDynamicImage
*assembly
, MonoMethod
*m
)
2830 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) m
;
2833 sig
= method_encode_signature (assembly
, mono_method_signature (imethod
->declaring
));
2834 token
= mono_image_get_memberref_token (
2835 assembly
, &m
->klass
->byval_arg
, m
->name
, sig
);
2841 create_generic_typespec (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
)
2843 MonoDynamicTable
*table
;
2852 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2853 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2854 * Because of this, we must not insert it into the `typeref' hash table.
2856 type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
);
2857 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
));
2861 sigbuffer_init (&buf
, 32);
2863 g_assert (tb
->generic_params
);
2864 klass
= mono_class_from_mono_type (type
);
2866 if (tb
->generic_container
)
2867 mono_reflection_create_generic_class (tb
);
2869 sigbuffer_add_value (&buf
, MONO_TYPE_GENERICINST
);
2870 g_assert (klass
->generic_container
);
2871 sigbuffer_add_value (&buf
, klass
->byval_arg
.type
);
2872 sigbuffer_add_value (&buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
2874 count
= mono_array_length (tb
->generic_params
);
2875 sigbuffer_add_value (&buf
, count
);
2876 for (i
= 0; i
< count
; i
++) {
2877 MonoReflectionGenericParam
*gparam
;
2879 gparam
= mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
);
2881 encode_type (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
), &buf
);
2884 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2886 if (assembly
->save
) {
2887 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2888 alloc_table (table
, table
->rows
+ 1);
2889 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2890 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2892 sigbuffer_free (&buf
);
2894 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2895 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
2901 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2904 add_custom_modifiers (MonoDynamicImage
*assembly
, MonoType
*type
, MonoArray
*modreq
, MonoArray
*modopt
)
2906 int i
, count
, len
, pos
;
2911 count
+= mono_array_length (modreq
);
2913 count
+= mono_array_length (modopt
);
2916 return mono_metadata_type_dup (NULL
, type
);
2918 len
= sizeof (MonoType
) + ((gint32
)count
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoCustomMod
);
2920 memcpy (t
, type
, sizeof (MonoType
));
2922 t
->num_mods
= count
;
2925 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
2926 MonoType
*mod
= mono_type_array_get_and_resolve (modreq
, i
);
2927 t
->modifiers
[pos
].required
= 1;
2928 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
);
2933 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
2934 MonoType
*mod
= mono_type_array_get_and_resolve (modopt
, i
);
2935 t
->modifiers
[pos
].required
= 0;
2936 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
);
2945 mono_image_get_generic_field_token (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
2947 MonoDynamicTable
*table
;
2949 MonoType
*custom
= NULL
;
2951 guint32 token
, pclass
, parent
, sig
;
2954 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, fb
));
2958 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle (fb
->typeb
));
2959 name
= mono_string_to_utf8 (fb
->name
);
2961 /* fb->type does not include the custom modifiers */
2962 /* FIXME: We should do this in one place when a fieldbuilder is created */
2963 if (fb
->modreq
|| fb
->modopt
) {
2964 custom
= add_custom_modifiers (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
), fb
->modreq
, fb
->modopt
);
2965 sig
= fieldref_encode_signature (assembly
, custom
);
2968 sig
= fieldref_encode_signature (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
));
2971 parent
= create_generic_typespec (assembly
, (MonoReflectionTypeBuilder
*) fb
->typeb
);
2972 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_TYPEDEFORREF_TYPESPEC
);
2974 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2975 parent
>>= MONO_TYPEDEFORREF_BITS
;
2977 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2979 if (assembly
->save
) {
2980 alloc_table (table
, table
->rows
+ 1);
2981 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2982 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2983 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2984 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2987 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2989 g_hash_table_insert (assembly
->handleref
, fb
, GUINT_TO_POINTER(token
));
2995 mono_reflection_encode_sighelper (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
3002 if (!assembly
->save
)
3005 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
3006 g_assert (helper
->type
== 2);
3008 if (helper
->arguments
)
3009 nargs
= mono_array_length (helper
->arguments
);
3013 size
= 10 + (nargs
* 10);
3015 sigbuffer_init (&buf
, 32);
3017 /* Encode calling convention */
3018 /* Change Any to Standard */
3019 if ((helper
->call_conv
& 0x03) == 0x03)
3020 helper
->call_conv
= 0x01;
3021 /* explicit_this implies has_this */
3022 if (helper
->call_conv
& 0x40)
3023 helper
->call_conv
&= 0x20;
3025 if (helper
->call_conv
== 0) { /* Unmanaged */
3026 idx
= helper
->unmanaged_call_conv
- 1;
3029 idx
= helper
->call_conv
& 0x60; /* has_this + explicit_this */
3030 if (helper
->call_conv
& 0x02) /* varargs */
3034 sigbuffer_add_byte (&buf
, idx
);
3035 sigbuffer_add_value (&buf
, nargs
);
3036 encode_reflection_type (assembly
, helper
->return_type
, &buf
);
3037 for (i
= 0; i
< nargs
; ++i
) {
3038 MonoArray
*modreqs
= NULL
;
3039 MonoArray
*modopts
= NULL
;
3040 MonoReflectionType
*pt
;
3042 if (helper
->modreqs
&& (i
< mono_array_length (helper
->modreqs
)))
3043 modreqs
= mono_array_get (helper
->modreqs
, MonoArray
*, i
);
3044 if (helper
->modopts
&& (i
< mono_array_length (helper
->modopts
)))
3045 modopts
= mono_array_get (helper
->modopts
, MonoArray
*, i
);
3047 encode_custom_modifiers (assembly
, modreqs
, modopts
, &buf
);
3048 pt
= mono_array_get (helper
->arguments
, MonoReflectionType
*, i
);
3049 encode_reflection_type (assembly
, pt
, &buf
);
3051 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3052 sigbuffer_free (&buf
);
3058 mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
3061 MonoDynamicTable
*table
;
3064 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
3065 idx
= table
->next_idx
++;
3067 alloc_table (table
, table
->rows
);
3068 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
3070 values
[MONO_STAND_ALONE_SIGNATURE
] =
3071 mono_reflection_encode_sighelper (assembly
, helper
);
3077 reflection_cc_to_file (int call_conv
) {
3078 switch (call_conv
& 0x3) {
3080 case 1: return MONO_CALL_DEFAULT
;
3081 case 2: return MONO_CALL_VARARG
;
3083 g_assert_not_reached ();
3087 #endif /* !DISABLE_REFLECTION_EMIT */
3091 MonoMethodSignature
*sig
;
3096 #ifndef DISABLE_REFLECTION_EMIT
3098 mono_image_get_array_token (MonoDynamicImage
*assembly
, MonoReflectionArrayMethod
*m
)
3103 MonoMethodSignature
*sig
;
3107 name
= mono_string_to_utf8 (m
->name
);
3108 nparams
= mono_array_length (m
->parameters
);
3109 sig
= g_malloc0 (sizeof (MonoMethodSignature
) + sizeof (MonoType
*) * nparams
);
3111 sig
->sentinelpos
= -1;
3112 sig
->call_convention
= reflection_cc_to_file (m
->call_conv
);
3113 sig
->param_count
= nparams
;
3114 sig
->ret
= m
->ret
? mono_reflection_type_get_handle (m
->ret
): &mono_defaults
.void_class
->byval_arg
;
3115 mtype
= mono_reflection_type_get_handle (m
->parent
);
3116 for (i
= 0; i
< nparams
; ++i
)
3117 sig
->params
[i
] = mono_type_array_get_and_resolve (m
->parameters
, i
);
3119 for (tmp
= assembly
->array_methods
; tmp
; tmp
= tmp
->next
) {
3121 if (strcmp (name
, am
->name
) == 0 &&
3122 mono_metadata_type_equal (am
->parent
, mtype
) &&
3123 mono_metadata_signature_equal (am
->sig
, sig
)) {
3126 m
->table_idx
= am
->token
& 0xffffff;
3130 am
= g_new0 (ArrayMethod
, 1);
3134 am
->token
= mono_image_get_memberref_token (assembly
, am
->parent
, name
,
3135 method_encode_signature (assembly
, sig
));
3136 assembly
->array_methods
= g_list_prepend (assembly
->array_methods
, am
);
3137 m
->table_idx
= am
->token
& 0xffffff;
3143 * Insert into the metadata tables all the info about the TypeBuilder tb.
3144 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3147 mono_image_get_type_info (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
, MonoDynamicImage
*assembly
)
3149 MonoDynamicTable
*table
;
3151 int i
, is_object
= 0, is_system
= 0;
3154 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
3155 values
= table
->values
+ tb
->table_idx
* MONO_TYPEDEF_SIZE
;
3156 values
[MONO_TYPEDEF_FLAGS
] = tb
->attrs
;
3157 n
= mono_string_to_utf8 (tb
->name
);
3158 if (strcmp (n
, "Object") == 0)
3160 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, n
);
3162 n
= mono_string_to_utf8 (tb
->nspace
);
3163 if (strcmp (n
, "System") == 0)
3165 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, n
);
3167 if (tb
->parent
&& !(is_system
&& is_object
) &&
3168 !(tb
->attrs
& TYPE_ATTRIBUTE_INTERFACE
)) { /* interfaces don't have a parent */
3169 values
[MONO_TYPEDEF_EXTENDS
] = mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle ((MonoReflectionType
*)tb
->parent
));
3171 values
[MONO_TYPEDEF_EXTENDS
] = 0;
3173 values
[MONO_TYPEDEF_FIELD_LIST
] = assembly
->tables
[MONO_TABLE_FIELD
].next_idx
;
3174 values
[MONO_TYPEDEF_METHOD_LIST
] = assembly
->tables
[MONO_TABLE_METHOD
].next_idx
;
3177 * if we have explicitlayout or sequentiallayouts, output data in the
3178 * ClassLayout table.
3180 if (((tb
->attrs
& TYPE_ATTRIBUTE_LAYOUT_MASK
) != TYPE_ATTRIBUTE_AUTO_LAYOUT
) &&
3181 ((tb
->class_size
> 0) || (tb
->packing_size
> 0))) {
3182 table
= &assembly
->tables
[MONO_TABLE_CLASSLAYOUT
];
3184 alloc_table (table
, table
->rows
);
3185 values
= table
->values
+ table
->rows
* MONO_CLASS_LAYOUT_SIZE
;
3186 values
[MONO_CLASS_LAYOUT_PARENT
] = tb
->table_idx
;
3187 values
[MONO_CLASS_LAYOUT_CLASS_SIZE
] = tb
->class_size
;
3188 values
[MONO_CLASS_LAYOUT_PACKING_SIZE
] = tb
->packing_size
;
3191 /* handle interfaces */
3192 if (tb
->interfaces
) {
3193 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3195 table
->rows
+= mono_array_length (tb
->interfaces
);
3196 alloc_table (table
, table
->rows
);
3197 values
= table
->values
+ (i
+ 1) * MONO_INTERFACEIMPL_SIZE
;
3198 for (i
= 0; i
< mono_array_length (tb
->interfaces
); ++i
) {
3199 MonoReflectionType
* iface
= (MonoReflectionType
*) mono_array_get (tb
->interfaces
, gpointer
, i
);
3200 values
[MONO_INTERFACEIMPL_CLASS
] = tb
->table_idx
;
3201 values
[MONO_INTERFACEIMPL_INTERFACE
] = mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle (iface
));
3202 values
+= MONO_INTERFACEIMPL_SIZE
;
3208 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
3209 table
->rows
+= tb
->num_fields
;
3210 alloc_table (table
, table
->rows
);
3211 for (i
= 0; i
< tb
->num_fields
; ++i
)
3212 mono_image_get_field_info (
3213 mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
3216 /* handle constructors */
3218 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3219 table
->rows
+= mono_array_length (tb
->ctors
);
3220 alloc_table (table
, table
->rows
);
3221 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
)
3222 mono_image_get_ctor_info (domain
,
3223 mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
), assembly
);
3226 /* handle methods */
3228 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3229 table
->rows
+= tb
->num_methods
;
3230 alloc_table (table
, table
->rows
);
3231 for (i
= 0; i
< tb
->num_methods
; ++i
)
3232 mono_image_get_method_info (
3233 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
3236 /* Do the same with properties etc.. */
3237 if (tb
->events
&& mono_array_length (tb
->events
)) {
3238 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
3239 table
->rows
+= mono_array_length (tb
->events
);
3240 alloc_table (table
, table
->rows
);
3241 table
= &assembly
->tables
[MONO_TABLE_EVENTMAP
];
3243 alloc_table (table
, table
->rows
);
3244 values
= table
->values
+ table
->rows
* MONO_EVENT_MAP_SIZE
;
3245 values
[MONO_EVENT_MAP_PARENT
] = tb
->table_idx
;
3246 values
[MONO_EVENT_MAP_EVENTLIST
] = assembly
->tables
[MONO_TABLE_EVENT
].next_idx
;
3247 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
)
3248 mono_image_get_event_info (
3249 mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
), assembly
);
3251 if (tb
->properties
&& mono_array_length (tb
->properties
)) {
3252 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
3253 table
->rows
+= mono_array_length (tb
->properties
);
3254 alloc_table (table
, table
->rows
);
3255 table
= &assembly
->tables
[MONO_TABLE_PROPERTYMAP
];
3257 alloc_table (table
, table
->rows
);
3258 values
= table
->values
+ table
->rows
* MONO_PROPERTY_MAP_SIZE
;
3259 values
[MONO_PROPERTY_MAP_PARENT
] = tb
->table_idx
;
3260 values
[MONO_PROPERTY_MAP_PROPERTY_LIST
] = assembly
->tables
[MONO_TABLE_PROPERTY
].next_idx
;
3261 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
)
3262 mono_image_get_property_info (
3263 mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
), assembly
);
3266 /* handle generic parameters */
3267 if (tb
->generic_params
) {
3268 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
3269 table
->rows
+= mono_array_length (tb
->generic_params
);
3270 alloc_table (table
, table
->rows
);
3271 for (i
= 0; i
< mono_array_length (tb
->generic_params
); ++i
) {
3272 guint32 owner
= MONO_TYPEORMETHOD_TYPE
| (tb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
3274 mono_image_get_generic_param_info (
3275 mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
), owner
, assembly
);
3279 mono_image_add_decl_security (assembly
,
3280 mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
), tb
->permissions
);
3283 MonoDynamicTable
*ntable
;
3285 ntable
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3286 ntable
->rows
+= mono_array_length (tb
->subtypes
);
3287 alloc_table (ntable
, ntable
->rows
);
3288 values
= ntable
->values
+ ntable
->next_idx
* MONO_NESTED_CLASS_SIZE
;
3290 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
3291 MonoReflectionTypeBuilder
*subtype
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3293 values
[MONO_NESTED_CLASS_NESTED
] = subtype
->table_idx
;
3294 values
[MONO_NESTED_CLASS_ENCLOSING
] = tb
->table_idx
;
3295 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3296 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3297 mono_string_to_utf8 (tb->name), tb->table_idx,
3298 ntable->next_idx, ntable->rows);*/
3299 values
+= MONO_NESTED_CLASS_SIZE
;
3306 collect_types (GPtrArray
*types
, MonoReflectionTypeBuilder
*type
)
3310 g_ptr_array_add (types
, type
); /* FIXME: GC object added to unmanaged memory */
3312 if (!type
->subtypes
)
3315 for (i
= 0; i
< mono_array_length (type
->subtypes
); ++i
) {
3316 MonoReflectionTypeBuilder
*subtype
= mono_array_get (type
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3317 collect_types (types
, subtype
);
3322 compare_types_by_table_idx (MonoReflectionTypeBuilder
**type1
, MonoReflectionTypeBuilder
**type2
)
3324 if ((*type1
)->table_idx
< (*type2
)->table_idx
)
3327 if ((*type1
)->table_idx
> (*type2
)->table_idx
)
3334 params_add_cattrs (MonoDynamicImage
*assembly
, MonoArray
*pinfo
) {
3339 for (i
= 0; i
< mono_array_length (pinfo
); ++i
) {
3340 MonoReflectionParamBuilder
*pb
;
3341 pb
= mono_array_get (pinfo
, MonoReflectionParamBuilder
*, i
);
3344 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PARAMDEF
, pb
->cattrs
);
3349 type_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
) {
3352 mono_image_add_cattrs (assembly
, tb
->table_idx
, MONO_CUSTOM_ATTR_TYPEDEF
, tb
->cattrs
);
3354 for (i
= 0; i
< tb
->num_fields
; ++i
) {
3355 MonoReflectionFieldBuilder
* fb
;
3356 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
);
3357 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3361 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
) {
3362 MonoReflectionEventBuilder
* eb
;
3363 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
3364 mono_image_add_cattrs (assembly
, eb
->table_idx
, MONO_CUSTOM_ATTR_EVENT
, eb
->cattrs
);
3367 if (tb
->properties
) {
3368 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
) {
3369 MonoReflectionPropertyBuilder
* pb
;
3370 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
3371 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PROPERTY
, pb
->cattrs
);
3375 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
3376 MonoReflectionCtorBuilder
* cb
;
3377 cb
= mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
);
3378 mono_image_add_cattrs (assembly
, cb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, cb
->cattrs
);
3379 params_add_cattrs (assembly
, cb
->pinfo
);
3384 for (i
= 0; i
< tb
->num_methods
; ++i
) {
3385 MonoReflectionMethodBuilder
* mb
;
3386 mb
= mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
3387 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3388 params_add_cattrs (assembly
, mb
->pinfo
);
3393 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3394 type_add_cattrs (assembly
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
));
3399 module_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionModuleBuilder
*moduleb
)
3403 mono_image_add_cattrs (assembly
, moduleb
->table_idx
, MONO_CUSTOM_ATTR_MODULE
, moduleb
->cattrs
);
3405 if (moduleb
->global_methods
) {
3406 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
3407 MonoReflectionMethodBuilder
* mb
= mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
3408 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3409 params_add_cattrs (assembly
, mb
->pinfo
);
3413 if (moduleb
->global_fields
) {
3414 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
) {
3415 MonoReflectionFieldBuilder
*fb
= mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
);
3416 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3420 if (moduleb
->types
) {
3421 for (i
= 0; i
< moduleb
->num_types
; ++i
)
3422 type_add_cattrs (assembly
, mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
));
3427 mono_image_fill_file_table (MonoDomain
*domain
, MonoReflectionModule
*module
, MonoDynamicImage
*assembly
)
3429 MonoDynamicTable
*table
;
3433 char *b
= blob_size
;
3436 table
= &assembly
->tables
[MONO_TABLE_FILE
];
3438 alloc_table (table
, table
->rows
);
3439 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
3440 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_METADATA
;
3441 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, module
->image
->module_name
);
3442 if (module
->image
->dynamic
) {
3443 /* This depends on the fact that the main module is emitted last */
3444 dir
= mono_string_to_utf8 (((MonoReflectionModuleBuilder
*)module
)->assemblyb
->dir
);
3445 path
= g_strdup_printf ("%s%c%s", dir
, G_DIR_SEPARATOR
, module
->image
->module_name
);
3448 path
= g_strdup (module
->image
->name
);
3450 mono_sha1_get_digest_from_file (path
, hash
);
3453 mono_metadata_encode_value (20, b
, &b
);
3454 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
3455 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
3460 mono_image_fill_module_table (MonoDomain
*domain
, MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
)
3462 MonoDynamicTable
*table
;
3465 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
3466 mb
->table_idx
= table
->next_idx
++;
3467 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->module
.name
);
3468 i
= mono_image_add_stream_data (&assembly
->guid
, mono_array_addr (mb
->guid
, char, 0), 16);
3471 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_GENERATION
] = 0;
3472 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_MVID
] = i
;
3473 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENC
] = 0;
3474 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENCBASE
] = 0;
3478 mono_image_fill_export_table_from_class (MonoDomain
*domain
, MonoClass
*klass
,
3479 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3481 MonoDynamicTable
*table
;
3485 visib
= klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
3486 if (! ((visib
& TYPE_ATTRIBUTE_PUBLIC
) || (visib
& TYPE_ATTRIBUTE_NESTED_PUBLIC
)))
3489 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3491 alloc_table (table
, table
->rows
);
3492 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3494 values
[MONO_EXP_TYPE_FLAGS
] = klass
->flags
;
3495 values
[MONO_EXP_TYPE_TYPEDEF
] = klass
->type_token
;
3496 if (klass
->nested_in
)
3497 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (parent_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
3499 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (module_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_FILE
;
3500 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3501 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3503 res
= table
->next_idx
;
3507 /* Emit nested types */
3508 if (klass
->ext
&& klass
->ext
->nested_classes
) {
3511 for (tmp
= klass
->ext
->nested_classes
; tmp
; tmp
= tmp
->next
)
3512 mono_image_fill_export_table_from_class (domain
, tmp
->data
, module_index
, table
->next_idx
- 1, assembly
);
3519 mono_image_fill_export_table (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
,
3520 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3525 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
));
3527 klass
->type_token
= mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
);
3529 idx
= mono_image_fill_export_table_from_class (domain
, klass
, module_index
,
3530 parent_index
, assembly
);
3534 * We need to do this ourselves since klass->nested_classes is not set up.
3537 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3538 mono_image_fill_export_table (domain
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
), module_index
, idx
, assembly
);
3543 mono_image_fill_export_table_from_module (MonoDomain
*domain
, MonoReflectionModule
*module
,
3544 guint32 module_index
, MonoDynamicImage
*assembly
)
3546 MonoImage
*image
= module
->image
;
3550 t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
3552 for (i
= 0; i
< t
->rows
; ++i
) {
3553 MonoClass
*klass
= mono_class_get (image
, mono_metadata_make_token (MONO_TABLE_TYPEDEF
, i
+ 1));
3555 if (klass
->flags
& TYPE_ATTRIBUTE_PUBLIC
)
3556 mono_image_fill_export_table_from_class (domain
, klass
, module_index
, 0, assembly
);
3561 add_exported_type (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
, MonoClass
*klass
)
3563 MonoDynamicTable
*table
;
3565 guint32 scope
, idx
, res
, impl
;
3566 gboolean forwarder
= TRUE
;
3568 if (klass
->nested_in
) {
3569 impl
= add_exported_type (assemblyb
, assembly
, klass
->nested_in
);
3572 scope
= resolution_scope_from_image (assembly
, klass
->image
);
3573 g_assert ((scope
& MONO_RESOLTION_SCOPE_MASK
) == MONO_RESOLTION_SCOPE_ASSEMBLYREF
);
3574 idx
= scope
>> MONO_RESOLTION_SCOPE_BITS
;
3575 impl
= (idx
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_ASSEMBLYREF
;
3578 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3581 alloc_table (table
, table
->rows
);
3582 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3584 values
[MONO_EXP_TYPE_FLAGS
] = forwarder
? TYPE_ATTRIBUTE_FORWARDER
: 0;
3585 values
[MONO_EXP_TYPE_TYPEDEF
] = 0;
3586 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = impl
;
3587 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3588 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3590 res
= (table
->next_idx
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
3598 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
)
3603 if (!assemblyb
->type_forwarders
)
3606 for (i
= 0; i
< mono_array_length (assemblyb
->type_forwarders
); ++i
) {
3607 MonoReflectionType
*t
= mono_array_get (assemblyb
->type_forwarders
, MonoReflectionType
*, i
);
3612 type
= mono_reflection_type_get_handle (t
);
3615 klass
= mono_class_from_mono_type (type
);
3617 add_exported_type (assemblyb
, assembly
, klass
);
3621 #define align_pointer(base,p)\
3623 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3625 (p) += 4 - (__diff & 3);\
3629 compare_constants (const void *a
, const void *b
)
3631 const guint32
*a_values
= a
;
3632 const guint32
*b_values
= b
;
3633 return a_values
[MONO_CONSTANT_PARENT
] - b_values
[MONO_CONSTANT_PARENT
];
3637 compare_semantics (const void *a
, const void *b
)
3639 const guint32
*a_values
= a
;
3640 const guint32
*b_values
= b
;
3641 int assoc
= a_values
[MONO_METHOD_SEMA_ASSOCIATION
] - b_values
[MONO_METHOD_SEMA_ASSOCIATION
];
3644 return a_values
[MONO_METHOD_SEMA_SEMANTICS
] - b_values
[MONO_METHOD_SEMA_SEMANTICS
];
3648 compare_custom_attrs (const void *a
, const void *b
)
3650 const guint32
*a_values
= a
;
3651 const guint32
*b_values
= b
;
3653 return a_values
[MONO_CUSTOM_ATTR_PARENT
] - b_values
[MONO_CUSTOM_ATTR_PARENT
];
3657 compare_field_marshal (const void *a
, const void *b
)
3659 const guint32
*a_values
= a
;
3660 const guint32
*b_values
= b
;
3662 return a_values
[MONO_FIELD_MARSHAL_PARENT
] - b_values
[MONO_FIELD_MARSHAL_PARENT
];
3666 compare_nested (const void *a
, const void *b
)
3668 const guint32
*a_values
= a
;
3669 const guint32
*b_values
= b
;
3671 return a_values
[MONO_NESTED_CLASS_NESTED
] - b_values
[MONO_NESTED_CLASS_NESTED
];
3675 compare_genericparam (const void *a
, const void *b
)
3677 const GenericParamTableEntry
**a_entry
= (const GenericParamTableEntry
**) a
;
3678 const GenericParamTableEntry
**b_entry
= (const GenericParamTableEntry
**) b
;
3680 if ((*b_entry
)->owner
== (*a_entry
)->owner
)
3682 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType
*)(*a_entry
)->gparam
)) -
3683 mono_type_get_generic_param_num (mono_reflection_type_get_handle ((MonoReflectionType
*)(*b_entry
)->gparam
));
3685 return (*a_entry
)->owner
- (*b_entry
)->owner
;
3689 compare_declsecurity_attrs (const void *a
, const void *b
)
3691 const guint32
*a_values
= a
;
3692 const guint32
*b_values
= b
;
3694 return a_values
[MONO_DECL_SECURITY_PARENT
] - b_values
[MONO_DECL_SECURITY_PARENT
];
3698 compare_interface_impl (const void *a
, const void *b
)
3700 const guint32
*a_values
= a
;
3701 const guint32
*b_values
= b
;
3703 int klass
= a_values
[MONO_INTERFACEIMPL_CLASS
] - b_values
[MONO_INTERFACEIMPL_CLASS
];
3707 return a_values
[MONO_INTERFACEIMPL_INTERFACE
] - b_values
[MONO_INTERFACEIMPL_INTERFACE
];
3711 pad_heap (MonoDynamicStream
*sh
)
3713 if (sh
->index
& 3) {
3714 int sz
= 4 - (sh
->index
& 3);
3715 memset (sh
->data
+ sh
->index
, 0, sz
);
3722 MonoDynamicStream
*stream
;
3726 * build_compressed_metadata() fills in the blob of data that represents the
3727 * raw metadata as it will be saved in the PE file. The five streams are output
3728 * and the metadata tables are comnpressed from the guint32 array representation,
3729 * to the compressed on-disk format.
3732 build_compressed_metadata (MonoDynamicImage
*assembly
)
3734 MonoDynamicTable
*table
;
3736 guint64 valid_mask
= 0;
3737 guint64 sorted_mask
;
3738 guint32 heapt_size
= 0;
3739 guint32 meta_size
= 256; /* allow for header and other stuff */
3740 guint32 table_offset
;
3741 guint32 ntables
= 0;
3747 struct StreamDesc stream_desc
[5];
3749 qsort (assembly
->gen_params
->pdata
, assembly
->gen_params
->len
, sizeof (gpointer
), compare_genericparam
);
3750 for (i
= 0; i
< assembly
->gen_params
->len
; i
++){
3751 GenericParamTableEntry
*entry
= g_ptr_array_index (assembly
->gen_params
, i
);
3752 write_generic_param_entry (assembly
, entry
);
3755 stream_desc
[0].name
= "#~";
3756 stream_desc
[0].stream
= &assembly
->tstream
;
3757 stream_desc
[1].name
= "#Strings";
3758 stream_desc
[1].stream
= &assembly
->sheap
;
3759 stream_desc
[2].name
= "#US";
3760 stream_desc
[2].stream
= &assembly
->us
;
3761 stream_desc
[3].name
= "#Blob";
3762 stream_desc
[3].stream
= &assembly
->blob
;
3763 stream_desc
[4].name
= "#GUID";
3764 stream_desc
[4].stream
= &assembly
->guid
;
3766 /* tables that are sorted */
3767 sorted_mask
= ((guint64
)1 << MONO_TABLE_CONSTANT
) | ((guint64
)1 << MONO_TABLE_FIELDMARSHAL
)
3768 | ((guint64
)1 << MONO_TABLE_METHODSEMANTICS
) | ((guint64
)1 << MONO_TABLE_CLASSLAYOUT
)
3769 | ((guint64
)1 << MONO_TABLE_FIELDLAYOUT
) | ((guint64
)1 << MONO_TABLE_FIELDRVA
)
3770 | ((guint64
)1 << MONO_TABLE_IMPLMAP
) | ((guint64
)1 << MONO_TABLE_NESTEDCLASS
)
3771 | ((guint64
)1 << MONO_TABLE_METHODIMPL
) | ((guint64
)1 << MONO_TABLE_CUSTOMATTRIBUTE
)
3772 | ((guint64
)1 << MONO_TABLE_DECLSECURITY
) | ((guint64
)1 << MONO_TABLE_GENERICPARAM
)
3773 | ((guint64
)1 << MONO_TABLE_INTERFACEIMPL
);
3775 /* Compute table sizes */
3776 /* the MonoImage has already been created in mono_image_basic_init() */
3777 meta
= &assembly
->image
;
3779 /* sizes should be multiple of 4 */
3780 pad_heap (&assembly
->blob
);
3781 pad_heap (&assembly
->guid
);
3782 pad_heap (&assembly
->sheap
);
3783 pad_heap (&assembly
->us
);
3785 /* Setup the info used by compute_sizes () */
3786 meta
->idx_blob_wide
= assembly
->blob
.index
>= 65536 ? 1 : 0;
3787 meta
->idx_guid_wide
= assembly
->guid
.index
>= 65536 ? 1 : 0;
3788 meta
->idx_string_wide
= assembly
->sheap
.index
>= 65536 ? 1 : 0;
3790 meta_size
+= assembly
->blob
.index
;
3791 meta_size
+= assembly
->guid
.index
;
3792 meta_size
+= assembly
->sheap
.index
;
3793 meta_size
+= assembly
->us
.index
;
3795 for (i
=0; i
< MONO_TABLE_NUM
; ++i
)
3796 meta
->tables
[i
].rows
= assembly
->tables
[i
].rows
;
3798 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3799 if (meta
->tables
[i
].rows
== 0)
3801 valid_mask
|= (guint64
)1 << i
;
3803 meta
->tables
[i
].row_size
= mono_metadata_compute_size (
3804 meta
, i
, &meta
->tables
[i
].size_bitfield
);
3805 heapt_size
+= meta
->tables
[i
].row_size
* meta
->tables
[i
].rows
;
3807 heapt_size
+= 24; /* #~ header size */
3808 heapt_size
+= ntables
* 4;
3809 /* make multiple of 4 */
3812 meta_size
+= heapt_size
;
3813 meta
->raw_metadata
= g_malloc0 (meta_size
);
3814 p
= (unsigned char*)meta
->raw_metadata
;
3815 /* the metadata signature */
3816 *p
++ = 'B'; *p
++ = 'S'; *p
++ = 'J'; *p
++ = 'B';
3817 /* version numbers and 4 bytes reserved */
3818 int16val
= (guint16
*)p
;
3819 *int16val
++ = GUINT16_TO_LE (meta
->md_version_major
);
3820 *int16val
= GUINT16_TO_LE (meta
->md_version_minor
);
3822 /* version string */
3823 int32val
= (guint32
*)p
;
3824 *int32val
= GUINT32_TO_LE ((strlen (meta
->version
) + 3) & (~3)); /* needs to be multiple of 4 */
3826 memcpy (p
, meta
->version
, strlen (meta
->version
));
3827 p
+= GUINT32_FROM_LE (*int32val
);
3828 align_pointer (meta
->raw_metadata
, p
);
3829 int16val
= (guint16
*)p
;
3830 *int16val
++ = GUINT16_TO_LE (0); /* flags must be 0 */
3831 *int16val
= GUINT16_TO_LE (5); /* number of streams */
3835 * write the stream info.
3837 table_offset
= (p
- (unsigned char*)meta
->raw_metadata
) + 5 * 8 + 40; /* room needed for stream headers */
3838 table_offset
+= 3; table_offset
&= ~3;
3840 assembly
->tstream
.index
= heapt_size
;
3841 for (i
= 0; i
< 5; ++i
) {
3842 int32val
= (guint32
*)p
;
3843 stream_desc
[i
].stream
->offset
= table_offset
;
3844 *int32val
++ = GUINT32_TO_LE (table_offset
);
3845 *int32val
= GUINT32_TO_LE (stream_desc
[i
].stream
->index
);
3846 table_offset
+= GUINT32_FROM_LE (*int32val
);
3847 table_offset
+= 3; table_offset
&= ~3;
3849 strcpy ((char*)p
, stream_desc
[i
].name
);
3850 p
+= strlen (stream_desc
[i
].name
) + 1;
3851 align_pointer (meta
->raw_metadata
, p
);
3854 * now copy the data, the table stream header and contents goes first.
3856 g_assert ((p
- (unsigned char*)meta
->raw_metadata
) < assembly
->tstream
.offset
);
3857 p
= (guchar
*)meta
->raw_metadata
+ assembly
->tstream
.offset
;
3858 int32val
= (guint32
*)p
;
3859 *int32val
= GUINT32_TO_LE (0); /* reserved */
3862 if (mono_framework_version () > 1) {
3863 *p
++ = 2; /* version */
3866 *p
++ = 1; /* version */
3870 if (meta
->idx_string_wide
)
3872 if (meta
->idx_guid_wide
)
3874 if (meta
->idx_blob_wide
)
3877 *p
++ = 1; /* reserved */
3878 int64val
= (guint64
*)p
;
3879 *int64val
++ = GUINT64_TO_LE (valid_mask
);
3880 *int64val
++ = GUINT64_TO_LE (valid_mask
& sorted_mask
); /* bitvector of sorted tables */
3882 int32val
= (guint32
*)p
;
3883 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3884 if (meta
->tables
[i
].rows
== 0)
3886 *int32val
++ = GUINT32_TO_LE (meta
->tables
[i
].rows
);
3888 p
= (unsigned char*)int32val
;
3890 /* sort the tables that still need sorting */
3891 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
3893 qsort (table
->values
+ MONO_CONSTANT_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CONSTANT_SIZE
, compare_constants
);
3894 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
3896 qsort (table
->values
+ MONO_METHOD_SEMA_SIZE
, table
->rows
, sizeof (guint32
) * MONO_METHOD_SEMA_SIZE
, compare_semantics
);
3897 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
3899 qsort (table
->values
+ MONO_CUSTOM_ATTR_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CUSTOM_ATTR_SIZE
, compare_custom_attrs
);
3900 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
3902 qsort (table
->values
+ MONO_FIELD_MARSHAL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_FIELD_MARSHAL_SIZE
, compare_field_marshal
);
3903 table
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3905 qsort (table
->values
+ MONO_NESTED_CLASS_SIZE
, table
->rows
, sizeof (guint32
) * MONO_NESTED_CLASS_SIZE
, compare_nested
);
3906 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3907 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
3909 qsort (table
->values
+ MONO_DECL_SECURITY_SIZE
, table
->rows
, sizeof (guint32
) * MONO_DECL_SECURITY_SIZE
, compare_declsecurity_attrs
);
3910 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3912 qsort (table
->values
+ MONO_INTERFACEIMPL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_INTERFACEIMPL_SIZE
, compare_interface_impl
);
3914 /* compress the tables */
3915 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3918 guint32 bitfield
= meta
->tables
[i
].size_bitfield
;
3919 if (!meta
->tables
[i
].rows
)
3921 if (assembly
->tables
[i
].columns
!= mono_metadata_table_count (bitfield
))
3922 g_error ("col count mismatch in %d: %d %d", i
, assembly
->tables
[i
].columns
, mono_metadata_table_count (bitfield
));
3923 meta
->tables
[i
].base
= (char*)p
;
3924 for (row
= 1; row
<= meta
->tables
[i
].rows
; ++row
) {
3925 values
= assembly
->tables
[i
].values
+ row
* assembly
->tables
[i
].columns
;
3926 for (col
= 0; col
< assembly
->tables
[i
].columns
; ++col
) {
3927 switch (mono_metadata_table_size (bitfield
, col
)) {
3929 *p
++ = values
[col
];
3932 *p
++ = values
[col
] & 0xff;
3933 *p
++ = (values
[col
] >> 8) & 0xff;
3936 *p
++ = values
[col
] & 0xff;
3937 *p
++ = (values
[col
] >> 8) & 0xff;
3938 *p
++ = (values
[col
] >> 16) & 0xff;
3939 *p
++ = (values
[col
] >> 24) & 0xff;
3942 g_assert_not_reached ();
3946 g_assert ((p
- (const unsigned char*)meta
->tables
[i
].base
) == (meta
->tables
[i
].rows
* meta
->tables
[i
].row_size
));
3949 g_assert (assembly
->guid
.offset
+ assembly
->guid
.index
< meta_size
);
3950 memcpy (meta
->raw_metadata
+ assembly
->sheap
.offset
, assembly
->sheap
.data
, assembly
->sheap
.index
);
3951 memcpy (meta
->raw_metadata
+ assembly
->us
.offset
, assembly
->us
.data
, assembly
->us
.index
);
3952 memcpy (meta
->raw_metadata
+ assembly
->blob
.offset
, assembly
->blob
.data
, assembly
->blob
.index
);
3953 memcpy (meta
->raw_metadata
+ assembly
->guid
.offset
, assembly
->guid
.data
, assembly
->guid
.index
);
3955 assembly
->meta_size
= assembly
->guid
.offset
+ assembly
->guid
.index
;
3959 * Some tables in metadata need to be sorted according to some criteria, but
3960 * when methods and fields are first created with reflection, they may be assigned a token
3961 * that doesn't correspond to the final token they will get assigned after the sorting.
3962 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3963 * with the reflection objects that represent them. Once all the tables are set up, the
3964 * reflection objects will contains the correct table index. fixup_method() will fixup the
3965 * tokens for the method with ILGenerator @ilgen.
3968 fixup_method (MonoReflectionILGen
*ilgen
, gpointer value
, MonoDynamicImage
*assembly
)
3970 guint32 code_idx
= GPOINTER_TO_UINT (value
);
3971 MonoReflectionILTokenInfo
*iltoken
;
3972 MonoReflectionFieldBuilder
*field
;
3973 MonoReflectionCtorBuilder
*ctor
;
3974 MonoReflectionMethodBuilder
*method
;
3975 MonoReflectionTypeBuilder
*tb
;
3976 MonoReflectionArrayMethod
*am
;
3978 unsigned char *target
;
3980 for (i
= 0; i
< ilgen
->num_token_fixups
; ++i
) {
3981 iltoken
= (MonoReflectionILTokenInfo
*)mono_array_addr_with_size (ilgen
->token_fixups
, sizeof (MonoReflectionILTokenInfo
), i
);
3982 target
= (guchar
*)assembly
->code
.data
+ code_idx
+ iltoken
->code_pos
;
3983 switch (target
[3]) {
3984 case MONO_TABLE_FIELD
:
3985 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
3986 field
= (MonoReflectionFieldBuilder
*)iltoken
->member
;
3987 idx
= field
->table_idx
;
3988 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
3989 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
3990 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->field_to_table_idx
, f
));
3992 g_assert_not_reached ();
3995 case MONO_TABLE_METHOD
:
3996 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
3997 method
= (MonoReflectionMethodBuilder
*)iltoken
->member
;
3998 idx
= method
->table_idx
;
3999 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
4000 ctor
= (MonoReflectionCtorBuilder
*)iltoken
->member
;
4001 idx
= ctor
->table_idx
;
4002 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
4003 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod")) {
4004 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4005 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4007 g_assert_not_reached ();
4010 case MONO_TABLE_TYPEDEF
:
4011 if (strcmp (iltoken
->member
->vtable
->klass
->name
, "TypeBuilder"))
4012 g_assert_not_reached ();
4013 tb
= (MonoReflectionTypeBuilder
*)iltoken
->member
;
4014 idx
= tb
->table_idx
;
4016 case MONO_TABLE_MEMBERREF
:
4017 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoArrayMethod")) {
4018 am
= (MonoReflectionArrayMethod
*)iltoken
->member
;
4019 idx
= am
->table_idx
;
4020 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
4021 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod") ||
4022 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod") ||
4023 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericCMethod")) {
4024 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4025 g_assert (m
->klass
->generic_class
|| m
->klass
->generic_container
);
4027 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
4029 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
4030 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
4031 g_assert (is_field_on_inst (f
));
4033 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder") ||
4034 !strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
4036 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldOnTypeBuilderInst")) {
4038 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodOnTypeBuilderInst")) {
4040 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst")) {
4043 g_assert_not_reached ();
4046 case MONO_TABLE_METHODSPEC
:
4047 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod")) {
4048 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4049 g_assert (mono_method_signature (m
)->generic_param_count
);
4051 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
4054 g_assert_not_reached ();
4058 g_error ("got unexpected table 0x%02x in fixup", target
[3]);
4060 target
[0] = idx
& 0xff;
4061 target
[1] = (idx
>> 8) & 0xff;
4062 target
[2] = (idx
>> 16) & 0xff;
4069 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4070 * value is not known when the table is emitted.
4073 fixup_cattrs (MonoDynamicImage
*assembly
)
4075 MonoDynamicTable
*table
;
4077 guint32 type
, i
, idx
, token
;
4080 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4082 for (i
= 0; i
< table
->rows
; ++i
) {
4083 values
= table
->values
+ ((i
+ 1) * MONO_CUSTOM_ATTR_SIZE
);
4085 type
= values
[MONO_CUSTOM_ATTR_TYPE
];
4086 if ((type
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_METHODDEF
) {
4087 idx
= type
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
4088 token
= mono_metadata_make_token (MONO_TABLE_METHOD
, idx
);
4089 ctor
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4092 if (!strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
4093 MonoMethod
*m
= ((MonoReflectionMethod
*)ctor
)->method
;
4094 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4095 values
[MONO_CUSTOM_ATTR_TYPE
] = (idx
<< MONO_CUSTOM_ATTR_TYPE_BITS
) | MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
4102 assembly_add_resource_manifest (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
, guint32 implementation
)
4104 MonoDynamicTable
*table
;
4107 table
= &assembly
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4109 alloc_table (table
, table
->rows
);
4110 values
= table
->values
+ table
->next_idx
* MONO_MANIFEST_SIZE
;
4111 values
[MONO_MANIFEST_OFFSET
] = rsrc
->offset
;
4112 values
[MONO_MANIFEST_FLAGS
] = rsrc
->attrs
;
4113 values
[MONO_MANIFEST_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, rsrc
->name
);
4114 values
[MONO_MANIFEST_IMPLEMENTATION
] = implementation
;
4119 assembly_add_resource (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
)
4121 MonoDynamicTable
*table
;
4125 char *b
= blob_size
;
4127 guint32 idx
, offset
;
4129 if (rsrc
->filename
) {
4130 name
= mono_string_to_utf8 (rsrc
->filename
);
4131 sname
= g_path_get_basename (name
);
4133 table
= &assembly
->tables
[MONO_TABLE_FILE
];
4135 alloc_table (table
, table
->rows
);
4136 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
4137 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_NO_METADATA
;
4138 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, sname
);
4141 mono_sha1_get_digest_from_file (name
, hash
);
4142 mono_metadata_encode_value (20, b
, &b
);
4143 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
4144 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
4146 idx
= table
->next_idx
++;
4148 idx
= MONO_IMPLEMENTATION_FILE
| (idx
<< MONO_IMPLEMENTATION_BITS
);
4154 data
= mono_array_addr (rsrc
->data
, char, 0);
4155 len
= mono_array_length (rsrc
->data
);
4161 sizebuf
[0] = offset
; sizebuf
[1] = offset
>> 8;
4162 sizebuf
[2] = offset
>> 16; sizebuf
[3] = offset
>> 24;
4163 rsrc
->offset
= mono_image_add_stream_data (&assembly
->resources
, sizebuf
, 4);
4164 mono_image_add_stream_data (&assembly
->resources
, data
, len
);
4168 * The entry should be emitted into the MANIFESTRESOURCE table of
4169 * the main module, but that needs to reference the FILE table
4170 * which isn't emitted yet.
4177 assembly_add_resource_manifest (mb
, assembly
, rsrc
, idx
);
4181 set_version_from_string (MonoString
*version
, guint32
*values
)
4183 gchar
*ver
, *p
, *str
;
4186 values
[MONO_ASSEMBLY_MAJOR_VERSION
] = 0;
4187 values
[MONO_ASSEMBLY_MINOR_VERSION
] = 0;
4188 values
[MONO_ASSEMBLY_REV_NUMBER
] = 0;
4189 values
[MONO_ASSEMBLY_BUILD_NUMBER
] = 0;
4192 ver
= str
= mono_string_to_utf8 (version
);
4193 for (i
= 0; i
< 4; ++i
) {
4194 values
[MONO_ASSEMBLY_MAJOR_VERSION
+ i
] = strtol (ver
, &p
, 10);
4200 /* handle Revision and Build */
4210 load_public_key (MonoArray
*pkey
, MonoDynamicImage
*assembly
) {
4214 char *b
= blob_size
;
4219 len
= mono_array_length (pkey
);
4220 mono_metadata_encode_value (len
, b
, &b
);
4221 token
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
- blob_size
);
4222 mono_image_add_stream_data (&assembly
->blob
, mono_array_addr (pkey
, char, 0), len
);
4224 assembly
->public_key
= g_malloc (len
);
4225 memcpy (assembly
->public_key
, mono_array_addr (pkey
, char, 0), len
);
4226 assembly
->public_key_len
= len
;
4228 /* Special case: check for ECMA key (16 bytes) */
4229 if ((len
== MONO_ECMA_KEY_LENGTH
) && mono_is_ecma_key (mono_array_addr (pkey
, char, 0), len
)) {
4230 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4231 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
;
4232 } else if (len
>= MONO_PUBLIC_KEY_HEADER_LENGTH
+ MONO_MINIMUM_PUBLIC_KEY_LENGTH
) {
4233 /* minimum key size (in 2.0) is 384 bits */
4234 assembly
->strong_name_size
= len
- MONO_PUBLIC_KEY_HEADER_LENGTH
;
4236 /* FIXME - verifier */
4237 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len
), (int)len
);
4238 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
; /* to be safe */
4240 assembly
->strong_name
= g_malloc0 (assembly
->strong_name_size
);
4246 mono_image_emit_manifest (MonoReflectionModuleBuilder
*moduleb
)
4248 MonoDynamicTable
*table
;
4249 MonoDynamicImage
*assembly
;
4250 MonoReflectionAssemblyBuilder
*assemblyb
;
4254 guint32 module_index
;
4256 assemblyb
= moduleb
->assemblyb
;
4257 assembly
= moduleb
->dynamic_image
;
4258 domain
= mono_object_domain (assemblyb
);
4260 /* Emit ASSEMBLY table */
4261 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLY
];
4262 alloc_table (table
, 1);
4263 values
= table
->values
+ MONO_ASSEMBLY_SIZE
;
4264 values
[MONO_ASSEMBLY_HASH_ALG
] = assemblyb
->algid
? assemblyb
->algid
: ASSEMBLY_HASH_SHA1
;
4265 values
[MONO_ASSEMBLY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->name
);
4266 if (assemblyb
->culture
) {
4267 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->culture
);
4269 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert (&assembly
->sheap
, "");
4271 values
[MONO_ASSEMBLY_PUBLIC_KEY
] = load_public_key (assemblyb
->public_key
, assembly
);
4272 values
[MONO_ASSEMBLY_FLAGS
] = assemblyb
->flags
;
4273 set_version_from_string (assemblyb
->version
, values
);
4275 /* Emit FILE + EXPORTED_TYPE table */
4277 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4279 MonoReflectionModuleBuilder
*file_module
=
4280 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4281 if (file_module
!= moduleb
) {
4282 mono_image_fill_file_table (domain
, (MonoReflectionModule
*)file_module
, assembly
);
4284 if (file_module
->types
) {
4285 for (j
= 0; j
< file_module
->num_types
; ++j
) {
4286 MonoReflectionTypeBuilder
*tb
= mono_array_get (file_module
->types
, MonoReflectionTypeBuilder
*, j
);
4287 mono_image_fill_export_table (domain
, tb
, module_index
, 0, assembly
);
4292 if (assemblyb
->loaded_modules
) {
4293 for (i
= 0; i
< mono_array_length (assemblyb
->loaded_modules
); ++i
) {
4294 MonoReflectionModule
*file_module
=
4295 mono_array_get (assemblyb
->loaded_modules
, MonoReflectionModule
*, i
);
4296 mono_image_fill_file_table (domain
, file_module
, assembly
);
4298 mono_image_fill_export_table_from_module (domain
, file_module
, module_index
, assembly
);
4301 if (assemblyb
->type_forwarders
)
4302 mono_image_fill_export_table_from_type_forwarders (assemblyb
, assembly
);
4304 /* Emit MANIFESTRESOURCE table */
4306 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4308 MonoReflectionModuleBuilder
*file_module
=
4309 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4310 /* The table for the main module is emitted later */
4311 if (file_module
!= moduleb
) {
4313 if (file_module
->resources
) {
4314 int len
= mono_array_length (file_module
->resources
);
4315 for (j
= 0; j
< len
; ++j
) {
4316 MonoReflectionResource
* res
= (MonoReflectionResource
*)mono_array_addr (file_module
->resources
, MonoReflectionResource
, j
);
4317 assembly_add_resource_manifest (file_module
, assembly
, res
, MONO_IMPLEMENTATION_FILE
| (module_index
<< MONO_IMPLEMENTATION_BITS
));
4324 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4327 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4328 * for the modulebuilder @moduleb.
4329 * At the end of the process, method and field tokens are fixed up and the
4330 * on-disk compressed metadata representation is created.
4333 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4335 MonoDynamicTable
*table
;
4336 MonoDynamicImage
*assembly
;
4337 MonoReflectionAssemblyBuilder
*assemblyb
;
4343 assemblyb
= moduleb
->assemblyb
;
4344 assembly
= moduleb
->dynamic_image
;
4345 domain
= mono_object_domain (assemblyb
);
4347 if (assembly
->text_rva
)
4350 assembly
->text_rva
= START_TEXT_RVA
;
4352 if (moduleb
->is_main
) {
4353 mono_image_emit_manifest (moduleb
);
4356 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4357 table
->rows
= 1; /* .<Module> */
4359 alloc_table (table
, table
->rows
);
4361 * Set the first entry.
4363 values
= table
->values
+ table
->columns
;
4364 values
[MONO_TYPEDEF_FLAGS
] = 0;
4365 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, "<Module>") ;
4366 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, "") ;
4367 values
[MONO_TYPEDEF_EXTENDS
] = 0;
4368 values
[MONO_TYPEDEF_FIELD_LIST
] = 1;
4369 values
[MONO_TYPEDEF_METHOD_LIST
] = 1;
4372 * handle global methods
4373 * FIXME: test what to do when global methods are defined in multiple modules.
4375 if (moduleb
->global_methods
) {
4376 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
4377 table
->rows
+= mono_array_length (moduleb
->global_methods
);
4378 alloc_table (table
, table
->rows
);
4379 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
)
4380 mono_image_get_method_info (
4381 mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
4383 if (moduleb
->global_fields
) {
4384 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
4385 table
->rows
+= mono_array_length (moduleb
->global_fields
);
4386 alloc_table (table
, table
->rows
);
4387 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
)
4388 mono_image_get_field_info (
4389 mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
4392 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
4393 alloc_table (table
, 1);
4394 mono_image_fill_module_table (domain
, moduleb
, assembly
);
4396 /* Collect all types into a list sorted by their table_idx */
4397 types
= g_ptr_array_new ();
4400 for (i
= 0; i
< moduleb
->num_types
; ++i
) {
4401 MonoReflectionTypeBuilder
*type
= mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
);
4402 collect_types (types
, type
);
4405 g_ptr_array_sort (types
, (GCompareFunc
)compare_types_by_table_idx
);
4406 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4407 table
->rows
+= types
->len
;
4408 alloc_table (table
, table
->rows
);
4411 * Emit type names + namespaces at one place inside the string heap,
4412 * so load_class_names () needs to touch fewer pages.
4414 for (i
= 0; i
< types
->len
; ++i
) {
4415 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4416 string_heap_insert_mstring (&assembly
->sheap
, tb
->nspace
);
4418 for (i
= 0; i
< types
->len
; ++i
) {
4419 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4420 string_heap_insert_mstring (&assembly
->sheap
, tb
->name
);
4423 for (i
= 0; i
< types
->len
; ++i
) {
4424 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4425 mono_image_get_type_info (domain
, type
, assembly
);
4429 * table->rows is already set above and in mono_image_fill_module_table.
4431 /* add all the custom attributes at the end, once all the indexes are stable */
4432 mono_image_add_cattrs (assembly
, 1, MONO_CUSTOM_ATTR_ASSEMBLY
, assemblyb
->cattrs
);
4434 /* CAS assembly permissions */
4435 if (assemblyb
->permissions_minimum
)
4436 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_minimum
);
4437 if (assemblyb
->permissions_optional
)
4438 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_optional
);
4439 if (assemblyb
->permissions_refused
)
4440 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_refused
);
4442 module_add_cattrs (assembly
, moduleb
);
4445 mono_g_hash_table_foreach (assembly
->token_fixups
, (GHFunc
)fixup_method
, assembly
);
4447 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4448 * the final tokens and don't need another fixup pass. */
4450 if (moduleb
->global_methods
) {
4451 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
4452 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4453 moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
4454 mono_image_add_methodimpl (assembly
, mb
);
4458 for (i
= 0; i
< types
->len
; ++i
) {
4459 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4460 if (type
->methods
) {
4461 for (j
= 0; j
< type
->num_methods
; ++j
) {
4462 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4463 type
->methods
, MonoReflectionMethodBuilder
*, j
);
4465 mono_image_add_methodimpl (assembly
, mb
);
4470 g_ptr_array_free (types
, TRUE
);
4472 fixup_cattrs (assembly
);
4475 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4478 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4480 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4483 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4487 guint32 import_lookup_table
;
4491 guint32 import_address_table_rva
;
4499 #ifndef DISABLE_REFLECTION_EMIT
4502 * mono_image_insert_string:
4503 * @module: module builder object
4506 * Insert @str into the user string stream of @module.
4509 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
4511 MonoDynamicImage
*assembly
;
4516 MONO_ARCH_SAVE_REGS
;
4518 if (!module
->dynamic_image
)
4519 mono_image_module_basic_init (module
);
4521 assembly
= module
->dynamic_image
;
4523 if (assembly
->save
) {
4524 mono_metadata_encode_value (1 | (str
->length
* 2), b
, &b
);
4525 idx
= mono_image_add_stream_data (&assembly
->us
, buf
, b
-buf
);
4526 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4528 char *swapped
= g_malloc (2 * mono_string_length (str
));
4529 const char *p
= (const char*)mono_string_chars (str
);
4531 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
4532 mono_image_add_stream_data (&assembly
->us
, swapped
, str
->length
* 2);
4536 mono_image_add_stream_data (&assembly
->us
, (const char*)mono_string_chars (str
), str
->length
* 2);
4538 mono_image_add_stream_data (&assembly
->us
, "", 1);
4540 idx
= assembly
->us
.index
++;
4543 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (MONO_TOKEN_STRING
| idx
), str
);
4545 return MONO_TOKEN_STRING
| idx
;
4549 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
4554 klass
= obj
->vtable
->klass
;
4555 if (strcmp (klass
->name
, "MonoMethod") == 0) {
4556 MonoMethod
*method
= ((MonoReflectionMethod
*)obj
)->method
;
4557 MonoMethodSignature
*sig
, *old
;
4558 guint32 sig_token
, parent
;
4561 g_assert (opt_param_types
&& (mono_method_signature (method
)->sentinelpos
>= 0));
4563 nargs
= mono_array_length (opt_param_types
);
4564 old
= mono_method_signature (method
);
4565 sig
= mono_metadata_signature_alloc ( &assembly
->image
, old
->param_count
+ nargs
);
4567 sig
->hasthis
= old
->hasthis
;
4568 sig
->explicit_this
= old
->explicit_this
;
4569 sig
->call_convention
= old
->call_convention
;
4570 sig
->generic_param_count
= old
->generic_param_count
;
4571 sig
->param_count
= old
->param_count
+ nargs
;
4572 sig
->sentinelpos
= old
->param_count
;
4573 sig
->ret
= old
->ret
;
4575 for (i
= 0; i
< old
->param_count
; i
++)
4576 sig
->params
[i
] = old
->params
[i
];
4578 for (i
= 0; i
< nargs
; i
++) {
4579 MonoReflectionType
*rt
= mono_array_get (opt_param_types
, MonoReflectionType
*, i
);
4580 sig
->params
[old
->param_count
+ i
] = mono_reflection_type_get_handle (rt
);
4583 parent
= mono_image_typedef_or_ref (assembly
, &method
->klass
->byval_arg
);
4584 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_MEMBERREF_PARENT_TYPEREF
);
4585 parent
>>= MONO_TYPEDEFORREF_BITS
;
4587 parent
<<= MONO_MEMBERREF_PARENT_BITS
;
4588 parent
|= MONO_MEMBERREF_PARENT_TYPEREF
;
4590 sig_token
= method_encode_signature (assembly
, sig
);
4591 token
= mono_image_get_varargs_method_token (assembly
, parent
, method
->name
, sig_token
);
4592 } else if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4593 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4594 ReflectionMethodBuilder rmb
;
4595 guint32 parent
, sig
;
4598 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
4599 rmb
.opt_types
= opt_param_types
;
4601 sig
= method_builder_encode_signature (assembly
, &rmb
);
4603 parent
= mono_image_create_token (assembly
, obj
, TRUE
, TRUE
);
4604 g_assert (mono_metadata_token_table (parent
) == MONO_TABLE_METHOD
);
4606 parent
= mono_metadata_token_index (parent
) << MONO_MEMBERREF_PARENT_BITS
;
4607 parent
|= MONO_MEMBERREF_PARENT_METHODDEF
;
4609 name
= mono_string_to_utf8 (rmb
.name
);
4610 token
= mono_image_get_varargs_method_token (
4611 assembly
, parent
, name
, sig
);
4614 g_error ("requested method token for %s\n", klass
->name
);
4621 * mono_image_create_token:
4622 * @assembly: a dynamic assembly
4624 * @register_token: Whenever to register the token in the assembly->tokens hash.
4626 * Get a token to insert in the IL code stream for the given MemberInfo.
4627 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4628 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4632 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
4633 gboolean create_methodspec
, gboolean register_token
)
4638 klass
= obj
->vtable
->klass
;
4640 /* Check for user defined reflection objects */
4641 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4642 if (klass
->image
!= mono_defaults
.corlib
|| (strcmp (klass
->name
, "TypeDelegator") == 0))
4643 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4645 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4646 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4647 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4649 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
&& !mb
->generic_params
)
4650 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4652 token
= mono_image_get_methodbuilder_token (assembly
, mb
, create_methodspec
);
4653 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4654 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
4655 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
4656 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4658 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
)
4659 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4661 token
= mono_image_get_ctorbuilder_token (assembly
, mb
);
4662 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4663 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
4664 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
4665 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
4666 if (tb
->generic_params
) {
4667 token
= mono_image_get_generic_field_token (assembly
, fb
);
4669 token
= fb
->table_idx
| MONO_TOKEN_FIELD_DEF
;
4671 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
4672 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
4673 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
4674 } else if (strcmp (klass
->name
, "MonoType") == 0) {
4675 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
4676 MonoClass
*mc
= mono_class_from_mono_type (type
);
4677 token
= mono_metadata_token_from_dor (
4678 mono_image_typedef_or_ref_full (assembly
, type
, mc
->generic_container
== NULL
));
4679 } else if (strcmp (klass
->name
, "GenericTypeParameterBuilder") == 0) {
4680 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
4681 token
= mono_metadata_token_from_dor (
4682 mono_image_typedef_or_ref (assembly
, type
));
4683 } else if (strcmp (klass
->name
, "MonoGenericClass") == 0) {
4684 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
4685 token
= mono_metadata_token_from_dor (
4686 mono_image_typedef_or_ref (assembly
, type
));
4687 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
4688 strcmp (klass
->name
, "MonoMethod") == 0 ||
4689 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
4690 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
4691 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
4692 if (m
->method
->is_inflated
) {
4693 if (create_methodspec
)
4694 token
= mono_image_get_methodspec_token (assembly
, m
->method
);
4696 token
= mono_image_get_inflated_method_token (assembly
, m
->method
);
4697 } else if ((m
->method
->klass
->image
== &assembly
->image
) &&
4698 !m
->method
->klass
->generic_class
) {
4699 static guint32 method_table_idx
= 0xffffff;
4700 if (m
->method
->klass
->wastypebuilder
) {
4701 /* we use the same token as the one that was assigned
4702 * to the Methodbuilder.
4703 * FIXME: do the equivalent for Fields.
4705 token
= m
->method
->token
;
4708 * Each token should have a unique index, but the indexes are
4709 * assigned by managed code, so we don't know about them. An
4710 * easy solution is to count backwards...
4712 method_table_idx
--;
4713 token
= MONO_TOKEN_METHOD_DEF
| method_table_idx
;
4716 token
= mono_image_get_methodref_token (assembly
, m
->method
, create_methodspec
);
4718 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4719 } else if (strcmp (klass
->name
, "MonoField") == 0) {
4720 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
4721 if ((f
->field
->parent
->image
== &assembly
->image
) && !is_field_on_inst (f
->field
)) {
4722 static guint32 field_table_idx
= 0xffffff;
4724 token
= MONO_TOKEN_FIELD_DEF
| field_table_idx
;
4726 token
= mono_image_get_fieldref_token (assembly
, f
);
4728 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4729 } else if (strcmp (klass
->name
, "MonoArrayMethod") == 0) {
4730 MonoReflectionArrayMethod
*m
= (MonoReflectionArrayMethod
*)obj
;
4731 token
= mono_image_get_array_token (assembly
, m
);
4732 } else if (strcmp (klass
->name
, "SignatureHelper") == 0) {
4733 MonoReflectionSigHelper
*s
= (MonoReflectionSigHelper
*)obj
;
4734 token
= MONO_TOKEN_SIGNATURE
| mono_image_get_sighelper_token (assembly
, s
);
4735 } else if (strcmp (klass
->name
, "EnumBuilder") == 0) {
4736 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
4737 token
= mono_metadata_token_from_dor (
4738 mono_image_typedef_or_ref (assembly
, type
));
4739 } else if (strcmp (klass
->name
, "FieldOnTypeBuilderInst") == 0) {
4740 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
4741 token
= mono_image_get_field_on_inst_token (assembly
, f
);
4742 } else if (strcmp (klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
4743 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
4744 token
= mono_image_get_ctor_on_inst_token (assembly
, c
, create_methodspec
);
4745 } else if (strcmp (klass
->name
, "MethodOnTypeBuilderInst") == 0) {
4746 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
4747 token
= mono_image_get_method_on_inst_token (assembly
, m
, create_methodspec
);
4748 } else if (is_sre_array (klass
) || is_sre_byref (klass
) || is_sre_pointer (klass
)) {
4749 MonoReflectionType
*type
= (MonoReflectionType
*)obj
;
4750 token
= mono_metadata_token_from_dor (
4751 mono_image_typedef_or_ref (assembly
, mono_reflection_type_get_handle (type
)));
4753 g_error ("requested token for %s\n", klass
->name
);
4757 mono_image_register_token (assembly
, token
, obj
);
4763 * mono_image_register_token:
4765 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4766 * the Module.ResolveXXXToken () methods to work.
4769 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
4771 MonoObject
*prev
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4773 /* There could be multiple MethodInfo objects with the same token */
4774 //g_assert (prev == obj);
4776 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), obj
);
4780 static MonoDynamicImage
*
4781 create_dynamic_mono_image (MonoDynamicAssembly
*assembly
, char *assembly_name
, char *module_name
)
4783 static const guchar entrycode
[16] = {0xff, 0x25, 0};
4784 MonoDynamicImage
*image
;
4787 const char *version
;
4789 if (!strcmp (mono_get_runtime_info ()->framework_version
, "2.1"))
4790 version
= "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4792 version
= mono_get_runtime_info ()->runtime_version
;
4795 image
= GC_MALLOC (sizeof (MonoDynamicImage
));
4797 image
= g_new0 (MonoDynamicImage
, 1);
4800 mono_profiler_module_event (&image
->image
, MONO_PROFILE_START_LOAD
);
4802 /*g_print ("created image %p\n", image);*/
4803 /* keep in sync with image.c */
4804 image
->image
.name
= assembly_name
;
4805 image
->image
.assembly_name
= image
->image
.name
; /* they may be different */
4806 image
->image
.module_name
= module_name
;
4807 image
->image
.version
= g_strdup (version
);
4808 image
->image
.md_version_major
= 1;
4809 image
->image
.md_version_minor
= 1;
4810 image
->image
.dynamic
= TRUE
;
4812 image
->image
.references
= g_new0 (MonoAssembly
*, 1);
4813 image
->image
.references
[0] = NULL
;
4815 mono_image_init (&image
->image
);
4817 image
->token_fixups
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
);
4818 image
->method_to_table_idx
= g_hash_table_new (NULL
, NULL
);
4819 image
->field_to_table_idx
= g_hash_table_new (NULL
, NULL
);
4820 image
->method_aux_hash
= g_hash_table_new (NULL
, NULL
);
4821 image
->handleref
= g_hash_table_new (NULL
, NULL
);
4822 image
->tokens
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
4823 image
->generic_def_objects
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
4824 image
->methodspec
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
);
4825 image
->typespec
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
4826 image
->typeref
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
4827 image
->blob_cache
= g_hash_table_new ((GHashFunc
)mono_blob_entry_hash
, (GCompareFunc
)mono_blob_entry_equal
);
4828 image
->gen_params
= g_ptr_array_new ();
4830 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4831 string_heap_init (&image
->sheap
);
4832 mono_image_add_stream_data (&image
->us
, "", 1);
4833 add_to_blob_cached (image
, (char*) "", 1, NULL
, 0);
4834 /* import tables... */
4835 mono_image_add_stream_data (&image
->code
, (char*)entrycode
, sizeof (entrycode
));
4836 image
->iat_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two IAT entries */
4837 image
->idt_offset
= mono_image_add_stream_zero (&image
->code
, 2 * sizeof (MonoIDT
)); /* two IDT entries */
4838 image
->imp_names_offset
= mono_image_add_stream_zero (&image
->code
, 2); /* flags for name entry */
4839 mono_image_add_stream_data (&image
->code
, "_CorExeMain", 12);
4840 mono_image_add_stream_data (&image
->code
, "mscoree.dll", 12);
4841 image
->ilt_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two ILT entries */
4842 stream_data_align (&image
->code
);
4844 image
->cli_header_offset
= mono_image_add_stream_zero (&image
->code
, sizeof (MonoCLIHeader
));
4846 for (i
=0; i
< MONO_TABLE_NUM
; ++i
) {
4847 image
->tables
[i
].next_idx
= 1;
4848 image
->tables
[i
].columns
= table_sizes
[i
];
4851 image
->image
.assembly
= (MonoAssembly
*)assembly
;
4852 image
->run
= assembly
->run
;
4853 image
->save
= assembly
->save
;
4854 image
->pe_kind
= 0x1; /* ILOnly */
4855 image
->machine
= 0x14c; /* I386 */
4857 mono_profiler_module_loaded (&image
->image
, MONO_PROFILE_OK
);
4864 free_blob_cache_entry (gpointer key
, gpointer val
, gpointer user_data
)
4870 mono_dynamic_image_free (MonoDynamicImage
*image
)
4872 MonoDynamicImage
*di
= image
;
4877 mono_g_hash_table_destroy (di
->methodspec
);
4879 g_hash_table_destroy (di
->typespec
);
4881 g_hash_table_destroy (di
->typeref
);
4883 g_hash_table_destroy (di
->handleref
);
4885 mono_g_hash_table_destroy (di
->tokens
);
4886 if (di
->generic_def_objects
)
4887 mono_g_hash_table_destroy (di
->generic_def_objects
);
4888 if (di
->blob_cache
) {
4889 g_hash_table_foreach (di
->blob_cache
, free_blob_cache_entry
, NULL
);
4890 g_hash_table_destroy (di
->blob_cache
);
4892 if (di
->standalonesig_cache
)
4893 g_hash_table_destroy (di
->standalonesig_cache
);
4894 for (list
= di
->array_methods
; list
; list
= list
->next
) {
4895 ArrayMethod
*am
= (ArrayMethod
*)list
->data
;
4900 g_list_free (di
->array_methods
);
4901 if (di
->gen_params
) {
4902 for (i
= 0; i
< di
->gen_params
->len
; i
++) {
4903 GenericParamTableEntry
*entry
= g_ptr_array_index (di
->gen_params
, i
);
4904 if (entry
->gparam
->type
.type
) {
4905 MonoGenericParam
*param
= entry
->gparam
->type
.type
->data
.generic_param
;
4906 g_free ((char*)mono_generic_param_info (param
)->name
);
4911 g_ptr_array_free (di
->gen_params
, TRUE
);
4913 if (di
->token_fixups
)
4914 mono_g_hash_table_destroy (di
->token_fixups
);
4915 if (di
->method_to_table_idx
)
4916 g_hash_table_destroy (di
->method_to_table_idx
);
4917 if (di
->field_to_table_idx
)
4918 g_hash_table_destroy (di
->field_to_table_idx
);
4919 if (di
->method_aux_hash
)
4920 g_hash_table_destroy (di
->method_aux_hash
);
4921 g_free (di
->strong_name
);
4922 g_free (di
->win32_res
);
4924 g_free (di
->public_key
);
4926 /*g_print ("string heap destroy for image %p\n", di);*/
4927 mono_dynamic_stream_reset (&di
->sheap
);
4928 mono_dynamic_stream_reset (&di
->code
);
4929 mono_dynamic_stream_reset (&di
->resources
);
4930 mono_dynamic_stream_reset (&di
->us
);
4931 mono_dynamic_stream_reset (&di
->blob
);
4932 mono_dynamic_stream_reset (&di
->tstream
);
4933 mono_dynamic_stream_reset (&di
->guid
);
4934 for (i
= 0; i
< MONO_TABLE_NUM
; ++i
) {
4935 g_free (di
->tables
[i
].values
);
4939 #ifndef DISABLE_REFLECTION_EMIT
4942 * mono_image_basic_init:
4943 * @assembly: an assembly builder object
4945 * Create the MonoImage that represents the assembly builder and setup some
4946 * of the helper hash table and the basic metadata streams.
4949 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
4951 MonoDynamicAssembly
*assembly
;
4952 MonoDynamicImage
*image
;
4953 MonoDomain
*domain
= mono_object_domain (assemblyb
);
4955 MONO_ARCH_SAVE_REGS
;
4957 if (assemblyb
->dynamic_assembly
)
4961 assembly
= assemblyb
->dynamic_assembly
= GC_MALLOC (sizeof (MonoDynamicAssembly
));
4963 assembly
= assemblyb
->dynamic_assembly
= g_new0 (MonoDynamicAssembly
, 1);
4966 mono_profiler_assembly_event (&assembly
->assembly
, MONO_PROFILE_START_LOAD
);
4968 assembly
->assembly
.ref_count
= 1;
4969 assembly
->assembly
.dynamic
= TRUE
;
4970 assembly
->assembly
.corlib_internal
= assemblyb
->corlib_internal
;
4971 assemblyb
->assembly
.assembly
= (MonoAssembly
*)assembly
;
4972 assembly
->assembly
.basedir
= mono_string_to_utf8 (assemblyb
->dir
);
4973 if (assemblyb
->culture
)
4974 assembly
->assembly
.aname
.culture
= mono_string_to_utf8 (assemblyb
->culture
);
4976 assembly
->assembly
.aname
.culture
= g_strdup ("");
4978 if (assemblyb
->version
) {
4979 char *vstr
= mono_string_to_utf8 (assemblyb
->version
);
4980 char **version
= g_strsplit (vstr
, ".", 4);
4981 char **parts
= version
;
4982 assembly
->assembly
.aname
.major
= atoi (*parts
++);
4983 assembly
->assembly
.aname
.minor
= atoi (*parts
++);
4984 assembly
->assembly
.aname
.build
= *parts
!= NULL
? atoi (*parts
++) : 0;
4985 assembly
->assembly
.aname
.revision
= *parts
!= NULL
? atoi (*parts
) : 0;
4987 g_strfreev (version
);
4990 assembly
->assembly
.aname
.major
= 0;
4991 assembly
->assembly
.aname
.minor
= 0;
4992 assembly
->assembly
.aname
.build
= 0;
4993 assembly
->assembly
.aname
.revision
= 0;
4996 assembly
->run
= assemblyb
->access
!= 2;
4997 assembly
->save
= assemblyb
->access
!= 1;
4999 image
= create_dynamic_mono_image (assembly
, mono_string_to_utf8 (assemblyb
->name
), g_strdup ("RefEmit_YouForgotToDefineAModule"));
5000 image
->initial_image
= TRUE
;
5001 assembly
->assembly
.aname
.name
= image
->image
.name
;
5002 assembly
->assembly
.image
= &image
->image
;
5003 if (assemblyb
->pktoken
&& assemblyb
->pktoken
->max_length
) {
5004 /* -1 to correct for the trailing NULL byte */
5005 if (assemblyb
->pktoken
->max_length
!= MONO_PUBLIC_KEY_TOKEN_LENGTH
- 1) {
5006 g_error ("Public key token length invalid for assembly %s: %i", assembly
->assembly
.aname
.name
, assemblyb
->pktoken
->max_length
);
5008 memcpy (&assembly
->assembly
.aname
.public_key_token
, mono_array_addr (assemblyb
->pktoken
, guint8
, 0), assemblyb
->pktoken
->max_length
);
5011 mono_domain_assemblies_lock (domain
);
5012 domain
->domain_assemblies
= g_slist_prepend (domain
->domain_assemblies
, assembly
);
5013 mono_domain_assemblies_unlock (domain
);
5015 register_assembly (mono_object_domain (assemblyb
), &assemblyb
->assembly
, &assembly
->assembly
);
5017 mono_profiler_assembly_loaded (&assembly
->assembly
, MONO_PROFILE_OK
);
5019 mono_assembly_invoke_load_hook ((MonoAssembly
*)assembly
);
5022 #endif /* !DISABLE_REFLECTION_EMIT */
5024 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5027 calc_section_size (MonoDynamicImage
*assembly
)
5031 /* alignment constraints */
5032 mono_image_add_stream_zero (&assembly
->code
, 4 - (assembly
->code
.index
% 4));
5033 g_assert ((assembly
->code
.index
% 4) == 0);
5034 assembly
->meta_size
+= 3;
5035 assembly
->meta_size
&= ~3;
5036 mono_image_add_stream_zero (&assembly
->resources
, 4 - (assembly
->resources
.index
% 4));
5037 g_assert ((assembly
->resources
.index
% 4) == 0);
5039 assembly
->sections
[MONO_SECTION_TEXT
].size
= assembly
->meta_size
+ assembly
->code
.index
+ assembly
->resources
.index
+ assembly
->strong_name_size
;
5040 assembly
->sections
[MONO_SECTION_TEXT
].attrs
= SECT_FLAGS_HAS_CODE
| SECT_FLAGS_MEM_EXECUTE
| SECT_FLAGS_MEM_READ
;
5043 if (assembly
->win32_res
) {
5044 guint32 res_size
= (assembly
->win32_res_size
+ 3) & ~3;
5046 assembly
->sections
[MONO_SECTION_RSRC
].size
= res_size
;
5047 assembly
->sections
[MONO_SECTION_RSRC
].attrs
= SECT_FLAGS_HAS_INITIALIZED_DATA
| SECT_FLAGS_MEM_READ
;
5051 assembly
->sections
[MONO_SECTION_RELOC
].size
= 12;
5052 assembly
->sections
[MONO_SECTION_RELOC
].attrs
= SECT_FLAGS_MEM_READ
| SECT_FLAGS_MEM_DISCARDABLE
| SECT_FLAGS_HAS_INITIALIZED_DATA
;
5062 MonoReflectionWin32Resource
*win32_res
; /* Only for leaf nodes */
5066 resource_tree_compare_by_id (gconstpointer a
, gconstpointer b
)
5068 ResTreeNode
*t1
= (ResTreeNode
*)a
;
5069 ResTreeNode
*t2
= (ResTreeNode
*)b
;
5071 return t1
->id
- t2
->id
;
5075 * resource_tree_create:
5077 * Organize the resources into a resource tree.
5079 static ResTreeNode
*
5080 resource_tree_create (MonoArray
*win32_resources
)
5082 ResTreeNode
*tree
, *res_node
, *type_node
, *lang_node
;
5086 tree
= g_new0 (ResTreeNode
, 1);
5088 for (i
= 0; i
< mono_array_length (win32_resources
); ++i
) {
5089 MonoReflectionWin32Resource
*win32_res
=
5090 (MonoReflectionWin32Resource
*)mono_array_addr (win32_resources
, MonoReflectionWin32Resource
, i
);
5094 /* FIXME: BUG: this stores managed references in unmanaged memory */
5095 lang_node
= g_new0 (ResTreeNode
, 1);
5096 lang_node
->id
= win32_res
->lang_id
;
5097 lang_node
->win32_res
= win32_res
;
5099 /* Create type node if neccesary */
5101 for (l
= tree
->children
; l
; l
= l
->next
)
5102 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_type
) {
5103 type_node
= (ResTreeNode
*)l
->data
;
5108 type_node
= g_new0 (ResTreeNode
, 1);
5109 type_node
->id
= win32_res
->res_type
;
5112 * The resource types have to be sorted otherwise
5113 * Windows Explorer can't display the version information.
5115 tree
->children
= g_slist_insert_sorted (tree
->children
,
5116 type_node
, resource_tree_compare_by_id
);
5119 /* Create res node if neccesary */
5121 for (l
= type_node
->children
; l
; l
= l
->next
)
5122 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_id
) {
5123 res_node
= (ResTreeNode
*)l
->data
;
5128 res_node
= g_new0 (ResTreeNode
, 1);
5129 res_node
->id
= win32_res
->res_id
;
5130 type_node
->children
= g_slist_append (type_node
->children
, res_node
);
5133 res_node
->children
= g_slist_append (res_node
->children
, lang_node
);
5140 * resource_tree_encode:
5142 * Encode the resource tree into the format used in the PE file.
5145 resource_tree_encode (ResTreeNode
*node
, char *begin
, char *p
, char **endbuf
)
5148 MonoPEResourceDir dir
;
5149 MonoPEResourceDirEntry dir_entry
;
5150 MonoPEResourceDataEntry data_entry
;
5152 guint32 res_id_entries
;
5155 * For the format of the resource directory, see the article
5156 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5160 memset (&dir
, 0, sizeof (dir
));
5161 memset (&dir_entry
, 0, sizeof (dir_entry
));
5162 memset (&data_entry
, 0, sizeof (data_entry
));
5164 g_assert (sizeof (dir
) == 16);
5165 g_assert (sizeof (dir_entry
) == 8);
5166 g_assert (sizeof (data_entry
) == 16);
5168 node
->offset
= p
- begin
;
5170 /* IMAGE_RESOURCE_DIRECTORY */
5171 res_id_entries
= g_slist_length (node
->children
);
5172 dir
.res_id_entries
= GUINT16_TO_LE (res_id_entries
);
5174 memcpy (p
, &dir
, sizeof (dir
));
5177 /* Reserve space for entries */
5179 p
+= sizeof (dir_entry
) * res_id_entries
;
5181 /* Write children */
5182 for (l
= node
->children
; l
; l
= l
->next
) {
5183 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5185 if (child
->win32_res
) {
5188 child
->offset
= p
- begin
;
5190 /* IMAGE_RESOURCE_DATA_ENTRY */
5191 data_entry
.rde_data_offset
= GUINT32_TO_LE (p
- begin
+ sizeof (data_entry
));
5192 size
= mono_array_length (child
->win32_res
->res_data
);
5193 data_entry
.rde_size
= GUINT32_TO_LE (size
);
5195 memcpy (p
, &data_entry
, sizeof (data_entry
));
5196 p
+= sizeof (data_entry
);
5198 memcpy (p
, mono_array_addr (child
->win32_res
->res_data
, char, 0), size
);
5201 resource_tree_encode (child
, begin
, p
, &p
);
5205 /* IMAGE_RESOURCE_ENTRY */
5206 for (l
= node
->children
; l
; l
= l
->next
) {
5207 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5209 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry
, FALSE
, child
->id
);
5210 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry
, !child
->win32_res
, child
->offset
);
5212 memcpy (entries
, &dir_entry
, sizeof (dir_entry
));
5213 entries
+= sizeof (dir_entry
);
5220 resource_tree_free (ResTreeNode
* node
)
5223 for (list
= node
->children
; list
; list
= list
->next
)
5224 resource_tree_free ((ResTreeNode
*)list
->data
);
5225 g_slist_free(node
->children
);
5230 assembly_add_win32_resources (MonoDynamicImage
*assembly
, MonoReflectionAssemblyBuilder
*assemblyb
)
5235 MonoReflectionWin32Resource
*win32_res
;
5238 if (!assemblyb
->win32_resources
)
5242 * Resources are stored in a three level tree inside the PE file.
5243 * - level one contains a node for each type of resource
5244 * - level two contains a node for each resource
5245 * - level three contains a node for each instance of a resource for a
5246 * specific language.
5249 tree
= resource_tree_create (assemblyb
->win32_resources
);
5251 /* Estimate the size of the encoded tree */
5253 for (i
= 0; i
< mono_array_length (assemblyb
->win32_resources
); ++i
) {
5254 win32_res
= (MonoReflectionWin32Resource
*)mono_array_addr (assemblyb
->win32_resources
, MonoReflectionWin32Resource
, i
);
5255 size
+= mono_array_length (win32_res
->res_data
);
5257 /* Directory structure */
5258 size
+= mono_array_length (assemblyb
->win32_resources
) * 256;
5259 p
= buf
= g_malloc (size
);
5261 resource_tree_encode (tree
, p
, p
, &p
);
5263 g_assert (p
- buf
<= size
);
5265 assembly
->win32_res
= g_malloc (p
- buf
);
5266 assembly
->win32_res_size
= p
- buf
;
5267 memcpy (assembly
->win32_res
, buf
, p
- buf
);
5270 resource_tree_free (tree
);
5274 fixup_resource_directory (char *res_section
, char *p
, guint32 rva
)
5276 MonoPEResourceDir
*dir
= (MonoPEResourceDir
*)p
;
5279 p
+= sizeof (MonoPEResourceDir
);
5280 for (i
= 0; i
< GUINT16_FROM_LE (dir
->res_named_entries
) + GUINT16_FROM_LE (dir
->res_id_entries
); ++i
) {
5281 MonoPEResourceDirEntry
*dir_entry
= (MonoPEResourceDirEntry
*)p
;
5282 char *child
= res_section
+ MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry
);
5283 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry
)) {
5284 fixup_resource_directory (res_section
, child
, rva
);
5286 MonoPEResourceDataEntry
*data_entry
= (MonoPEResourceDataEntry
*)child
;
5287 data_entry
->rde_data_offset
= GUINT32_TO_LE (GUINT32_FROM_LE (data_entry
->rde_data_offset
) + rva
);
5290 p
+= sizeof (MonoPEResourceDirEntry
);
5295 checked_write_file (HANDLE f
, gconstpointer buffer
, guint32 numbytes
)
5298 if (!WriteFile (f
, buffer
, numbytes
, &dummy
, NULL
))
5299 g_error ("WriteFile returned %d\n", GetLastError ());
5303 * mono_image_create_pefile:
5304 * @mb: a module builder object
5306 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5307 * assembly->pefile where it can be easily retrieved later in chunks.
5310 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5312 MonoMSDOSHeader
*msdos
;
5313 MonoDotNetHeader
*header
;
5314 MonoSectionTable
*section
;
5315 MonoCLIHeader
*cli_header
;
5316 guint32 size
, image_size
, virtual_base
, text_offset
;
5317 guint32 header_start
, section_start
, file_offset
, virtual_offset
;
5318 MonoDynamicImage
*assembly
;
5319 MonoReflectionAssemblyBuilder
*assemblyb
;
5320 MonoDynamicStream pefile_stream
= {0};
5321 MonoDynamicStream
*pefile
= &pefile_stream
;
5323 guint32
*rva
, value
;
5325 static const unsigned char msheader
[] = {
5326 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5327 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5328 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5329 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5330 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5331 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5332 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5333 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5336 assemblyb
= mb
->assemblyb
;
5338 mono_image_basic_init (assemblyb
);
5339 assembly
= mb
->dynamic_image
;
5341 assembly
->pe_kind
= assemblyb
->pe_kind
;
5342 assembly
->machine
= assemblyb
->machine
;
5343 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->pe_kind
= assemblyb
->pe_kind
;
5344 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->machine
= assemblyb
->machine
;
5346 mono_image_build_metadata (mb
);
5348 if (mb
->is_main
&& assemblyb
->resources
) {
5349 int len
= mono_array_length (assemblyb
->resources
);
5350 for (i
= 0; i
< len
; ++i
)
5351 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (assemblyb
->resources
, MonoReflectionResource
, i
));
5354 if (mb
->resources
) {
5355 int len
= mono_array_length (mb
->resources
);
5356 for (i
= 0; i
< len
; ++i
)
5357 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (mb
->resources
, MonoReflectionResource
, i
));
5360 build_compressed_metadata (assembly
);
5363 assembly_add_win32_resources (assembly
, assemblyb
);
5365 nsections
= calc_section_size (assembly
);
5367 /* The DOS header and stub */
5368 g_assert (sizeof (MonoMSDOSHeader
) == sizeof (msheader
));
5369 mono_image_add_stream_data (pefile
, (char*)msheader
, sizeof (msheader
));
5371 /* the dotnet header */
5372 header_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoDotNetHeader
));
5374 /* the section tables */
5375 section_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoSectionTable
) * nsections
);
5377 file_offset
= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5378 virtual_offset
= VIRT_ALIGN
;
5381 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5382 if (!assembly
->sections
[i
].size
)
5385 file_offset
+= FILE_ALIGN
- 1;
5386 file_offset
&= ~(FILE_ALIGN
- 1);
5387 virtual_offset
+= VIRT_ALIGN
- 1;
5388 virtual_offset
&= ~(VIRT_ALIGN
- 1);
5390 assembly
->sections
[i
].offset
= file_offset
;
5391 assembly
->sections
[i
].rva
= virtual_offset
;
5393 file_offset
+= assembly
->sections
[i
].size
;
5394 virtual_offset
+= assembly
->sections
[i
].size
;
5395 image_size
+= (assembly
->sections
[i
].size
+ VIRT_ALIGN
- 1) & ~(VIRT_ALIGN
- 1);
5398 file_offset
+= FILE_ALIGN
- 1;
5399 file_offset
&= ~(FILE_ALIGN
- 1);
5401 image_size
+= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5403 /* back-patch info */
5404 msdos
= (MonoMSDOSHeader
*)pefile
->data
;
5405 msdos
->pe_offset
= GUINT32_FROM_LE (sizeof (MonoMSDOSHeader
));
5407 header
= (MonoDotNetHeader
*)(pefile
->data
+ header_start
);
5408 header
->pesig
[0] = 'P';
5409 header
->pesig
[1] = 'E';
5411 header
->coff
.coff_machine
= GUINT16_FROM_LE (assemblyb
->machine
);
5412 header
->coff
.coff_sections
= GUINT16_FROM_LE (nsections
);
5413 header
->coff
.coff_time
= GUINT32_FROM_LE (time (NULL
));
5414 header
->coff
.coff_opt_header_size
= GUINT16_FROM_LE (sizeof (MonoDotNetHeader
) - sizeof (MonoCOFFHeader
) - 4);
5415 if (assemblyb
->pekind
== 1) {
5417 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x210e);
5420 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x010e);
5423 virtual_base
= 0x400000; /* FIXME: 0x10000000 if a DLL */
5425 header
->pe
.pe_magic
= GUINT16_FROM_LE (0x10B);
5426 header
->pe
.pe_major
= 6;
5427 header
->pe
.pe_minor
= 0;
5428 size
= assembly
->sections
[MONO_SECTION_TEXT
].size
;
5429 size
+= FILE_ALIGN
- 1;
5430 size
&= ~(FILE_ALIGN
- 1);
5431 header
->pe
.pe_code_size
= GUINT32_FROM_LE(size
);
5432 size
= assembly
->sections
[MONO_SECTION_RSRC
].size
;
5433 size
+= FILE_ALIGN
- 1;
5434 size
&= ~(FILE_ALIGN
- 1);
5435 header
->pe
.pe_data_size
= GUINT32_FROM_LE(size
);
5436 g_assert (START_TEXT_RVA
== assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5437 header
->pe
.pe_rva_code_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5438 header
->pe
.pe_rva_data_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5439 /* pe_rva_entry_point always at the beginning of the text section */
5440 header
->pe
.pe_rva_entry_point
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5442 header
->nt
.pe_image_base
= GUINT32_FROM_LE (virtual_base
);
5443 header
->nt
.pe_section_align
= GUINT32_FROM_LE (VIRT_ALIGN
);
5444 header
->nt
.pe_file_alignment
= GUINT32_FROM_LE (FILE_ALIGN
);
5445 header
->nt
.pe_os_major
= GUINT16_FROM_LE (4);
5446 header
->nt
.pe_os_minor
= GUINT16_FROM_LE (0);
5447 header
->nt
.pe_subsys_major
= GUINT16_FROM_LE (4);
5448 size
= section_start
;
5449 size
+= FILE_ALIGN
- 1;
5450 size
&= ~(FILE_ALIGN
- 1);
5451 header
->nt
.pe_header_size
= GUINT32_FROM_LE (size
);
5453 size
+= VIRT_ALIGN
- 1;
5454 size
&= ~(VIRT_ALIGN
- 1);
5455 header
->nt
.pe_image_size
= GUINT32_FROM_LE (size
);
5458 // Translate the PEFileKind value to the value expected by the Windows loader
5464 // PEFileKinds.Dll == 1
5465 // PEFileKinds.ConsoleApplication == 2
5466 // PEFileKinds.WindowApplication == 3
5469 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5470 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5472 if (assemblyb
->pekind
== 3)
5477 header
->nt
.pe_subsys_required
= GUINT16_FROM_LE (kind
);
5479 header
->nt
.pe_stack_reserve
= GUINT32_FROM_LE (0x00100000);
5480 header
->nt
.pe_stack_commit
= GUINT32_FROM_LE (0x00001000);
5481 header
->nt
.pe_heap_reserve
= GUINT32_FROM_LE (0x00100000);
5482 header
->nt
.pe_heap_commit
= GUINT32_FROM_LE (0x00001000);
5483 header
->nt
.pe_loader_flags
= GUINT32_FROM_LE (0);
5484 header
->nt
.pe_data_dir_count
= GUINT32_FROM_LE (16);
5486 /* fill data directory entries */
5488 header
->datadir
.pe_resource_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].size
);
5489 header
->datadir
.pe_resource_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5491 header
->datadir
.pe_reloc_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].size
);
5492 header
->datadir
.pe_reloc_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].rva
);
5494 header
->datadir
.pe_cli_header
.size
= GUINT32_FROM_LE (72);
5495 header
->datadir
.pe_cli_header
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->cli_header_offset
);
5496 header
->datadir
.pe_iat
.size
= GUINT32_FROM_LE (8);
5497 header
->datadir
.pe_iat
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5498 /* patch entrypoint name */
5499 if (assemblyb
->pekind
== 1)
5500 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorDllMain", 12);
5502 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorExeMain", 12);
5503 /* patch imported function RVA name */
5504 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->iat_offset
);
5505 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
);
5507 /* the import table */
5508 header
->datadir
.pe_import_table
.size
= GUINT32_FROM_LE (79); /* FIXME: magic number? */
5509 header
->datadir
.pe_import_table
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->idt_offset
);
5510 /* patch imported dll RVA name and other entries in the dir */
5511 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, name_rva
));
5512 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
+ 14); /* 14 is hint+strlen+1 of func name */
5513 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_address_table_rva
));
5514 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5515 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_lookup_table
));
5516 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->ilt_offset
);
5518 p
= (guchar
*)(assembly
->code
.data
+ assembly
->ilt_offset
);
5519 value
= (assembly
->text_rva
+ assembly
->imp_names_offset
);
5520 *p
++ = (value
) & 0xff;
5521 *p
++ = (value
>> 8) & (0xff);
5522 *p
++ = (value
>> 16) & (0xff);
5523 *p
++ = (value
>> 24) & (0xff);
5525 /* the CLI header info */
5526 cli_header
= (MonoCLIHeader
*)(assembly
->code
.data
+ assembly
->cli_header_offset
);
5527 cli_header
->ch_size
= GUINT32_FROM_LE (72);
5528 cli_header
->ch_runtime_major
= GUINT16_FROM_LE (2);
5529 if (mono_framework_version () > 1)
5530 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (5);
5532 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (0);
5533 cli_header
->ch_flags
= GUINT32_FROM_LE (assemblyb
->pe_kind
);
5534 if (assemblyb
->entry_point
) {
5535 guint32 table_idx
= 0;
5536 if (!strcmp (assemblyb
->entry_point
->object
.vtable
->klass
->name
, "MethodBuilder")) {
5537 MonoReflectionMethodBuilder
*methodb
= (MonoReflectionMethodBuilder
*)assemblyb
->entry_point
;
5538 table_idx
= methodb
->table_idx
;
5540 table_idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, assemblyb
->entry_point
->method
));
5542 cli_header
->ch_entry_point
= GUINT32_FROM_LE (table_idx
| MONO_TOKEN_METHOD_DEF
);
5544 cli_header
->ch_entry_point
= GUINT32_FROM_LE (0);
5546 /* The embedded managed resources */
5547 text_offset
= assembly
->text_rva
+ assembly
->code
.index
;
5548 cli_header
->ch_resources
.rva
= GUINT32_FROM_LE (text_offset
);
5549 cli_header
->ch_resources
.size
= GUINT32_FROM_LE (assembly
->resources
.index
);
5550 text_offset
+= assembly
->resources
.index
;
5551 cli_header
->ch_metadata
.rva
= GUINT32_FROM_LE (text_offset
);
5552 cli_header
->ch_metadata
.size
= GUINT32_FROM_LE (assembly
->meta_size
);
5553 text_offset
+= assembly
->meta_size
;
5554 if (assembly
->strong_name_size
) {
5555 cli_header
->ch_strong_name
.rva
= GUINT32_FROM_LE (text_offset
);
5556 cli_header
->ch_strong_name
.size
= GUINT32_FROM_LE (assembly
->strong_name_size
);
5557 text_offset
+= assembly
->strong_name_size
;
5560 /* write the section tables and section content */
5561 section
= (MonoSectionTable
*)(pefile
->data
+ section_start
);
5562 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5563 static const char section_names
[][7] = {
5564 ".text", ".rsrc", ".reloc"
5566 if (!assembly
->sections
[i
].size
)
5568 strcpy (section
->st_name
, section_names
[i
]);
5569 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5570 section
->st_virtual_address
= GUINT32_FROM_LE (assembly
->sections
[i
].rva
);
5571 section
->st_virtual_size
= GUINT32_FROM_LE (assembly
->sections
[i
].size
);
5572 section
->st_raw_data_size
= GUINT32_FROM_LE (GUINT32_TO_LE (section
->st_virtual_size
) + (FILE_ALIGN
- 1));
5573 section
->st_raw_data_size
&= GUINT32_FROM_LE (~(FILE_ALIGN
- 1));
5574 section
->st_raw_data_ptr
= GUINT32_FROM_LE (assembly
->sections
[i
].offset
);
5575 section
->st_flags
= GUINT32_FROM_LE (assembly
->sections
[i
].attrs
);
5579 checked_write_file (file
, pefile
->data
, pefile
->index
);
5581 mono_dynamic_stream_reset (pefile
);
5583 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5584 if (!assembly
->sections
[i
].size
)
5587 if (SetFilePointer (file
, assembly
->sections
[i
].offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5588 g_error ("SetFilePointer returned %d\n", GetLastError ());
5591 case MONO_SECTION_TEXT
:
5592 /* patch entry point */
5593 p
= (guchar
*)(assembly
->code
.data
+ 2);
5594 value
= (virtual_base
+ assembly
->text_rva
+ assembly
->iat_offset
);
5595 *p
++ = (value
) & 0xff;
5596 *p
++ = (value
>> 8) & 0xff;
5597 *p
++ = (value
>> 16) & 0xff;
5598 *p
++ = (value
>> 24) & 0xff;
5600 checked_write_file (file
, assembly
->code
.data
, assembly
->code
.index
);
5601 checked_write_file (file
, assembly
->resources
.data
, assembly
->resources
.index
);
5602 checked_write_file (file
, assembly
->image
.raw_metadata
, assembly
->meta_size
);
5603 checked_write_file (file
, assembly
->strong_name
, assembly
->strong_name_size
);
5606 g_free (assembly
->image
.raw_metadata
);
5608 case MONO_SECTION_RELOC
: {
5612 guint16 type_and_offset
;
5616 g_assert (sizeof (reloc
) == 12);
5618 reloc
.page_rva
= GUINT32_FROM_LE (assembly
->text_rva
);
5619 reloc
.block_size
= GUINT32_FROM_LE (12);
5622 * the entrypoint is always at the start of the text section
5623 * 3 is IMAGE_REL_BASED_HIGHLOW
5624 * 2 is patch_size_rva - text_rva
5626 reloc
.type_and_offset
= GUINT16_FROM_LE ((3 << 12) + (2));
5629 checked_write_file (file
, &reloc
, sizeof (reloc
));
5633 case MONO_SECTION_RSRC
:
5634 if (assembly
->win32_res
) {
5636 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5637 fixup_resource_directory (assembly
->win32_res
, assembly
->win32_res
, assembly
->sections
[i
].rva
);
5638 checked_write_file (file
, assembly
->win32_res
, assembly
->win32_res_size
);
5642 g_assert_not_reached ();
5646 /* check that the file is properly padded */
5647 if (SetFilePointer (file
, file_offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5648 g_error ("SetFilePointer returned %d\n", GetLastError ());
5649 if (! SetEndOfFile (file
))
5650 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5652 mono_dynamic_stream_reset (&assembly
->code
);
5653 mono_dynamic_stream_reset (&assembly
->us
);
5654 mono_dynamic_stream_reset (&assembly
->blob
);
5655 mono_dynamic_stream_reset (&assembly
->guid
);
5656 mono_dynamic_stream_reset (&assembly
->sheap
);
5658 g_hash_table_foreach (assembly
->blob_cache
, (GHFunc
)g_free
, NULL
);
5659 g_hash_table_destroy (assembly
->blob_cache
);
5660 assembly
->blob_cache
= NULL
;
5663 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5666 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5668 g_assert_not_reached ();
5671 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5673 #ifndef DISABLE_REFLECTION_EMIT
5675 MonoReflectionModule
*
5676 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
5680 MonoImageOpenStatus status
;
5681 MonoDynamicAssembly
*assembly
;
5682 guint32 module_count
;
5683 MonoImage
**new_modules
;
5684 gboolean
*new_modules_loaded
;
5686 name
= mono_string_to_utf8 (fileName
);
5688 image
= mono_image_open (name
, &status
);
5691 if (status
== MONO_IMAGE_ERROR_ERRNO
)
5692 exc
= mono_get_exception_file_not_found (fileName
);
5694 exc
= mono_get_exception_bad_image_format (name
);
5696 mono_raise_exception (exc
);
5701 assembly
= ab
->dynamic_assembly
;
5702 image
->assembly
= (MonoAssembly
*)assembly
;
5704 module_count
= image
->assembly
->image
->module_count
;
5705 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5706 new_modules_loaded
= g_new0 (gboolean
, module_count
+ 1);
5708 if (image
->assembly
->image
->modules
)
5709 memcpy (new_modules
, image
->assembly
->image
->modules
, module_count
* sizeof (MonoImage
*));
5710 if (image
->assembly
->image
->modules_loaded
)
5711 memcpy (new_modules_loaded
, image
->assembly
->image
->modules_loaded
, module_count
* sizeof (gboolean
));
5712 new_modules
[module_count
] = image
;
5713 new_modules_loaded
[module_count
] = TRUE
;
5714 mono_image_addref (image
);
5716 g_free (image
->assembly
->image
->modules
);
5717 image
->assembly
->image
->modules
= new_modules
;
5718 image
->assembly
->image
->modules_loaded
= new_modules_loaded
;
5719 image
->assembly
->image
->module_count
++;
5721 mono_assembly_load_references (image
, &status
);
5723 mono_image_close (image
);
5724 mono_raise_exception (mono_get_exception_file_not_found (fileName
));
5727 return mono_module_get_object (mono_domain_get (), image
);
5730 #endif /* DISABLE_REFLECTION_EMIT */
5733 * We need to return always the same object for MethodInfo, FieldInfo etc..
5734 * but we need to consider the reflected type.
5735 * type uses a different hash, since it uses custom hash/equal functions.
5740 MonoClass
*refclass
;
5744 reflected_equal (gconstpointer a
, gconstpointer b
) {
5745 const ReflectedEntry
*ea
= a
;
5746 const ReflectedEntry
*eb
= b
;
5748 return (ea
->item
== eb
->item
) && (ea
->refclass
== eb
->refclass
);
5752 reflected_hash (gconstpointer a
) {
5753 const ReflectedEntry
*ea
= a
;
5754 return mono_aligned_addr_hash (ea
->item
);
5757 #define CHECK_OBJECT(t,p,k) \
5763 mono_domain_lock (domain); \
5764 if (!domain->refobject_hash) \
5765 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5766 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5767 mono_domain_unlock (domain); \
5770 mono_domain_unlock (domain); \
5773 #ifdef HAVE_BOEHM_GC
5774 /* ReflectedEntry doesn't need to be GC tracked */
5775 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5776 #define FREE_REFENTRY(entry) g_free ((entry))
5777 #define REFENTRY_REQUIRES_CLEANUP
5779 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5781 #define FREE_REFENTRY(entry)
5784 #define CACHE_OBJECT(t,p,o,k) \
5787 ReflectedEntry pe; \
5789 pe.refclass = (k); \
5790 mono_domain_lock (domain); \
5791 if (!domain->refobject_hash) \
5792 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5793 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5795 ReflectedEntry *e = ALLOC_REFENTRY; \
5797 e->refclass = (k); \
5798 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5801 mono_domain_unlock (domain); \
5806 clear_cached_object (MonoDomain
*domain
, gpointer o
, MonoClass
*klass
)
5808 mono_domain_lock (domain
);
5809 if (domain
->refobject_hash
) {
5811 gpointer orig_pe
, orig_value
;
5814 pe
.refclass
= klass
;
5815 if (mono_g_hash_table_lookup_extended (domain
->refobject_hash
, &pe
, &orig_pe
, &orig_value
)) {
5816 mono_g_hash_table_remove (domain
->refobject_hash
, &pe
);
5817 FREE_REFENTRY (orig_pe
);
5820 mono_domain_unlock (domain
);
5823 #ifdef REFENTRY_REQUIRES_CLEANUP
5825 cleanup_refobject_hash (gpointer key
, gpointer value
, gpointer user_data
)
5827 FREE_REFENTRY (key
);
5832 mono_reflection_cleanup_domain (MonoDomain
*domain
)
5834 if (domain
->refobject_hash
) {
5835 /*let's avoid scanning the whole hashtable if not needed*/
5836 #ifdef REFENTRY_REQUIRES_CLEANUP
5837 mono_g_hash_table_foreach (domain
->refobject_hash
, cleanup_refobject_hash
, NULL
);
5839 mono_g_hash_table_destroy (domain
->refobject_hash
);
5840 domain
->refobject_hash
= NULL
;
5844 #ifndef DISABLE_REFLECTION_EMIT
5846 register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
)
5848 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
5852 register_module (MonoDomain
*domain
, MonoReflectionModuleBuilder
*res
, MonoDynamicImage
*module
)
5854 CACHE_OBJECT (MonoReflectionModuleBuilder
*, module
, res
, NULL
);
5858 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
5860 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
5861 MonoReflectionAssemblyBuilder
*ab
= moduleb
->assemblyb
;
5864 MonoImage
**new_modules
;
5867 * FIXME: we already created an image in mono_image_basic_init (), but
5868 * we don't know which module it belongs to, since that is only
5869 * determined at assembly save time.
5871 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5872 image
= create_dynamic_mono_image (ab
->dynamic_assembly
, mono_string_to_utf8 (ab
->name
), mono_string_to_utf8 (moduleb
->module
.fqname
));
5874 moduleb
->module
.image
= &image
->image
;
5875 moduleb
->dynamic_image
= image
;
5876 register_module (mono_object_domain (moduleb
), moduleb
, image
);
5878 /* register the module with the assembly */
5879 ass
= ab
->dynamic_assembly
->assembly
.image
;
5880 module_count
= ass
->module_count
;
5881 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5884 memcpy (new_modules
, ass
->modules
, module_count
* sizeof (MonoImage
*));
5885 new_modules
[module_count
] = &image
->image
;
5886 mono_image_addref (&image
->image
);
5888 g_free (ass
->modules
);
5889 ass
->modules
= new_modules
;
5890 ass
->module_count
++;
5895 mono_image_set_wrappers_type (MonoReflectionModuleBuilder
*moduleb
, MonoReflectionType
*type
)
5897 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
5899 g_assert (type
->type
);
5900 image
->wrappers_type
= mono_class_from_mono_type (type
->type
);
5906 * mono_assembly_get_object:
5907 * @domain: an app domain
5908 * @assembly: an assembly
5910 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5912 MonoReflectionAssembly
*
5913 mono_assembly_get_object (MonoDomain
*domain
, MonoAssembly
*assembly
)
5915 static MonoClass
*System_Reflection_Assembly
;
5916 MonoReflectionAssembly
*res
;
5918 CHECK_OBJECT (MonoReflectionAssembly
*, assembly
, NULL
);
5919 if (!System_Reflection_Assembly
)
5920 System_Reflection_Assembly
= mono_class_from_name (
5921 mono_defaults
.corlib
, "System.Reflection", "Assembly");
5922 res
= (MonoReflectionAssembly
*)mono_object_new (domain
, System_Reflection_Assembly
);
5923 res
->assembly
= assembly
;
5925 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
5930 MonoReflectionModule
*
5931 mono_module_get_object (MonoDomain
*domain
, MonoImage
*image
)
5933 static MonoClass
*System_Reflection_Module
;
5934 MonoReflectionModule
*res
;
5937 CHECK_OBJECT (MonoReflectionModule
*, image
, NULL
);
5938 if (!System_Reflection_Module
)
5939 System_Reflection_Module
= mono_class_from_name (
5940 mono_defaults
.corlib
, "System.Reflection", "Module");
5941 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
5944 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
5946 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, image
->name
));
5947 basename
= g_path_get_basename (image
->name
);
5948 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, basename
));
5949 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, image
->module_name
));
5953 if (image
->assembly
->image
== image
) {
5954 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULE
, 1);
5958 if (image
->assembly
->image
->modules
) {
5959 for (i
= 0; i
< image
->assembly
->image
->module_count
; i
++) {
5960 if (image
->assembly
->image
->modules
[i
] == image
)
5961 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULEREF
, i
+ 1);
5963 g_assert (res
->token
);
5967 CACHE_OBJECT (MonoReflectionModule
*, image
, res
, NULL
);
5970 MonoReflectionModule
*
5971 mono_module_file_get_object (MonoDomain
*domain
, MonoImage
*image
, int table_index
)
5973 static MonoClass
*System_Reflection_Module
;
5974 MonoReflectionModule
*res
;
5975 MonoTableInfo
*table
;
5976 guint32 cols
[MONO_FILE_SIZE
];
5978 guint32 i
, name_idx
;
5981 if (!System_Reflection_Module
)
5982 System_Reflection_Module
= mono_class_from_name (
5983 mono_defaults
.corlib
, "System.Reflection", "Module");
5984 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
5986 table
= &image
->tables
[MONO_TABLE_FILE
];
5987 g_assert (table_index
< table
->rows
);
5988 mono_metadata_decode_row (table
, table_index
, cols
, MONO_FILE_SIZE
);
5991 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
5992 name
= mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]);
5994 /* Check whenever the row has a corresponding row in the moduleref table */
5995 table
= &image
->tables
[MONO_TABLE_MODULEREF
];
5996 for (i
= 0; i
< table
->rows
; ++i
) {
5997 name_idx
= mono_metadata_decode_row_col (table
, i
, MONO_MODULEREF_NAME
);
5998 val
= mono_metadata_string_heap (image
, name_idx
);
5999 if (strcmp (val
, name
) == 0)
6000 res
->image
= image
->modules
[i
];
6003 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, name
));
6004 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, name
));
6005 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, name
));
6006 res
->is_resource
= cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
;
6007 res
->token
= mono_metadata_make_token (MONO_TABLE_FILE
, table_index
+ 1);
6013 mymono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
6015 if ((t1
->type
!= t2
->type
) ||
6016 (t1
->byref
!= t2
->byref
))
6020 case MONO_TYPE_VOID
:
6021 case MONO_TYPE_BOOLEAN
:
6022 case MONO_TYPE_CHAR
:
6033 case MONO_TYPE_STRING
:
6036 case MONO_TYPE_OBJECT
:
6037 case MONO_TYPE_TYPEDBYREF
:
6039 case MONO_TYPE_VALUETYPE
:
6040 case MONO_TYPE_CLASS
:
6041 case MONO_TYPE_SZARRAY
:
6042 return t1
->data
.klass
== t2
->data
.klass
;
6044 return mymono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
);
6045 case MONO_TYPE_ARRAY
:
6046 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
6048 return t1
->data
.array
->eklass
== t2
->data
.array
->eklass
;
6049 case MONO_TYPE_GENERICINST
: {
6051 MonoGenericInst
*i1
= t1
->data
.generic_class
->context
.class_inst
;
6052 MonoGenericInst
*i2
= t2
->data
.generic_class
->context
.class_inst
;
6053 if (i1
->type_argc
!= i2
->type_argc
)
6055 if (!mono_metadata_type_equal (&t1
->data
.generic_class
->container_class
->byval_arg
,
6056 &t2
->data
.generic_class
->container_class
->byval_arg
))
6058 /* FIXME: we should probably just compare the instance pointers directly. */
6059 for (i
= 0; i
< i1
->type_argc
; ++i
) {
6060 if (!mono_metadata_type_equal (i1
->type_argv
[i
], i2
->type_argv
[i
]))
6066 case MONO_TYPE_MVAR
:
6067 return t1
->data
.generic_param
== t2
->data
.generic_param
;
6069 g_error ("implement type compare for %0x!", t1
->type
);
6077 mymono_metadata_type_hash (MonoType
*t1
)
6083 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
6085 case MONO_TYPE_VALUETYPE
:
6086 case MONO_TYPE_CLASS
:
6087 case MONO_TYPE_SZARRAY
:
6088 /* check if the distribution is good enough */
6089 return ((hash
<< 5) - hash
) ^ g_str_hash (t1
->data
.klass
->name
);
6091 return ((hash
<< 5) - hash
) ^ mymono_metadata_type_hash (t1
->data
.type
);
6092 case MONO_TYPE_GENERICINST
: {
6094 MonoGenericInst
*inst
= t1
->data
.generic_class
->context
.class_inst
;
6095 hash
+= g_str_hash (t1
->data
.generic_class
->container_class
->name
);
6097 for (i
= 0; i
< inst
->type_argc
; ++i
) {
6098 hash
+= mymono_metadata_type_hash (inst
->type_argv
[i
]);
6107 static MonoReflectionGenericClass
*
6108 mono_generic_class_get_object (MonoDomain
*domain
, MonoType
*geninst
)
6110 static MonoClass
*System_Reflection_MonoGenericClass
;
6111 MonoReflectionGenericClass
*res
;
6112 MonoClass
*klass
, *gklass
;
6114 if (!System_Reflection_MonoGenericClass
) {
6115 System_Reflection_MonoGenericClass
= mono_class_from_name (
6116 mono_defaults
.corlib
, "System.Reflection", "MonoGenericClass");
6117 g_assert (System_Reflection_MonoGenericClass
);
6120 klass
= mono_class_from_mono_type (geninst
);
6121 gklass
= klass
->generic_class
->container_class
;
6123 mono_class_init (klass
);
6126 res
= (MonoReflectionGenericClass
*) mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, System_Reflection_MonoGenericClass
), mono_class_instance_size (System_Reflection_MonoGenericClass
));
6128 res
= (MonoReflectionGenericClass
*) mono_object_new (domain
, System_Reflection_MonoGenericClass
);
6131 res
->type
.type
= geninst
;
6132 g_assert (gklass
->reflection_info
);
6133 g_assert (!strcmp (((MonoObject
*)gklass
->reflection_info
)->vtable
->klass
->name
, "TypeBuilder"));
6134 MONO_OBJECT_SETREF (res
, generic_type
, gklass
->reflection_info
);
6140 verify_safe_for_managed_space (MonoType
*type
)
6142 switch (type
->type
) {
6144 case MONO_TYPE_ARRAY
:
6145 return verify_safe_for_managed_space (&type
->data
.array
->eklass
->byval_arg
);
6147 return verify_safe_for_managed_space (type
->data
.type
);
6148 case MONO_TYPE_SZARRAY
:
6149 return verify_safe_for_managed_space (&type
->data
.klass
->byval_arg
);
6150 case MONO_TYPE_GENERICINST
: {
6151 MonoGenericInst
*inst
= type
->data
.generic_class
->inst
;
6155 for (i
= 0; i
< inst
->type_argc
; ++i
)
6156 if (!verify_safe_for_managed_space (inst
->type_argv
[i
]))
6162 case MONO_TYPE_MVAR
:
6169 * mono_type_get_object:
6170 * @domain: an app domain
6173 * Return an System.MonoType object representing the type @type.
6176 mono_type_get_object (MonoDomain
*domain
, MonoType
*type
)
6178 MonoReflectionType
*res
;
6179 MonoClass
*klass
= mono_class_from_mono_type (type
);
6181 /*we must avoid using @type as it might have come
6182 * from a mono_metadata_type_dup and the caller
6183 * expects that is can be freed.
6184 * Using the right type from
6186 type
= klass
->byval_arg
.byref
== type
->byref
? &klass
->byval_arg
: &klass
->this_arg
;
6188 /* void is very common */
6189 if (type
->type
== MONO_TYPE_VOID
&& domain
->typeof_void
)
6190 return (MonoReflectionType
*)domain
->typeof_void
;
6193 * If the vtable of the given class was already created, we can use
6194 * the MonoType from there and avoid all locking and hash table lookups.
6196 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6197 * that the resulting object is different.
6199 if (type
== &klass
->byval_arg
&& !klass
->image
->dynamic
) {
6200 MonoVTable
*vtable
= mono_class_try_get_vtable (domain
, klass
);
6201 if (vtable
&& vtable
->type
)
6202 return vtable
->type
;
6205 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6206 mono_domain_lock (domain
);
6207 if (!domain
->type_hash
)
6208 domain
->type_hash
= mono_g_hash_table_new_type ((GHashFunc
)mymono_metadata_type_hash
,
6209 (GCompareFunc
)mymono_metadata_type_equal
, MONO_HASH_VALUE_GC
);
6210 if ((res
= mono_g_hash_table_lookup (domain
->type_hash
, type
))) {
6211 mono_domain_unlock (domain
);
6212 mono_loader_unlock ();
6215 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6216 if ((type
->type
== MONO_TYPE_GENERICINST
) && type
->data
.generic_class
->is_dynamic
&& !type
->data
.generic_class
->container_class
->wastypebuilder
) {
6217 res
= (MonoReflectionType
*)mono_generic_class_get_object (domain
, type
);
6218 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6219 mono_domain_unlock (domain
);
6220 mono_loader_unlock ();
6224 if (!verify_safe_for_managed_space (type
)) {
6225 mono_domain_unlock (domain
);
6226 mono_loader_unlock ();
6227 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6230 if (klass
->reflection_info
&& !klass
->wastypebuilder
) {
6231 /* g_assert_not_reached (); */
6232 /* should this be considered an error condition? */
6234 mono_domain_unlock (domain
);
6235 mono_loader_unlock ();
6236 return klass
->reflection_info
;
6239 // FIXME: Get rid of this, do it in the icalls for Type
6240 mono_class_init (klass
);
6242 res
= (MonoReflectionType
*)mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, mono_defaults
.monotype_class
), mono_class_instance_size (mono_defaults
.monotype_class
));
6244 res
= (MonoReflectionType
*)mono_object_new (domain
, mono_defaults
.monotype_class
);
6247 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6249 if (type
->type
== MONO_TYPE_VOID
)
6250 MONO_OBJECT_SETREF (domain
, typeof_void
, res
);
6252 mono_domain_unlock (domain
);
6253 mono_loader_unlock ();
6258 * mono_method_get_object:
6259 * @domain: an app domain
6261 * @refclass: the reflected type (can be NULL)
6263 * Return an System.Reflection.MonoMethod object representing the method @method.
6265 MonoReflectionMethod
*
6266 mono_method_get_object (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
6269 * We use the same C representation for methods and constructors, but the type
6270 * name in C# is different.
6272 static MonoClass
*System_Reflection_MonoMethod
= NULL
;
6273 static MonoClass
*System_Reflection_MonoCMethod
= NULL
;
6274 static MonoClass
*System_Reflection_MonoGenericMethod
= NULL
;
6275 static MonoClass
*System_Reflection_MonoGenericCMethod
= NULL
;
6277 MonoReflectionMethod
*ret
;
6279 if (method
->is_inflated
) {
6280 MonoReflectionGenericMethod
*gret
;
6282 refclass
= method
->klass
;
6283 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6284 if ((*method
->name
== '.') && (!strcmp (method
->name
, ".ctor") || !strcmp (method
->name
, ".cctor"))) {
6285 if (!System_Reflection_MonoGenericCMethod
)
6286 System_Reflection_MonoGenericCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericCMethod");
6287 klass
= System_Reflection_MonoGenericCMethod
;
6289 if (!System_Reflection_MonoGenericMethod
)
6290 System_Reflection_MonoGenericMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericMethod");
6291 klass
= System_Reflection_MonoGenericMethod
;
6293 gret
= (MonoReflectionGenericMethod
*)mono_object_new (domain
, klass
);
6294 gret
->method
.method
= method
;
6295 MONO_OBJECT_SETREF (gret
, method
.name
, mono_string_new (domain
, method
->name
));
6296 MONO_OBJECT_SETREF (gret
, method
.reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6297 CACHE_OBJECT (MonoReflectionMethod
*, method
, (MonoReflectionMethod
*)gret
, refclass
);
6301 refclass
= method
->klass
;
6303 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6304 if (*method
->name
== '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0)) {
6305 if (!System_Reflection_MonoCMethod
)
6306 System_Reflection_MonoCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoCMethod");
6307 klass
= System_Reflection_MonoCMethod
;
6310 if (!System_Reflection_MonoMethod
)
6311 System_Reflection_MonoMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoMethod");
6312 klass
= System_Reflection_MonoMethod
;
6314 ret
= (MonoReflectionMethod
*)mono_object_new (domain
, klass
);
6315 ret
->method
= method
;
6316 MONO_OBJECT_SETREF (ret
, reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6317 CACHE_OBJECT (MonoReflectionMethod
*, method
, ret
, refclass
);
6321 * mono_method_clear_object:
6323 * Clear the cached reflection objects for the dynamic method METHOD.
6326 mono_method_clear_object (MonoDomain
*domain
, MonoMethod
*method
)
6329 g_assert (method
->dynamic
);
6331 klass
= method
->klass
;
6333 clear_cached_object (domain
, method
, klass
);
6334 klass
= klass
->parent
;
6336 /* Added by mono_param_get_objects () */
6337 clear_cached_object (domain
, &(method
->signature
), NULL
);
6338 klass
= method
->klass
;
6340 clear_cached_object (domain
, &(method
->signature
), klass
);
6341 klass
= klass
->parent
;
6346 * mono_field_get_object:
6347 * @domain: an app domain
6351 * Return an System.Reflection.MonoField object representing the field @field
6354 MonoReflectionField
*
6355 mono_field_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
)
6357 MonoReflectionField
*res
;
6358 static MonoClass
*monofield_klass
;
6360 CHECK_OBJECT (MonoReflectionField
*, field
, klass
);
6361 if (!monofield_klass
)
6362 monofield_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoField");
6363 res
= (MonoReflectionField
*)mono_object_new (domain
, monofield_klass
);
6366 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, mono_field_get_name (field
)));
6367 if (is_field_on_inst (field
))
6368 res
->attrs
= get_field_on_inst_generic_type (field
)->attrs
;
6370 res
->attrs
= field
->type
->attrs
;
6371 MONO_OBJECT_SETREF (res
, type
, mono_type_get_object (domain
, field
->type
));
6372 CACHE_OBJECT (MonoReflectionField
*, field
, res
, klass
);
6376 * mono_property_get_object:
6377 * @domain: an app domain
6379 * @property: a property
6381 * Return an System.Reflection.MonoProperty object representing the property @property
6384 MonoReflectionProperty
*
6385 mono_property_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
)
6387 MonoReflectionProperty
*res
;
6388 static MonoClass
*monoproperty_klass
;
6390 CHECK_OBJECT (MonoReflectionProperty
*, property
, klass
);
6391 if (!monoproperty_klass
)
6392 monoproperty_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoProperty");
6393 res
= (MonoReflectionProperty
*)mono_object_new (domain
, monoproperty_klass
);
6395 res
->property
= property
;
6396 CACHE_OBJECT (MonoReflectionProperty
*, property
, res
, klass
);
6400 * mono_event_get_object:
6401 * @domain: an app domain
6405 * Return an System.Reflection.MonoEvent object representing the event @event
6408 MonoReflectionEvent
*
6409 mono_event_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
)
6411 MonoReflectionEvent
*res
;
6412 MonoReflectionMonoEvent
*mono_event
;
6413 static MonoClass
*monoevent_klass
;
6415 CHECK_OBJECT (MonoReflectionEvent
*, event
, klass
);
6416 if (!monoevent_klass
)
6417 monoevent_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoEvent");
6418 mono_event
= (MonoReflectionMonoEvent
*)mono_object_new (domain
, monoevent_klass
);
6419 mono_event
->klass
= klass
;
6420 mono_event
->event
= event
;
6421 res
= (MonoReflectionEvent
*)mono_event
;
6422 CACHE_OBJECT (MonoReflectionEvent
*, event
, res
, klass
);
6426 * mono_get_reflection_missing_object:
6427 * @domain: Domain where the object lives
6429 * Returns the System.Reflection.Missing.Value singleton object
6430 * (of type System.Reflection.Missing).
6432 * Used as the value for ParameterInfo.DefaultValue when Optional
6436 mono_get_reflection_missing_object (MonoDomain
*domain
)
6439 static MonoClassField
*missing_value_field
= NULL
;
6441 if (!missing_value_field
) {
6442 MonoClass
*missing_klass
;
6443 missing_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Missing");
6444 mono_class_init (missing_klass
);
6445 missing_value_field
= mono_class_get_field_from_name (missing_klass
, "Value");
6446 g_assert (missing_value_field
);
6448 obj
= mono_field_get_value_object (domain
, missing_value_field
, NULL
);
6454 get_dbnull (MonoDomain
*domain
, MonoObject
**dbnull
)
6457 *dbnull
= mono_get_dbnull_object (domain
);
6462 get_reflection_missing (MonoDomain
*domain
, MonoObject
**reflection_missing
)
6464 if (!*reflection_missing
)
6465 *reflection_missing
= mono_get_reflection_missing_object (domain
);
6466 return *reflection_missing
;
6470 * mono_param_get_objects:
6471 * @domain: an app domain
6474 * Return an System.Reflection.ParameterInfo array object representing the parameters
6475 * in the method @method.
6478 mono_param_get_objects_internal (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
6480 static MonoClass
*System_Reflection_ParameterInfo
;
6481 static MonoClass
*System_Reflection_ParameterInfo_array
;
6482 MonoArray
*res
= NULL
;
6483 MonoReflectionMethod
*member
= NULL
;
6484 MonoReflectionParameter
*param
= NULL
;
6485 char **names
, **blobs
= NULL
;
6486 guint32
*types
= NULL
;
6487 MonoType
*type
= NULL
;
6488 MonoObject
*dbnull
= NULL
;
6489 MonoObject
*missing
= NULL
;
6490 MonoMarshalSpec
**mspecs
;
6491 MonoMethodSignature
*sig
;
6492 MonoVTable
*pinfo_vtable
;
6495 if (!System_Reflection_ParameterInfo_array
) {
6498 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ParameterInfo");
6499 mono_memory_barrier ();
6500 System_Reflection_ParameterInfo
= klass
;
6502 klass
= mono_array_class_get (klass
, 1);
6503 mono_memory_barrier ();
6504 System_Reflection_ParameterInfo_array
= klass
;
6507 if (!mono_method_signature (method
)->param_count
)
6508 return mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), 0);
6510 /* Note: the cache is based on the address of the signature into the method
6511 * since we already cache MethodInfos with the method as keys.
6513 CHECK_OBJECT (MonoArray
*, &(method
->signature
), refclass
);
6515 sig
= mono_method_signature (method
);
6516 member
= mono_method_get_object (domain
, method
, refclass
);
6517 names
= g_new (char *, sig
->param_count
);
6518 mono_method_get_param_names (method
, (const char **) names
);
6520 mspecs
= g_new (MonoMarshalSpec
*, sig
->param_count
+ 1);
6521 mono_method_get_marshal_info (method
, mspecs
);
6523 res
= mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), sig
->param_count
);
6524 pinfo_vtable
= mono_class_vtable (domain
, System_Reflection_ParameterInfo
);
6525 for (i
= 0; i
< sig
->param_count
; ++i
) {
6526 param
= (MonoReflectionParameter
*)mono_object_new_specific (pinfo_vtable
);
6527 MONO_OBJECT_SETREF (param
, ClassImpl
, mono_type_get_object (domain
, sig
->params
[i
]));
6528 MONO_OBJECT_SETREF (param
, MemberImpl
, (MonoObject
*)member
);
6529 MONO_OBJECT_SETREF (param
, NameImpl
, mono_string_new (domain
, names
[i
]));
6530 param
->PositionImpl
= i
;
6531 param
->AttrsImpl
= sig
->params
[i
]->attrs
;
6533 if (!(param
->AttrsImpl
& PARAM_ATTRIBUTE_HAS_DEFAULT
)) {
6534 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6535 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6537 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6541 blobs
= g_new0 (char *, sig
->param_count
);
6542 types
= g_new0 (guint32
, sig
->param_count
);
6543 get_default_param_value_blobs (method
, blobs
, types
);
6546 /* Build MonoType for the type from the Constant Table */
6548 type
= g_new0 (MonoType
, 1);
6549 type
->type
= types
[i
];
6550 type
->data
.klass
= NULL
;
6551 if (types
[i
] == MONO_TYPE_CLASS
)
6552 type
->data
.klass
= mono_defaults
.object_class
;
6553 else if ((sig
->params
[i
]->type
== MONO_TYPE_VALUETYPE
) && sig
->params
[i
]->data
.klass
->enumtype
) {
6554 /* For enums, types [i] contains the base type */
6556 type
->type
= MONO_TYPE_VALUETYPE
;
6557 type
->data
.klass
= mono_class_from_mono_type (sig
->params
[i
]);
6559 type
->data
.klass
= mono_class_from_mono_type (type
);
6561 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, mono_get_object_from_blob (domain
, type
, blobs
[i
]));
6563 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6564 if (types
[i
] != MONO_TYPE_CLASS
&& !param
->DefaultValueImpl
) {
6565 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6566 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6568 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6574 MONO_OBJECT_SETREF (param
, MarshalAsImpl
, (MonoObject
*)mono_reflection_marshal_from_marshal_spec (domain
, method
->klass
, mspecs
[i
+ 1]));
6576 mono_array_setref (res
, i
, param
);
6583 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
6585 mono_metadata_free_marshal_spec (mspecs
[i
]);
6588 CACHE_OBJECT (MonoArray
*, &(method
->signature
), res
, refclass
);
6592 mono_param_get_objects (MonoDomain
*domain
, MonoMethod
*method
)
6594 return mono_param_get_objects_internal (domain
, method
, NULL
);
6598 * mono_method_body_get_object:
6599 * @domain: an app domain
6602 * Return an System.Reflection.MethodBody object representing the method @method.
6604 MonoReflectionMethodBody
*
6605 mono_method_body_get_object (MonoDomain
*domain
, MonoMethod
*method
)
6607 static MonoClass
*System_Reflection_MethodBody
= NULL
;
6608 static MonoClass
*System_Reflection_LocalVariableInfo
= NULL
;
6609 static MonoClass
*System_Reflection_ExceptionHandlingClause
= NULL
;
6610 MonoReflectionMethodBody
*ret
;
6611 MonoMethodNormal
*mn
;
6612 MonoMethodHeader
*header
;
6613 guint32 method_rva
, local_var_sig_token
;
6615 unsigned char format
, flags
;
6618 if (!System_Reflection_MethodBody
)
6619 System_Reflection_MethodBody
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MethodBody");
6620 if (!System_Reflection_LocalVariableInfo
)
6621 System_Reflection_LocalVariableInfo
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "LocalVariableInfo");
6622 if (!System_Reflection_ExceptionHandlingClause
)
6623 System_Reflection_ExceptionHandlingClause
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ExceptionHandlingClause");
6625 CHECK_OBJECT (MonoReflectionMethodBody
*, method
, NULL
);
6627 if ((method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
6628 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
6629 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
6630 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
))
6632 mn
= (MonoMethodNormal
*)method
;
6633 header
= mono_method_get_header (method
);
6635 /* Obtain local vars signature token */
6636 method_rva
= mono_metadata_decode_row_col (&method
->klass
->image
->tables
[MONO_TABLE_METHOD
], mono_metadata_token_index (method
->token
) - 1, MONO_METHOD_RVA
);
6637 ptr
= mono_image_rva_map (method
->klass
->image
, method_rva
);
6638 flags
= *(const unsigned char *) ptr
;
6639 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
6641 case METHOD_HEADER_TINY_FORMAT
:
6642 case METHOD_HEADER_TINY_FORMAT1
:
6643 local_var_sig_token
= 0;
6645 case METHOD_HEADER_FAT_FORMAT
:
6649 local_var_sig_token
= read32 (ptr
);
6652 g_assert_not_reached ();
6655 ret
= (MonoReflectionMethodBody
*)mono_object_new (domain
, System_Reflection_MethodBody
);
6657 ret
->init_locals
= header
->init_locals
;
6658 ret
->max_stack
= header
->max_stack
;
6659 ret
->local_var_sig_token
= local_var_sig_token
;
6660 MONO_OBJECT_SETREF (ret
, il
, mono_array_new_cached (domain
, mono_defaults
.byte_class
, header
->code_size
));
6661 memcpy (mono_array_addr (ret
->il
, guint8
, 0), header
->code
, header
->code_size
);
6664 MONO_OBJECT_SETREF (ret
, locals
, mono_array_new_cached (domain
, System_Reflection_LocalVariableInfo
, header
->num_locals
));
6665 for (i
= 0; i
< header
->num_locals
; ++i
) {
6666 MonoReflectionLocalVariableInfo
*info
= (MonoReflectionLocalVariableInfo
*)mono_object_new (domain
, System_Reflection_LocalVariableInfo
);
6667 MONO_OBJECT_SETREF (info
, local_type
, mono_type_get_object (domain
, header
->locals
[i
]));
6668 info
->is_pinned
= header
->locals
[i
]->pinned
;
6669 info
->local_index
= i
;
6670 mono_array_setref (ret
->locals
, i
, info
);
6674 MONO_OBJECT_SETREF (ret
, clauses
, mono_array_new_cached (domain
, System_Reflection_ExceptionHandlingClause
, header
->num_clauses
));
6675 for (i
= 0; i
< header
->num_clauses
; ++i
) {
6676 MonoReflectionExceptionHandlingClause
*info
= (MonoReflectionExceptionHandlingClause
*)mono_object_new (domain
, System_Reflection_ExceptionHandlingClause
);
6677 MonoExceptionClause
*clause
= &header
->clauses
[i
];
6679 info
->flags
= clause
->flags
;
6680 info
->try_offset
= clause
->try_offset
;
6681 info
->try_length
= clause
->try_len
;
6682 info
->handler_offset
= clause
->handler_offset
;
6683 info
->handler_length
= clause
->handler_len
;
6684 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)
6685 info
->filter_offset
= clause
->data
.filter_offset
;
6686 else if (clause
->data
.catch_class
)
6687 MONO_OBJECT_SETREF (info
, catch_type
, mono_type_get_object (mono_domain_get (), &clause
->data
.catch_class
->byval_arg
));
6689 mono_array_setref (ret
->clauses
, i
, info
);
6692 CACHE_OBJECT (MonoReflectionMethodBody
*, method
, ret
, NULL
);
6697 * mono_get_dbnull_object:
6698 * @domain: Domain where the object lives
6700 * Returns the System.DBNull.Value singleton object
6702 * Used as the value for ParameterInfo.DefaultValue
6705 mono_get_dbnull_object (MonoDomain
*domain
)
6708 static MonoClassField
*dbnull_value_field
= NULL
;
6710 if (!dbnull_value_field
) {
6711 MonoClass
*dbnull_klass
;
6712 dbnull_klass
= mono_class_from_name (mono_defaults
.corlib
, "System", "DBNull");
6713 mono_class_init (dbnull_klass
);
6714 dbnull_value_field
= mono_class_get_field_from_name (dbnull_klass
, "Value");
6715 g_assert (dbnull_value_field
);
6717 obj
= mono_field_get_value_object (domain
, dbnull_value_field
, NULL
);
6723 get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
)
6725 guint32 param_index
, i
, lastp
, crow
= 0;
6726 guint32 param_cols
[MONO_PARAM_SIZE
], const_cols
[MONO_CONSTANT_SIZE
];
6729 MonoClass
*klass
= method
->klass
;
6730 MonoImage
*image
= klass
->image
;
6731 MonoMethodSignature
*methodsig
= mono_method_signature (method
);
6733 MonoTableInfo
*constt
;
6734 MonoTableInfo
*methodt
;
6735 MonoTableInfo
*paramt
;
6737 if (!methodsig
->param_count
)
6740 mono_class_init (klass
);
6742 if (klass
->image
->dynamic
) {
6743 MonoReflectionMethodAux
*aux
;
6744 if (method
->is_inflated
)
6745 method
= ((MonoMethodInflated
*)method
)->declaring
;
6746 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
6747 if (aux
&& aux
->param_defaults
) {
6748 memcpy (blobs
, &(aux
->param_defaults
[1]), methodsig
->param_count
* sizeof (char*));
6749 memcpy (types
, &(aux
->param_default_types
[1]), methodsig
->param_count
* sizeof (guint32
));
6754 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
6755 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
6756 constt
= &image
->tables
[MONO_TABLE_CONSTANT
];
6758 idx
= mono_method_get_index (method
) - 1;
6759 g_assert (idx
!= -1);
6761 param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
6762 if (idx
+ 1 < methodt
->rows
)
6763 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
6765 lastp
= paramt
->rows
+ 1;
6767 for (i
= param_index
; i
< lastp
; ++i
) {
6770 mono_metadata_decode_row (paramt
, i
- 1, param_cols
, MONO_PARAM_SIZE
);
6771 paramseq
= param_cols
[MONO_PARAM_SEQUENCE
];
6773 if (!param_cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_DEFAULT
)
6776 crow
= mono_metadata_get_constant_index (image
, MONO_TOKEN_PARAM_DEF
| i
, crow
+ 1);
6781 mono_metadata_decode_row (constt
, crow
- 1, const_cols
, MONO_CONSTANT_SIZE
);
6782 blobs
[paramseq
- 1] = (gpointer
) mono_metadata_blob_heap (image
, const_cols
[MONO_CONSTANT_VALUE
]);
6783 types
[paramseq
- 1] = const_cols
[MONO_CONSTANT_TYPE
];
6790 mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
)
6795 MonoType
*basetype
= type
;
6800 klass
= mono_class_from_mono_type (type
);
6801 if (klass
->valuetype
) {
6802 object
= mono_object_new (domain
, klass
);
6803 retval
= ((gchar
*) object
+ sizeof (MonoObject
));
6804 if (klass
->enumtype
)
6805 basetype
= mono_class_enum_basetype (klass
);
6810 if (!mono_get_constant_value_from_blob (domain
, basetype
->type
, blob
, retval
))
6817 assembly_name_to_aname (MonoAssemblyName
*assembly
, char *p
) {
6821 memset (assembly
, 0, sizeof (MonoAssemblyName
));
6823 assembly
->culture
= "";
6824 memset (assembly
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
6826 while (*p
&& (isalnum (*p
) || *p
== '.' || *p
== '-' || *p
== '_' || *p
== '$' || *p
== '@'))
6829 while (g_ascii_isspace (*p
) || *p
== ',') {
6838 if (*p
== 'V' && g_ascii_strncasecmp (p
, "Version=", 8) == 0) {
6840 assembly
->major
= strtoul (p
, &s
, 10);
6841 if (s
== p
|| *s
!= '.')
6844 assembly
->minor
= strtoul (p
, &s
, 10);
6845 if (s
== p
|| *s
!= '.')
6848 assembly
->build
= strtoul (p
, &s
, 10);
6849 if (s
== p
|| *s
!= '.')
6852 assembly
->revision
= strtoul (p
, &s
, 10);
6856 } else if (*p
== 'C' && g_ascii_strncasecmp (p
, "Culture=", 8) == 0) {
6858 if (g_ascii_strncasecmp (p
, "neutral", 7) == 0) {
6859 assembly
->culture
= "";
6862 assembly
->culture
= p
;
6863 while (*p
&& *p
!= ',') {
6867 } else if (*p
== 'P' && g_ascii_strncasecmp (p
, "PublicKeyToken=", 15) == 0) {
6869 if (strncmp (p
, "null", 4) == 0) {
6874 while (*p
&& *p
!= ',') {
6877 len
= (p
- start
+ 1);
6878 if (len
> MONO_PUBLIC_KEY_TOKEN_LENGTH
)
6879 len
= MONO_PUBLIC_KEY_TOKEN_LENGTH
;
6880 g_strlcpy ((char*)assembly
->public_key_token
, start
, len
);
6883 while (*p
&& *p
!= ',')
6887 while (g_ascii_isspace (*p
) || *p
== ',') {
6901 * mono_reflection_parse_type:
6904 * Parse a type name as accepted by the GetType () method and output the info
6905 * extracted in the info structure.
6906 * the name param will be mangled, so, make a copy before passing it to this function.
6907 * The fields in info will be valid until the memory pointed to by name is valid.
6909 * See also mono_type_get_name () below.
6911 * Returns: 0 on parse error.
6914 _mono_reflection_parse_type (char *name
, char **endptr
, gboolean is_recursed
,
6915 MonoTypeNameParse
*info
)
6917 char *start
, *p
, *w
, *temp
, *last_point
, *startn
;
6918 int in_modifiers
= 0;
6919 int isbyref
= 0, rank
, arity
= 0, i
;
6921 start
= p
= w
= name
;
6923 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6924 memset (&info
->assembly
, 0, sizeof (MonoAssemblyName
));
6925 info
->name
= info
->name_space
= NULL
;
6926 info
->nested
= NULL
;
6927 info
->modifiers
= NULL
;
6928 info
->type_arguments
= NULL
;
6930 /* last_point separates the namespace from the name */
6933 while (*p
== ' ') p
++, start
++, w
++, name
++;
6938 *p
= 0; /* NULL terminate the name */
6940 info
->nested
= g_list_append (info
->nested
, startn
);
6941 /* we have parsed the nesting namespace + name */
6945 info
->name_space
= start
;
6947 info
->name
= last_point
+ 1;
6949 info
->name_space
= (char *)"";
6968 i
= strtol (p
, &temp
, 10);
6985 info
->name_space
= start
;
6987 info
->name
= last_point
+ 1;
6989 info
->name_space
= (char *)"";
6996 if (isbyref
) /* only one level allowed by the spec */
6999 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (0));
7003 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-1));
7009 info
->type_arguments
= g_ptr_array_new ();
7010 for (i
= 0; i
< arity
; i
++) {
7011 MonoTypeNameParse
*subinfo
= g_new0 (MonoTypeNameParse
, 1);
7012 gboolean fqname
= FALSE
;
7014 g_ptr_array_add (info
->type_arguments
, subinfo
);
7021 if (!_mono_reflection_parse_type (p
, &p
, TRUE
, subinfo
))
7032 while (*p
&& (*p
!= ']'))
7040 if (g_ascii_isspace (*aname
)) {
7047 !assembly_name_to_aname (&subinfo
->assembly
, aname
))
7051 if (i
+ 1 < arity
) {
7071 else if (*p
== '*') /* '*' means unknown lower bound */
7072 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-2));
7079 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (rank
));
7090 if (g_ascii_isspace (*p
)) {
7097 return 0; /* missing assembly name */
7098 if (!assembly_name_to_aname (&info
->assembly
, p
))
7104 if (info
->assembly
.name
)
7107 // *w = 0; /* terminate class name */
7109 if (!info
->name
|| !*info
->name
)
7113 /* add other consistency checks */
7118 mono_reflection_parse_type (char *name
, MonoTypeNameParse
*info
)
7120 return _mono_reflection_parse_type (name
, NULL
, FALSE
, info
);
7124 _mono_reflection_get_type_from_info (MonoTypeNameParse
*info
, MonoImage
*image
, gboolean ignorecase
)
7126 gboolean type_resolve
= FALSE
;
7128 MonoImage
*rootimage
= image
;
7130 if (info
->assembly
.name
) {
7131 MonoAssembly
*assembly
= mono_assembly_loaded (&info
->assembly
);
7132 if (!assembly
&& image
&& image
->assembly
&& mono_assembly_names_equal (&info
->assembly
, &image
->assembly
->aname
))
7134 * This could happen in the AOT compiler case when the search hook is not
7137 assembly
= image
->assembly
;
7139 /* then we must load the assembly ourselve - see #60439 */
7140 assembly
= mono_assembly_load (&info
->assembly
, NULL
, NULL
);
7144 image
= assembly
->image
;
7145 } else if (!image
) {
7146 image
= mono_defaults
.corlib
;
7149 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7150 if (type
== NULL
&& !info
->assembly
.name
&& image
!= mono_defaults
.corlib
) {
7151 image
= mono_defaults
.corlib
;
7152 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7159 mono_reflection_get_type_internal (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7164 gboolean bounded
= FALSE
;
7167 image
= mono_defaults
.corlib
;
7170 klass
= mono_class_from_name_case (image
, info
->name_space
, info
->name
);
7172 klass
= mono_class_from_name (image
, info
->name_space
, info
->name
);
7175 for (mod
= info
->nested
; mod
; mod
= mod
->next
) {
7176 gpointer iter
= NULL
;
7180 mono_class_init (parent
);
7182 while ((klass
= mono_class_get_nested_types (parent
, &iter
))) {
7184 if (g_strcasecmp (klass
->name
, mod
->data
) == 0)
7187 if (strcmp (klass
->name
, mod
->data
) == 0)
7196 mono_class_init (klass
);
7198 if (info
->type_arguments
) {
7199 MonoType
**type_args
= g_new0 (MonoType
*, info
->type_arguments
->len
);
7200 MonoReflectionType
*the_type
;
7204 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7205 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7207 type_args
[i
] = _mono_reflection_get_type_from_info (subinfo
, rootimage
, ignorecase
);
7208 if (!type_args
[i
]) {
7214 the_type
= mono_type_get_object (mono_domain_get (), &klass
->byval_arg
);
7216 instance
= mono_reflection_bind_generic_parameters (
7217 the_type
, info
->type_arguments
->len
, type_args
);
7223 klass
= mono_class_from_mono_type (instance
);
7226 for (mod
= info
->modifiers
; mod
; mod
= mod
->next
) {
7227 modval
= GPOINTER_TO_UINT (mod
->data
);
7228 if (!modval
) { /* byref: must be last modifier */
7229 return &klass
->this_arg
;
7230 } else if (modval
== -1) {
7231 klass
= mono_ptr_class_get (&klass
->byval_arg
);
7232 } else if (modval
== -2) {
7234 } else { /* array rank */
7235 klass
= mono_bounded_array_class_get (klass
, modval
, bounded
);
7237 mono_class_init (klass
);
7240 return &klass
->byval_arg
;
7244 * mono_reflection_get_type:
7245 * @image: a metadata context
7246 * @info: type description structure
7247 * @ignorecase: flag for case-insensitive string compares
7248 * @type_resolve: whenever type resolve was already tried
7250 * Build a MonoType from the type description in @info.
7255 mono_reflection_get_type (MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
) {
7256 return mono_reflection_get_type_with_rootimage(image
, image
, info
, ignorecase
, type_resolve
);
7260 mono_reflection_get_type_internal_dynamic (MonoImage
*rootimage
, MonoAssembly
*assembly
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7262 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)mono_assembly_get_object (mono_domain_get (), assembly
);
7266 g_assert (assembly
->dynamic
);
7268 /* Enumerate all modules */
7271 if (abuilder
->modules
) {
7272 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
7273 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
7274 type
= mono_reflection_get_type_internal (rootimage
, &mb
->dynamic_image
->image
, info
, ignorecase
);
7280 if (!type
&& abuilder
->loaded_modules
) {
7281 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
7282 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
7283 type
= mono_reflection_get_type_internal (rootimage
, mod
->image
, info
, ignorecase
);
7293 mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
)
7296 MonoReflectionAssembly
*assembly
;
7300 if (image
&& image
->dynamic
)
7301 type
= mono_reflection_get_type_internal_dynamic (rootimage
, image
->assembly
, info
, ignorecase
);
7303 type
= mono_reflection_get_type_internal (rootimage
, image
, info
, ignorecase
);
7306 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7313 *type_resolve
= TRUE
;
7316 /* Reconstruct the type name */
7317 fullName
= g_string_new ("");
7318 if (info
->name_space
&& (info
->name_space
[0] != '\0'))
7319 g_string_printf (fullName
, "%s.%s", info
->name_space
, info
->name
);
7321 g_string_printf (fullName
, info
->name
);
7322 for (mod
= info
->nested
; mod
; mod
= mod
->next
)
7323 g_string_append_printf (fullName
, "+%s", (char*)mod
->data
);
7325 assembly
= mono_domain_try_type_resolve ( mono_domain_get (), fullName
->str
, NULL
);
7327 if (assembly
->assembly
->dynamic
)
7328 type
= mono_reflection_get_type_internal_dynamic (rootimage
, assembly
->assembly
, info
, ignorecase
);
7330 type
= mono_reflection_get_type_internal (rootimage
, assembly
->assembly
->image
,
7333 g_string_free (fullName
, TRUE
);
7338 mono_reflection_free_type_info (MonoTypeNameParse
*info
)
7340 g_list_free (info
->modifiers
);
7341 g_list_free (info
->nested
);
7343 if (info
->type_arguments
) {
7346 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7347 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7349 mono_reflection_free_type_info (subinfo
);
7350 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7354 g_ptr_array_free (info
->type_arguments
, TRUE
);
7359 * mono_reflection_type_from_name:
7361 * @image: a metadata context (can be NULL).
7363 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7364 * it defaults to get the type from @image or, if @image is NULL or loading
7365 * from it fails, uses corlib.
7369 mono_reflection_type_from_name (char *name
, MonoImage
*image
)
7371 MonoType
*type
= NULL
;
7372 MonoTypeNameParse info
;
7375 /* Make a copy since parse_type modifies its argument */
7376 tmp
= g_strdup (name
);
7378 /*g_print ("requested type %s\n", str);*/
7379 if (mono_reflection_parse_type (tmp
, &info
)) {
7380 type
= _mono_reflection_get_type_from_info (&info
, image
, FALSE
);
7384 mono_reflection_free_type_info (&info
);
7389 * mono_reflection_get_token:
7391 * Return the metadata token of OBJ which should be an object
7392 * representing a metadata element.
7395 mono_reflection_get_token (MonoObject
*obj
)
7400 klass
= obj
->vtable
->klass
;
7402 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
7403 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
7405 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7406 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
7407 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
7409 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7410 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
7411 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
7413 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7414 token
= mono_image_create_token (((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
, obj
, FALSE
, TRUE
);
7415 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
7416 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
7417 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
7418 } else if (strcmp (klass
->name
, "MonoType") == 0) {
7419 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
7420 token
= mono_class_from_mono_type (type
)->type_token
;
7421 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
7422 strcmp (klass
->name
, "MonoMethod") == 0 ||
7423 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
7424 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
7425 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
7426 if (m
->method
->is_inflated
) {
7427 MonoMethodInflated
*inflated
= (MonoMethodInflated
*) m
->method
;
7428 return inflated
->declaring
->token
;
7430 token
= m
->method
->token
;
7432 } else if (strcmp (klass
->name
, "MonoField") == 0) {
7433 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
7435 if (is_field_on_inst (f
->field
)) {
7436 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)f
->field
->parent
->generic_class
;
7437 int field_index
= f
->field
- dgclass
->fields
;
7440 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
7441 obj
= dgclass
->field_objects
[field_index
];
7442 return mono_reflection_get_token (obj
);
7444 token
= mono_class_get_field_token (f
->field
);
7445 } else if (strcmp (klass
->name
, "MonoProperty") == 0) {
7446 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)obj
;
7448 token
= mono_class_get_property_token (p
->property
);
7449 } else if (strcmp (klass
->name
, "MonoEvent") == 0) {
7450 MonoReflectionMonoEvent
*p
= (MonoReflectionMonoEvent
*)obj
;
7452 token
= mono_class_get_event_token (p
->event
);
7453 } else if (strcmp (klass
->name
, "ParameterInfo") == 0) {
7454 MonoReflectionParameter
*p
= (MonoReflectionParameter
*)obj
;
7456 token
= mono_method_get_param_token (((MonoReflectionMethod
*)p
->MemberImpl
)->method
, p
->PositionImpl
);
7457 } else if (strcmp (klass
->name
, "Module") == 0) {
7458 MonoReflectionModule
*m
= (MonoReflectionModule
*)obj
;
7461 } else if (strcmp (klass
->name
, "Assembly") == 0) {
7462 token
= mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1);
7464 gchar
*msg
= g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass
->name_space
, klass
->name
);
7465 MonoException
*ex
= mono_get_exception_not_implemented (msg
);
7467 mono_raise_exception (ex
);
7474 load_cattr_value (MonoImage
*image
, MonoType
*t
, const char *p
, const char **end
)
7476 int slen
, type
= t
->type
;
7477 MonoClass
*tklass
= t
->data
.klass
;
7483 case MONO_TYPE_BOOLEAN
: {
7484 MonoBoolean
*bval
= g_malloc (sizeof (MonoBoolean
));
7489 case MONO_TYPE_CHAR
:
7491 case MONO_TYPE_I2
: {
7492 guint16
*val
= g_malloc (sizeof (guint16
));
7497 #if SIZEOF_VOID_P == 4
7503 case MONO_TYPE_I4
: {
7504 guint32
*val
= g_malloc (sizeof (guint32
));
7509 #if SIZEOF_VOID_P == 8
7510 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
7514 case MONO_TYPE_I8
: {
7515 guint64
*val
= g_malloc (sizeof (guint64
));
7520 case MONO_TYPE_R8
: {
7521 double *val
= g_malloc (sizeof (double));
7526 case MONO_TYPE_VALUETYPE
:
7527 if (t
->data
.klass
->enumtype
) {
7528 type
= mono_class_enum_basetype (t
->data
.klass
)->type
;
7531 g_error ("generic valutype %s not handled in custom attr value decoding", t
->data
.klass
->name
);
7534 case MONO_TYPE_STRING
:
7535 if (*p
== (char)0xFF) {
7539 slen
= mono_metadata_decode_value (p
, &p
);
7541 return mono_string_new_len (mono_domain_get (), p
, slen
);
7542 case MONO_TYPE_CLASS
: {
7545 if (*p
== (char)0xFF) {
7550 slen
= mono_metadata_decode_value (p
, &p
);
7551 n
= g_memdup (p
, slen
+ 1);
7553 t
= mono_reflection_type_from_name (n
, image
);
7555 g_warning ("Cannot load type '%s'", n
);
7559 return mono_type_get_object (mono_domain_get (), t
);
7563 case MONO_TYPE_OBJECT
: {
7566 MonoClass
*subc
= NULL
;
7571 } else if (subt
== 0x0E) {
7572 type
= MONO_TYPE_STRING
;
7574 } else if (subt
== 0x1D) {
7575 MonoType simple_type
= {{0}};
7580 /* See Partition II, Appendix B3 */
7581 etype
= MONO_TYPE_OBJECT
;
7582 type
= MONO_TYPE_SZARRAY
;
7583 simple_type
.type
= etype
;
7584 tklass
= mono_class_from_mono_type (&simple_type
);
7586 } else if (subt
== 0x55) {
7589 slen
= mono_metadata_decode_value (p
, &p
);
7590 n
= g_memdup (p
, slen
+ 1);
7592 t
= mono_reflection_type_from_name (n
, image
);
7594 g_error ("Cannot load type '%s'", n
);
7597 subc
= mono_class_from_mono_type (t
);
7598 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
7599 MonoType simple_type
= {{0}};
7600 simple_type
.type
= subt
;
7601 subc
= mono_class_from_mono_type (&simple_type
);
7603 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
7605 val
= load_cattr_value (image
, &subc
->byval_arg
, p
, end
);
7606 obj
= mono_object_new (mono_domain_get (), subc
);
7607 memcpy ((char*)obj
+ sizeof (MonoObject
), val
, mono_class_value_size (subc
, NULL
));
7611 case MONO_TYPE_SZARRAY
: {
7613 guint32 i
, alen
, basetype
;
7616 if (alen
== 0xffffffff) {
7620 arr
= mono_array_new (mono_domain_get(), tklass
, alen
);
7621 basetype
= tklass
->byval_arg
.type
;
7622 if (basetype
== MONO_TYPE_VALUETYPE
&& tklass
->enumtype
)
7623 basetype
= mono_class_enum_basetype (tklass
)->type
;
7628 case MONO_TYPE_BOOLEAN
:
7629 for (i
= 0; i
< alen
; i
++) {
7630 MonoBoolean val
= *p
++;
7631 mono_array_set (arr
, MonoBoolean
, i
, val
);
7634 case MONO_TYPE_CHAR
:
7637 for (i
= 0; i
< alen
; i
++) {
7638 guint16 val
= read16 (p
);
7639 mono_array_set (arr
, guint16
, i
, val
);
7646 for (i
= 0; i
< alen
; i
++) {
7647 guint32 val
= read32 (p
);
7648 mono_array_set (arr
, guint32
, i
, val
);
7653 for (i
= 0; i
< alen
; i
++) {
7656 mono_array_set (arr
, double, i
, val
);
7662 for (i
= 0; i
< alen
; i
++) {
7663 guint64 val
= read64 (p
);
7664 mono_array_set (arr
, guint64
, i
, val
);
7668 case MONO_TYPE_CLASS
:
7669 case MONO_TYPE_OBJECT
:
7670 case MONO_TYPE_STRING
:
7671 for (i
= 0; i
< alen
; i
++) {
7672 MonoObject
*item
= load_cattr_value (image
, &tklass
->byval_arg
, p
, &p
);
7673 mono_array_setref (arr
, i
, item
);
7677 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
7683 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
7689 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
)
7691 static MonoClass
*klass
;
7692 static MonoMethod
*ctor
;
7694 void *params
[2], *unboxed
;
7697 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeTypedArgument");
7699 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7701 params
[0] = mono_type_get_object (mono_domain_get (), t
);
7703 retval
= mono_object_new (mono_domain_get (), klass
);
7704 unboxed
= mono_object_unbox (retval
);
7705 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7711 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
)
7713 static MonoClass
*klass
;
7714 static MonoMethod
*ctor
;
7716 void *unboxed
, *params
[2];
7719 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeNamedArgument");
7721 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7724 params
[1] = typedarg
;
7725 retval
= mono_object_new (mono_domain_get (), klass
);
7726 unboxed
= mono_object_unbox (retval
);
7727 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7733 type_is_reference (MonoType
*type
)
7735 switch (type
->type
) {
7736 case MONO_TYPE_BOOLEAN
:
7737 case MONO_TYPE_CHAR
:
7750 case MONO_TYPE_VALUETYPE
:
7758 free_param_data (MonoMethodSignature
*sig
, void **params
) {
7760 for (i
= 0; i
< sig
->param_count
; ++i
) {
7761 if (!type_is_reference (sig
->params
[i
]))
7762 g_free (params
[i
]);
7767 * Find the field index in the metadata FieldDef table.
7770 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
7773 for (i
= 0; i
< klass
->field
.count
; ++i
) {
7774 if (field
== &klass
->fields
[i
])
7775 return klass
->field
.first
+ 1 + i
;
7781 * Find the property index in the metadata Property table.
7784 find_property_index (MonoClass
*klass
, MonoProperty
*property
) {
7787 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
7788 if (property
== &klass
->ext
->properties
[i
])
7789 return klass
->ext
->property
.first
+ 1 + i
;
7795 * Find the event index in the metadata Event table.
7798 find_event_index (MonoClass
*klass
, MonoEvent
*event
) {
7801 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
7802 if (event
== &klass
->ext
->events
[i
])
7803 return klass
->ext
->event
.first
+ 1 + i
;
7809 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
7811 const char *p
= (const char*)data
;
7813 guint32 i
, j
, num_named
;
7815 void *params_buf
[32];
7817 MonoMethodSignature
*sig
;
7819 mono_class_init (method
->klass
);
7822 attr
= mono_object_new (mono_domain_get (), method
->klass
);
7823 mono_runtime_invoke (method
, attr
, NULL
, NULL
);
7827 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
7830 /*g_print ("got attr %s\n", method->klass->name);*/
7832 sig
= mono_method_signature (method
);
7833 if (sig
->param_count
< 32)
7834 params
= params_buf
;
7836 /* Allocate using GC so it gets GC tracking */
7837 params
= mono_gc_alloc_fixed (sig
->param_count
* sizeof (void*), NULL
);
7841 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
7842 params
[i
] = load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
7846 attr
= mono_object_new (mono_domain_get (), method
->klass
);
7847 mono_runtime_invoke (method
, attr
, params
, NULL
);
7848 free_param_data (method
->signature
, params
);
7849 num_named
= read16 (named
);
7851 for (j
= 0; j
< num_named
; j
++) {
7853 char *name
, named_type
, data_type
;
7854 named_type
= *named
++;
7855 data_type
= *named
++; /* type of data */
7856 if (data_type
== MONO_TYPE_SZARRAY
)
7857 data_type
= *named
++;
7858 if (data_type
== MONO_TYPE_ENUM
) {
7861 type_len
= mono_metadata_decode_blob_size (named
, &named
);
7862 type_name
= g_malloc (type_len
+ 1);
7863 memcpy (type_name
, named
, type_len
);
7864 type_name
[type_len
] = 0;
7866 /* FIXME: lookup the type and check type consistency */
7869 name_len
= mono_metadata_decode_blob_size (named
, &named
);
7870 name
= g_malloc (name_len
+ 1);
7871 memcpy (name
, named
, name_len
);
7872 name
[name_len
] = 0;
7874 if (named_type
== 0x53) {
7875 MonoClassField
*field
= mono_class_get_field_from_name (mono_object_class (attr
), name
);
7876 void *val
= load_cattr_value (image
, field
->type
, named
, &named
);
7877 mono_field_set_value (attr
, field
, val
);
7878 if (!type_is_reference (field
->type
))
7880 } else if (named_type
== 0x54) {
7883 MonoType
*prop_type
;
7885 prop
= mono_class_get_property_from_name (mono_object_class (attr
), name
);
7886 /* can we have more that 1 arg in a custom attr named property? */
7887 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
7888 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
7889 pparams
[0] = load_cattr_value (image
, prop_type
, named
, &named
);
7890 mono_property_set_value (prop
, attr
, pparams
, NULL
);
7891 if (!type_is_reference (prop_type
))
7892 g_free (pparams
[0]);
7897 if (params
!= params_buf
)
7898 mono_gc_free_fixed (params
);
7904 create_custom_attr_data (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
7906 MonoArray
*typedargs
, *namedargs
;
7907 MonoClass
*attrklass
;
7908 static MonoMethod
*ctor
;
7911 const char *p
= (const char*)data
;
7913 guint32 i
, j
, num_named
;
7916 mono_class_init (method
->klass
);
7919 ctor
= mono_class_get_method_from_name (mono_defaults
.customattribute_data_class
, ".ctor", 3);
7921 domain
= mono_domain_get ();
7923 /* This is for Attributes with no parameters */
7924 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
7925 params
[0] = mono_method_get_object (domain
, method
, NULL
);
7926 params
[1] = params
[2] = NULL
;
7927 mono_runtime_invoke (method
, attr
, params
, NULL
);
7931 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
7934 typedargs
= mono_array_new (domain
, mono_get_object_class (), mono_method_signature (method
)->param_count
);
7938 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
7939 MonoObject
*obj
, *typedarg
;
7942 val
= load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
7943 obj
= type_is_reference (mono_method_signature (method
)->params
[i
]) ?
7944 val
: mono_value_box (domain
, mono_class_from_mono_type (mono_method_signature (method
)->params
[i
]), val
);
7945 typedarg
= create_cattr_typed_arg (mono_method_signature (method
)->params
[i
], obj
);
7946 mono_array_setref (typedargs
, i
, typedarg
);
7948 if (!type_is_reference (mono_method_signature (method
)->params
[i
]))
7953 num_named
= read16 (named
);
7954 namedargs
= mono_array_new (domain
, mono_get_object_class (), num_named
);
7956 attrklass
= method
->klass
;
7957 for (j
= 0; j
< num_named
; j
++) {
7959 char *name
, named_type
, data_type
;
7960 named_type
= *named
++;
7961 data_type
= *named
++; /* type of data */
7962 if (data_type
== MONO_TYPE_SZARRAY
)
7963 data_type
= *named
++;
7964 if (data_type
== MONO_TYPE_ENUM
) {
7967 type_len
= mono_metadata_decode_blob_size (named
, &named
);
7968 type_name
= g_malloc (type_len
+ 1);
7969 memcpy (type_name
, named
, type_len
);
7970 type_name
[type_len
] = 0;
7972 /* FIXME: lookup the type and check type consistency */
7975 name_len
= mono_metadata_decode_blob_size (named
, &named
);
7976 name
= g_malloc (name_len
+ 1);
7977 memcpy (name
, named
, name_len
);
7978 name
[name_len
] = 0;
7980 if (named_type
== 0x53) {
7981 MonoObject
*obj
, *typedarg
, *namedarg
;
7982 MonoClassField
*field
= mono_class_get_field_from_name (attrklass
, name
);
7983 void *minfo
, *val
= load_cattr_value (image
, field
->type
, named
, &named
);
7985 minfo
= mono_field_get_object (domain
, NULL
, field
);
7986 obj
= type_is_reference (field
->type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (field
->type
), val
);
7987 typedarg
= create_cattr_typed_arg (field
->type
, obj
);
7988 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
7989 mono_array_setref (namedargs
, j
, namedarg
);
7990 if (!type_is_reference (field
->type
))
7992 } else if (named_type
== 0x54) {
7993 MonoObject
*obj
, *typedarg
, *namedarg
;
7994 MonoType
*prop_type
;
7996 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
7998 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
7999 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
8000 minfo
= mono_property_get_object (domain
, NULL
, prop
);
8001 val
= load_cattr_value (image
, prop_type
, named
, &named
);
8002 obj
= type_is_reference (prop_type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (prop_type
), val
);
8003 typedarg
= create_cattr_typed_arg (prop_type
, obj
);
8004 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
8005 mono_array_setref (namedargs
, j
, namedarg
);
8006 if (!type_is_reference (prop_type
))
8011 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
8012 params
[0] = mono_method_get_object (domain
, method
, NULL
);
8013 params
[1] = typedargs
;
8014 params
[2] = namedargs
;
8015 mono_runtime_invoke (ctor
, attr
, params
, NULL
);
8020 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
8026 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, cinfo
->num_attrs
);
8027 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8028 if (!cinfo
->attrs
[i
].ctor
)
8029 /* The cattr type is not finished yet */
8030 /* We should include the type name but cinfo doesn't contain it */
8031 mono_raise_exception (mono_get_exception_type_load (NULL
, NULL
));
8032 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
8033 mono_array_setref (result
, i
, attr
);
8039 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
)
8046 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8047 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
))
8051 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, n
);
8053 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8054 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
)) {
8055 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
8056 mono_array_setref (result
, n
, attr
);
8064 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
)
8070 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, cinfo
->num_attrs
);
8071 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8072 attr
= create_custom_attr_data (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
8073 mono_array_setref (result
, i
, attr
);
8079 * mono_custom_attrs_from_index:
8081 * Returns: NULL if no attributes are found or if a loading error occurs.
8084 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
8086 guint32 mtoken
, i
, len
;
8087 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
8089 MonoCustomAttrInfo
*ainfo
;
8090 GList
*tmp
, *list
= NULL
;
8093 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
8095 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
8099 while (i
< ca
->rows
) {
8100 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
8102 list
= g_list_prepend (list
, GUINT_TO_POINTER (i
));
8105 len
= g_list_length (list
);
8108 ainfo
= g_malloc0 (sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (len
- MONO_ZERO_LEN_ARRAY
));
8109 ainfo
->num_attrs
= len
;
8110 ainfo
->image
= image
;
8111 for (i
= 0, tmp
= list
; i
< len
; ++i
, tmp
= tmp
->next
) {
8112 mono_metadata_decode_row (ca
, GPOINTER_TO_UINT (tmp
->data
), cols
, MONO_CUSTOM_ATTR_SIZE
);
8113 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
8114 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
8115 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
8116 mtoken
|= MONO_TOKEN_METHOD_DEF
;
8118 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
8119 mtoken
|= MONO_TOKEN_MEMBER_REF
;
8122 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
8125 ainfo
->attrs
[i
].ctor
= mono_get_method (image
, mtoken
, NULL
);
8126 if (!ainfo
->attrs
[i
].ctor
) {
8127 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image
->name
, mtoken
);
8132 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
8133 ainfo
->attrs
[i
].data_size
= mono_metadata_decode_value (data
, &data
);
8134 ainfo
->attrs
[i
].data
= (guchar
*)data
;
8142 mono_custom_attrs_from_method (MonoMethod
*method
)
8147 * An instantiated method has the same cattrs as the generic method definition.
8149 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8150 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8152 if (method
->is_inflated
)
8153 method
= ((MonoMethodInflated
*) method
)->declaring
;
8155 if (method
->dynamic
|| method
->klass
->image
->dynamic
)
8156 return lookup_custom_attr (method
->klass
->image
, method
);
8159 /* Synthetic methods */
8162 idx
= mono_method_get_index (method
);
8163 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8164 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
8165 return mono_custom_attrs_from_index (method
->klass
->image
, idx
);
8169 mono_custom_attrs_from_class (MonoClass
*klass
)
8173 if (klass
->generic_class
)
8174 klass
= klass
->generic_class
->container_class
;
8176 if (klass
->image
->dynamic
)
8177 return lookup_custom_attr (klass
->image
, klass
);
8179 if (klass
->byval_arg
.type
== MONO_TYPE_VAR
|| klass
->byval_arg
.type
== MONO_TYPE_MVAR
) {
8180 idx
= mono_metadata_token_index (klass
->sizes
.generic_param_token
);
8181 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8182 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
8184 idx
= mono_metadata_token_index (klass
->type_token
);
8185 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8186 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
8188 return mono_custom_attrs_from_index (klass
->image
, idx
);
8192 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
8196 if (assembly
->image
->dynamic
)
8197 return lookup_custom_attr (assembly
->image
, assembly
);
8198 idx
= 1; /* there is only one assembly */
8199 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8200 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
8201 return mono_custom_attrs_from_index (assembly
->image
, idx
);
8204 static MonoCustomAttrInfo
*
8205 mono_custom_attrs_from_module (MonoImage
*image
)
8210 return lookup_custom_attr (image
, image
);
8211 idx
= 1; /* there is only one module */
8212 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8213 idx
|= MONO_CUSTOM_ATTR_MODULE
;
8214 return mono_custom_attrs_from_index (image
, idx
);
8218 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
8222 if (klass
->image
->dynamic
) {
8223 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
8224 return lookup_custom_attr (klass
->image
, property
);
8226 idx
= find_property_index (klass
, property
);
8227 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8228 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
8229 return mono_custom_attrs_from_index (klass
->image
, idx
);
8233 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
8237 if (klass
->image
->dynamic
) {
8238 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
8239 return lookup_custom_attr (klass
->image
, event
);
8241 idx
= find_event_index (klass
, event
);
8242 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8243 idx
|= MONO_CUSTOM_ATTR_EVENT
;
8244 return mono_custom_attrs_from_index (klass
->image
, idx
);
8248 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
8251 if (klass
->image
->dynamic
) {
8252 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
8253 return lookup_custom_attr (klass
->image
, field
);
8255 idx
= find_field_index (klass
, field
);
8256 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8257 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
8258 return mono_custom_attrs_from_index (klass
->image
, idx
);
8262 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
8265 guint32 i
, idx
, method_index
;
8266 guint32 param_list
, param_last
, param_pos
, found
;
8268 MonoReflectionMethodAux
*aux
;
8271 * An instantiated method has the same cattrs as the generic method definition.
8273 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8274 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8276 if (method
->is_inflated
)
8277 method
= ((MonoMethodInflated
*) method
)->declaring
;
8279 if (method
->klass
->image
->dynamic
) {
8280 MonoCustomAttrInfo
*res
, *ainfo
;
8283 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
8284 if (!aux
|| !aux
->param_cattr
)
8287 /* Need to copy since it will be freed later */
8288 ainfo
= aux
->param_cattr
[param
];
8289 size
= sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (ainfo
->num_attrs
- MONO_ZERO_LEN_ARRAY
);
8290 res
= g_malloc0 (size
);
8291 memcpy (res
, ainfo
, size
);
8295 image
= method
->klass
->image
;
8296 method_index
= mono_method_get_index (method
);
8297 ca
= &image
->tables
[MONO_TABLE_METHOD
];
8299 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
8300 if (method_index
== ca
->rows
) {
8301 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8302 param_last
= ca
->rows
+ 1;
8304 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
8305 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8308 for (i
= param_list
; i
< param_last
; ++i
) {
8309 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
8310 if (param_pos
== param
) {
8318 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8319 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
8320 return mono_custom_attrs_from_index (image
, idx
);
8324 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8328 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8329 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8330 if (mono_class_has_parent (klass
, attr_klass
) || (MONO_CLASS_IS_INTERFACE (attr_klass
) && mono_class_is_assignable_from (attr_klass
, klass
)))
8337 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8344 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8345 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8346 if (mono_class_has_parent (klass
, attr_klass
)) {
8351 if (attr_index
== -1)
8354 attrs
= mono_custom_attrs_construct (ainfo
);
8356 return mono_array_get (attrs
, MonoObject
*, attr_index
);
8362 * mono_reflection_get_custom_attrs_info:
8363 * @obj: a reflection object handle
8365 * Return the custom attribute info for attributes defined for the
8366 * reflection handle @obj. The objects.
8368 * FIXME this function leaks like a sieve for SRE objects.
8371 mono_reflection_get_custom_attrs_info (MonoObject
*obj
)
8374 MonoCustomAttrInfo
*cinfo
= NULL
;
8376 klass
= obj
->vtable
->klass
;
8377 if (klass
== mono_defaults
.monotype_class
) {
8378 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
8379 klass
= mono_class_from_mono_type (type
);
8380 cinfo
= mono_custom_attrs_from_class (klass
);
8381 } else if (strcmp ("Assembly", klass
->name
) == 0) {
8382 MonoReflectionAssembly
*rassembly
= (MonoReflectionAssembly
*)obj
;
8383 cinfo
= mono_custom_attrs_from_assembly (rassembly
->assembly
);
8384 } else if (strcmp ("Module", klass
->name
) == 0) {
8385 MonoReflectionModule
*module
= (MonoReflectionModule
*)obj
;
8386 cinfo
= mono_custom_attrs_from_module (module
->image
);
8387 } else if (strcmp ("MonoProperty", klass
->name
) == 0) {
8388 MonoReflectionProperty
*rprop
= (MonoReflectionProperty
*)obj
;
8389 cinfo
= mono_custom_attrs_from_property (rprop
->property
->parent
, rprop
->property
);
8390 } else if (strcmp ("MonoEvent", klass
->name
) == 0) {
8391 MonoReflectionMonoEvent
*revent
= (MonoReflectionMonoEvent
*)obj
;
8392 cinfo
= mono_custom_attrs_from_event (revent
->event
->parent
, revent
->event
);
8393 } else if (strcmp ("MonoField", klass
->name
) == 0) {
8394 MonoReflectionField
*rfield
= (MonoReflectionField
*)obj
;
8395 cinfo
= mono_custom_attrs_from_field (rfield
->field
->parent
, rfield
->field
);
8396 } else if ((strcmp ("MonoMethod", klass
->name
) == 0) || (strcmp ("MonoCMethod", klass
->name
) == 0)) {
8397 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8398 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8399 } else if ((strcmp ("MonoGenericMethod", klass
->name
) == 0) || (strcmp ("MonoGenericCMethod", klass
->name
) == 0)) {
8400 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8401 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8402 } else if (strcmp ("ParameterInfo", klass
->name
) == 0) {
8403 MonoReflectionParameter
*param
= (MonoReflectionParameter
*)obj
;
8404 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
8405 cinfo
= mono_custom_attrs_from_param (rmethod
->method
, param
->PositionImpl
+ 1);
8406 } else if (strcmp ("AssemblyBuilder", klass
->name
) == 0) {
8407 MonoReflectionAssemblyBuilder
*assemblyb
= (MonoReflectionAssemblyBuilder
*)obj
;
8408 cinfo
= mono_custom_attrs_from_builders (NULL
, assemblyb
->assembly
.assembly
->image
, assemblyb
->cattrs
);
8409 } else if (strcmp ("TypeBuilder", klass
->name
) == 0) {
8410 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
8411 cinfo
= mono_custom_attrs_from_builders (NULL
, &tb
->module
->dynamic_image
->image
, tb
->cattrs
);
8412 } else if (strcmp ("ModuleBuilder", klass
->name
) == 0) {
8413 MonoReflectionModuleBuilder
*mb
= (MonoReflectionModuleBuilder
*)obj
;
8414 cinfo
= mono_custom_attrs_from_builders (NULL
, &mb
->dynamic_image
->image
, mb
->cattrs
);
8415 } else if (strcmp ("ConstructorBuilder", klass
->name
) == 0) {
8416 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
8417 cinfo
= mono_custom_attrs_from_builders (NULL
, cb
->mhandle
->klass
->image
, cb
->cattrs
);
8418 } else if (strcmp ("MethodBuilder", klass
->name
) == 0) {
8419 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
8420 cinfo
= mono_custom_attrs_from_builders (NULL
, mb
->mhandle
->klass
->image
, mb
->cattrs
);
8421 } else if (strcmp ("FieldBuilder", klass
->name
) == 0) {
8422 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
8423 cinfo
= mono_custom_attrs_from_builders (NULL
, &((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
->image
, fb
->cattrs
);
8424 } else if (strcmp ("MonoGenericClass", klass
->name
) == 0) {
8425 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)obj
;
8426 cinfo
= mono_reflection_get_custom_attrs_info ((MonoObject
*)gclass
->generic_type
);
8427 } else { /* handle other types here... */
8428 g_error ("get custom attrs not yet supported for %s", klass
->name
);
8435 * mono_reflection_get_custom_attrs_by_type:
8436 * @obj: a reflection object handle
8438 * Return an array with all the custom attributes defined of the
8439 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8440 * of that type are returned. The objects are fully build. Return NULL if a loading error
8444 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj
, MonoClass
*attr_klass
)
8447 MonoCustomAttrInfo
*cinfo
;
8449 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8452 result
= mono_custom_attrs_construct_by_type (cinfo
, attr_klass
);
8454 result
= mono_custom_attrs_construct (cinfo
);
8456 mono_custom_attrs_free (cinfo
);
8458 if (mono_loader_get_last_error ())
8460 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, 0);
8467 * mono_reflection_get_custom_attrs:
8468 * @obj: a reflection object handle
8470 * Return an array with all the custom attributes defined of the
8471 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8475 mono_reflection_get_custom_attrs (MonoObject
*obj
)
8477 return mono_reflection_get_custom_attrs_by_type (obj
, NULL
);
8481 * mono_reflection_get_custom_attrs_data:
8482 * @obj: a reflection obj handle
8484 * Returns an array of System.Reflection.CustomAttributeData,
8485 * which include information about attributes reflected on
8486 * types loaded using the Reflection Only methods
8489 mono_reflection_get_custom_attrs_data (MonoObject
*obj
)
8492 MonoCustomAttrInfo
*cinfo
;
8494 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8496 result
= mono_custom_attrs_data_construct (cinfo
);
8498 mono_custom_attrs_free (cinfo
);
8500 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, 0);
8505 static MonoReflectionType
*
8506 mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
)
8508 MonoMethod
*method_get_underlying_system_type
;
8510 method_get_underlying_system_type
= mono_object_get_virtual_method ((MonoObject
*) t
,
8511 mono_class_get_method_from_name (mono_object_class (t
),
8512 "get_UnderlyingSystemType",
8514 return (MonoReflectionType
*) mono_runtime_invoke (method_get_underlying_system_type
, t
, NULL
, NULL
);
8517 #ifndef DISABLE_REFLECTION_EMIT
8520 is_corlib_type (MonoClass
*class)
8522 return class->image
== mono_defaults
.corlib
;
8526 is_usertype (MonoReflectionType
*ref
)
8528 MonoClass
*class = mono_object_class (ref
);
8529 return class->image
!= mono_defaults
.corlib
|| strcmp ("TypeDelegator", class->name
) == 0;
8532 #define check_corlib_type_cached(_class, _namespace, _name) do { \
8533 static MonoClass *cached_class; \
8535 return cached_class == _class; \
8536 if (is_corlib_type (_class) && !strcmp (_name, _class->name) && !strcmp (_namespace, _class->name_space)) { \
8537 cached_class = _class; \
8544 is_sre_array (MonoClass
*class)
8546 check_corlib_type_cached (class, "System.Reflection.Emit", "ArrayType");
8550 is_sre_byref (MonoClass
*class)
8552 check_corlib_type_cached (class, "System.Reflection.Emit", "ByRefType");
8556 is_sre_pointer (MonoClass
*class)
8558 check_corlib_type_cached (class, "System.Reflection.Emit", "PointerType");
8562 mono_reflection_type_get_handle (MonoReflectionType
* ref
)
8570 if (is_usertype (ref
)) {
8571 ref
= mono_reflection_type_get_underlying_system_type (ref
);
8572 g_assert (!is_usertype (ref
)); /*FIXME fail better*/
8577 class = mono_object_class (ref
);
8579 if (is_sre_array (class)) {
8581 MonoReflectionArrayType
*sre_array
= (MonoReflectionArrayType
*)ref
;
8582 MonoType
*base
= mono_reflection_type_get_handle (sre_array
->element_type
);
8584 res
= &mono_array_class_get (mono_class_from_mono_type (base
), sre_array
->rank
)->byval_arg
;
8585 sre_array
->type
.type
= res
;
8587 } else if (is_sre_byref (class)) {
8589 MonoReflectionDerivedType
*sre_byref
= (MonoReflectionDerivedType
*)ref
;
8590 MonoType
*base
= mono_reflection_type_get_handle (sre_byref
->element_type
);
8592 res
= &mono_class_from_mono_type (base
)->this_arg
;
8593 sre_byref
->type
.type
= res
;
8595 } else if (is_sre_pointer (class)) {
8597 MonoReflectionDerivedType
*sre_pointer
= (MonoReflectionDerivedType
*)ref
;
8598 MonoType
*base
= mono_reflection_type_get_handle (sre_pointer
->element_type
);
8600 res
= &mono_ptr_class_get (base
)->byval_arg
;
8601 sre_pointer
->type
.type
= res
;
8605 g_error ("Cannot handle corlib user type %s", mono_type_full_name (&mono_object_class(ref
)->byval_arg
));
8609 static MonoReflectionType
*
8610 mono_reflection_type_resolve_user_types (MonoReflectionType
*type
)
8612 if (!type
|| type
->type
)
8615 if (is_usertype (type
)) {
8616 type
= mono_reflection_type_get_underlying_system_type (type
);
8617 if (is_usertype (type
))
8618 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported22"));
8625 mono_reflection_create_unmanaged_type (MonoReflectionType
*type
)
8627 mono_reflection_type_get_handle (type
);
8631 * LOCKING: Assumes the loader lock is held.
8633 static MonoMethodSignature
*
8634 parameters_to_signature (MonoImage
*image
, MonoArray
*parameters
) {
8635 MonoMethodSignature
*sig
;
8638 count
= parameters
? mono_array_length (parameters
): 0;
8640 sig
= image_g_malloc0 (image
, sizeof (MonoMethodSignature
) + sizeof (MonoType
*) * count
);
8641 sig
->param_count
= count
;
8642 sig
->sentinelpos
= -1; /* FIXME */
8643 for (i
= 0; i
< count
; ++i
)
8644 sig
->params
[i
] = mono_type_array_get_and_resolve (parameters
, i
);
8649 * LOCKING: Assumes the loader lock is held.
8651 static MonoMethodSignature
*
8652 ctor_builder_to_signature (MonoImage
*image
, MonoReflectionCtorBuilder
*ctor
) {
8653 MonoMethodSignature
*sig
;
8655 sig
= parameters_to_signature (image
, ctor
->parameters
);
8656 sig
->hasthis
= ctor
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8657 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
8662 * LOCKING: Assumes the loader lock is held.
8664 static MonoMethodSignature
*
8665 method_builder_to_signature (MonoImage
*image
, MonoReflectionMethodBuilder
*method
) {
8666 MonoMethodSignature
*sig
;
8668 sig
= parameters_to_signature (image
, method
->parameters
);
8669 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8670 sig
->ret
= method
->rtype
? mono_reflection_type_get_handle ((MonoReflectionType
*)method
->rtype
): &mono_defaults
.void_class
->byval_arg
;
8671 sig
->generic_param_count
= method
->generic_params
? mono_array_length (method
->generic_params
) : 0;
8675 static MonoMethodSignature
*
8676 dynamic_method_to_signature (MonoReflectionDynamicMethod
*method
) {
8677 MonoMethodSignature
*sig
;
8679 sig
= parameters_to_signature (NULL
, method
->parameters
);
8680 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8681 sig
->ret
= method
->rtype
? mono_reflection_type_get_handle (method
->rtype
): &mono_defaults
.void_class
->byval_arg
;
8682 sig
->generic_param_count
= 0;
8687 get_prop_name_and_type (MonoObject
*prop
, char **name
, MonoType
**type
)
8689 MonoClass
*klass
= mono_object_class (prop
);
8690 if (strcmp (klass
->name
, "PropertyBuilder") == 0) {
8691 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*)prop
;
8692 *name
= mono_string_to_utf8 (pb
->name
);
8693 *type
= mono_reflection_type_get_handle ((MonoReflectionType
*)pb
->type
);
8695 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)prop
;
8696 *name
= g_strdup (p
->property
->name
);
8697 if (p
->property
->get
)
8698 *type
= mono_method_signature (p
->property
->get
)->ret
;
8700 *type
= mono_method_signature (p
->property
->set
)->params
[mono_method_signature (p
->property
->set
)->param_count
- 1];
8705 get_field_name_and_type (MonoObject
*field
, char **name
, MonoType
**type
)
8707 MonoClass
*klass
= mono_object_class (field
);
8708 if (strcmp (klass
->name
, "FieldBuilder") == 0) {
8709 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)field
;
8710 *name
= mono_string_to_utf8 (fb
->name
);
8711 *type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
);
8713 MonoReflectionField
*f
= (MonoReflectionField
*)field
;
8714 *name
= g_strdup (mono_field_get_name (f
->field
));
8715 *type
= f
->field
->type
;
8718 #endif /* !DISABLE_REFLECTION_EMIT */
8721 * Encode a value in a custom attribute stream of bytes.
8722 * The value to encode is either supplied as an object in argument val
8723 * (valuetypes are boxed), or as a pointer to the data in the
8725 * @type represents the type of the value
8726 * @buffer is the start of the buffer
8727 * @p the current position in the buffer
8728 * @buflen contains the size of the buffer and is used to return the new buffer size
8729 * if this needs to be realloced.
8730 * @retbuffer and @retp return the start and the position of the buffer
8733 encode_cattr_value (MonoAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, MonoObject
*arg
, char *argval
)
8735 MonoTypeEnum simple_type
;
8737 if ((p
-buffer
) + 10 >= *buflen
) {
8740 newbuf
= g_realloc (buffer
, *buflen
);
8741 p
= newbuf
+ (p
-buffer
);
8745 argval
= ((char*)arg
+ sizeof (MonoObject
));
8746 simple_type
= type
->type
;
8748 switch (simple_type
) {
8749 case MONO_TYPE_BOOLEAN
:
8754 case MONO_TYPE_CHAR
:
8757 swap_with_size (p
, argval
, 2, 1);
8763 swap_with_size (p
, argval
, 4, 1);
8767 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8777 swap_with_size (p
, argval
, 8, 1);
8783 swap_with_size (p
, argval
, 8, 1);
8786 case MONO_TYPE_VALUETYPE
:
8787 if (type
->data
.klass
->enumtype
) {
8788 simple_type
= mono_class_enum_basetype (type
->data
.klass
)->type
;
8791 g_warning ("generic valutype %s not handled in custom attr value decoding", type
->data
.klass
->name
);
8794 case MONO_TYPE_STRING
: {
8801 str
= mono_string_to_utf8 ((MonoString
*)arg
);
8802 slen
= strlen (str
);
8803 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8807 newbuf
= g_realloc (buffer
, *buflen
);
8808 p
= newbuf
+ (p
-buffer
);
8811 mono_metadata_encode_value (slen
, p
, &p
);
8812 memcpy (p
, str
, slen
);
8817 case MONO_TYPE_CLASS
: {
8825 k
= mono_object_class (arg
);
8826 if (!mono_object_isinst (arg
, mono_defaults
.monotype_class
) &&
8827 (strcmp (k
->name
, "TypeBuilder") || strcmp (k
->name_space
, "System.Reflection.Emit"))) {
8828 MonoReflectionType
* rt
= mono_reflection_type_get_underlying_system_type ((MonoReflectionType
*) arg
);
8831 if (rt
&& (rtc
= mono_object_class (rt
)) &&
8832 (mono_object_isinst ((MonoObject
*) rt
, mono_defaults
.monotype_class
) ||
8833 !strcmp (rtc
->name
, "TypeBuilder") || !strcmp (rtc
->name_space
, "System.Reflection.Emit"))) {
8834 arg
= (MonoObject
*) rt
;
8837 g_error ("Only System.Type allowed, not %s.%s", k
->name_space
, k
->name
);
8840 str
= type_get_qualified_name (((MonoReflectionType
*)arg
)->type
, NULL
);
8841 slen
= strlen (str
);
8842 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8846 newbuf
= g_realloc (buffer
, *buflen
);
8847 p
= newbuf
+ (p
-buffer
);
8850 mono_metadata_encode_value (slen
, p
, &p
);
8851 memcpy (p
, str
, slen
);
8856 case MONO_TYPE_SZARRAY
: {
8858 MonoClass
*eclass
, *arg_eclass
;
8861 *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff;
8864 len
= mono_array_length ((MonoArray
*)arg
);
8866 *p
++ = (len
>> 8) & 0xff;
8867 *p
++ = (len
>> 16) & 0xff;
8868 *p
++ = (len
>> 24) & 0xff;
8870 *retbuffer
= buffer
;
8871 eclass
= type
->data
.klass
;
8872 arg_eclass
= mono_object_class (arg
)->element_class
;
8875 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8876 eclass
= mono_defaults
.object_class
;
8878 if (eclass
== mono_defaults
.object_class
&& arg_eclass
->valuetype
) {
8879 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
8880 int elsize
= mono_class_array_element_size (arg_eclass
);
8881 for (i
= 0; i
< len
; ++i
) {
8882 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &arg_eclass
->byval_arg
, NULL
, elptr
);
8885 } else if (eclass
->valuetype
&& arg_eclass
->valuetype
) {
8886 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
8887 int elsize
= mono_class_array_element_size (eclass
);
8888 for (i
= 0; i
< len
; ++i
) {
8889 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, NULL
, elptr
);
8893 for (i
= 0; i
< len
; ++i
) {
8894 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, mono_array_get ((MonoArray
*)arg
, MonoObject
*, i
), NULL
);
8899 case MONO_TYPE_OBJECT
: {
8905 * The parameter type is 'object' but the type of the actual
8906 * argument is not. So we have to add type information to the blob
8907 * too. This is completely undocumented in the spec.
8911 *p
++ = MONO_TYPE_STRING
; // It's same hack as MS uses
8916 klass
= mono_object_class (arg
);
8918 if (mono_object_isinst (arg
, mono_defaults
.systemtype_class
)) {
8921 } else if (klass
->enumtype
) {
8923 } else if (klass
== mono_defaults
.string_class
) {
8924 simple_type
= MONO_TYPE_STRING
;
8927 } else if (klass
->rank
== 1) {
8929 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_OBJECT
)
8930 /* See Partition II, Appendix B3 */
8933 *p
++ = klass
->element_class
->byval_arg
.type
;
8934 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &klass
->byval_arg
, arg
, NULL
);
8936 } else if (klass
->byval_arg
.type
>= MONO_TYPE_BOOLEAN
&& klass
->byval_arg
.type
<= MONO_TYPE_R8
) {
8937 *p
++ = simple_type
= klass
->byval_arg
.type
;
8940 g_error ("unhandled type in custom attr");
8942 str
= type_get_qualified_name (mono_class_get_type(klass
), NULL
);
8943 slen
= strlen (str
);
8944 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8948 newbuf
= g_realloc (buffer
, *buflen
);
8949 p
= newbuf
+ (p
-buffer
);
8952 mono_metadata_encode_value (slen
, p
, &p
);
8953 memcpy (p
, str
, slen
);
8956 simple_type
= mono_class_enum_basetype (klass
)->type
;
8960 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type
);
8963 *retbuffer
= buffer
;
8967 encode_field_or_prop_type (MonoType
*type
, char *p
, char **retp
)
8969 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
8970 char *str
= type_get_qualified_name (type
, NULL
);
8971 int slen
= strlen (str
);
8975 * This seems to be optional...
8978 mono_metadata_encode_value (slen
, p
, &p
);
8979 memcpy (p
, str
, slen
);
8982 } else if (type
->type
== MONO_TYPE_OBJECT
) {
8984 } else if (type
->type
== MONO_TYPE_CLASS
) {
8985 /* it should be a type: encode_cattr_value () has the check */
8988 mono_metadata_encode_value (type
->type
, p
, &p
);
8989 if (type
->type
== MONO_TYPE_SZARRAY
)
8990 /* See the examples in Partition VI, Annex B */
8991 encode_field_or_prop_type (&type
->data
.klass
->byval_arg
, p
, &p
);
8997 #ifndef DISABLE_REFLECTION_EMIT
8999 encode_named_val (MonoReflectionAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, char *name
, MonoObject
*value
)
9002 /* Preallocate a large enough buffer */
9003 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
9004 char *str
= type_get_qualified_name (type
, NULL
);
9007 } else if (type
->type
== MONO_TYPE_SZARRAY
&& type
->data
.klass
->enumtype
) {
9008 char *str
= type_get_qualified_name (&type
->data
.klass
->byval_arg
, NULL
);
9014 len
+= strlen (name
);
9016 if ((p
-buffer
) + 20 + len
>= *buflen
) {
9020 newbuf
= g_realloc (buffer
, *buflen
);
9021 p
= newbuf
+ (p
-buffer
);
9025 encode_field_or_prop_type (type
, p
, &p
);
9027 len
= strlen (name
);
9028 mono_metadata_encode_value (len
, p
, &p
);
9029 memcpy (p
, name
, len
);
9031 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, buflen
, type
, value
, NULL
);
9033 *retbuffer
= buffer
;
9037 * mono_reflection_get_custom_attrs_blob:
9038 * @ctor: custom attribute constructor
9039 * @ctorArgs: arguments o the constructor
9045 * Creates the blob of data that needs to be saved in the metadata and that represents
9046 * the custom attributed described by @ctor, @ctorArgs etc.
9047 * Returns: a Byte array representing the blob of data.
9050 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
9053 MonoMethodSignature
*sig
;
9058 MONO_ARCH_SAVE_REGS
;
9060 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
9061 /* sig is freed later so allocate it in the heap */
9062 sig
= ctor_builder_to_signature (NULL
, (MonoReflectionCtorBuilder
*)ctor
);
9064 sig
= mono_method_signature (((MonoReflectionMethod
*)ctor
)->method
);
9067 g_assert (mono_array_length (ctorArgs
) == sig
->param_count
);
9069 p
= buffer
= g_malloc (buflen
);
9070 /* write the prolog */
9073 for (i
= 0; i
< sig
->param_count
; ++i
) {
9074 arg
= mono_array_get (ctorArgs
, MonoObject
*, i
);
9075 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, &buflen
, sig
->params
[i
], arg
, NULL
);
9079 i
+= mono_array_length (properties
);
9081 i
+= mono_array_length (fields
);
9083 *p
++ = (i
>> 8) & 0xff;
9086 for (i
= 0; i
< mono_array_length (properties
); ++i
) {
9090 prop
= mono_array_get (properties
, gpointer
, i
);
9091 get_prop_name_and_type (prop
, &pname
, &ptype
);
9092 *p
++ = 0x54; /* PROPERTY signature */
9093 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ptype
, pname
, (MonoObject
*)mono_array_get (propValues
, gpointer
, i
));
9100 for (i
= 0; i
< mono_array_length (fields
); ++i
) {
9104 field
= mono_array_get (fields
, gpointer
, i
);
9105 get_field_name_and_type (field
, &fname
, &ftype
);
9106 *p
++ = 0x53; /* FIELD signature */
9107 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ftype
, fname
, (MonoObject
*)mono_array_get (fieldValues
, gpointer
, i
));
9112 g_assert (p
- buffer
<= buflen
);
9113 buflen
= p
- buffer
;
9114 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
9115 p
= mono_array_addr (result
, char, 0);
9116 memcpy (p
, buffer
, buflen
);
9118 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod"))
9124 * mono_reflection_setup_internal_class:
9125 * @tb: a TypeBuilder object
9127 * Creates a MonoClass that represents the TypeBuilder.
9128 * This is a trick that lets us simplify a lot of reflection code
9129 * (and will allow us to support Build and Run assemblies easier).
9132 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
9134 MonoClass
*klass
, *parent
;
9136 MONO_ARCH_SAVE_REGS
;
9138 RESOLVE_TYPE (tb
->parent
);
9140 mono_loader_lock ();
9143 /* check so we can compile corlib correctly */
9144 if (strcmp (mono_object_class (tb
->parent
)->name
, "TypeBuilder") == 0) {
9145 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
9146 parent
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
->parent
)->data
.klass
;
9148 parent
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
->parent
));
9154 /* the type has already being created: it means we just have to change the parent */
9155 if (tb
->type
.type
) {
9156 klass
= mono_class_from_mono_type (tb
->type
.type
);
9157 klass
->parent
= NULL
;
9158 /* fool mono_class_setup_parent */
9159 klass
->supertypes
= NULL
;
9160 mono_class_setup_parent (klass
, parent
);
9161 mono_class_setup_mono_type (klass
);
9162 mono_loader_unlock ();
9166 klass
= mono_image_alloc0 (&tb
->module
->dynamic_image
->image
, sizeof (MonoClass
));
9168 klass
->image
= &tb
->module
->dynamic_image
->image
;
9170 klass
->inited
= 1; /* we lie to the runtime */
9171 klass
->name
= mono_string_to_utf8_image (klass
->image
, tb
->name
);
9172 klass
->name_space
= mono_string_to_utf8_image (klass
->image
, tb
->nspace
);
9173 klass
->type_token
= MONO_TOKEN_TYPE_DEF
| tb
->table_idx
;
9174 klass
->flags
= tb
->attrs
;
9176 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
9178 klass
->element_class
= klass
;
9180 MOVING_GC_REGISTER (&klass
->reflection_info
);
9181 klass
->reflection_info
= tb
;
9183 /* Put into cache so mono_class_get () will find it */
9184 mono_image_add_to_name_cache (klass
->image
, klass
->name_space
, klass
->name
, tb
->table_idx
);
9186 mono_g_hash_table_insert (tb
->module
->dynamic_image
->tokens
,
9187 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF
| tb
->table_idx
), tb
);
9189 if (parent
!= NULL
) {
9190 mono_class_setup_parent (klass
, parent
);
9191 } else if (strcmp (klass
->name
, "Object") == 0 && strcmp (klass
->name_space
, "System") == 0) {
9192 const char *old_n
= klass
->name
;
9193 /* trick to get relative numbering right when compiling corlib */
9194 klass
->name
= "BuildingObject";
9195 mono_class_setup_parent (klass
, mono_defaults
.object_class
);
9196 klass
->name
= old_n
;
9199 if ((!strcmp (klass
->name
, "ValueType") && !strcmp (klass
->name_space
, "System")) ||
9200 (!strcmp (klass
->name
, "Object") && !strcmp (klass
->name_space
, "System")) ||
9201 (!strcmp (klass
->name
, "Enum") && !strcmp (klass
->name_space
, "System"))) {
9202 klass
->instance_size
= sizeof (MonoObject
);
9203 klass
->size_inited
= 1;
9204 mono_class_setup_vtable_general (klass
, NULL
, 0);
9207 mono_class_setup_mono_type (klass
);
9209 mono_class_setup_supertypes (klass
);
9212 * FIXME: handle interfaces.
9215 tb
->type
.type
= &klass
->byval_arg
;
9217 if (tb
->nesting_type
) {
9218 g_assert (tb
->nesting_type
->type
);
9219 klass
->nested_in
= mono_class_from_mono_type (mono_reflection_type_get_handle (tb
->nesting_type
));
9222 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9224 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
9226 mono_loader_unlock ();
9230 * mono_reflection_setup_generic_class:
9231 * @tb: a TypeBuilder object
9233 * Setup the generic class before adding the first generic parameter.
9236 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
9241 * mono_reflection_create_generic_class:
9242 * @tb: a TypeBuilder object
9244 * Creates the generic class after all generic parameters have been added.
9247 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
9252 MONO_ARCH_SAVE_REGS
;
9254 klass
= mono_class_from_mono_type (tb
->type
.type
);
9256 count
= tb
->generic_params
? mono_array_length (tb
->generic_params
) : 0;
9258 if (klass
->generic_container
|| (count
== 0))
9261 g_assert (tb
->generic_container
&& (tb
->generic_container
->owner
.klass
== klass
));
9263 klass
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
9265 klass
->generic_container
->owner
.klass
= klass
;
9266 klass
->generic_container
->type_argc
= count
;
9267 klass
->generic_container
->type_params
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericParamFull
) * count
);
9269 klass
->is_generic
= 1;
9271 for (i
= 0; i
< count
; i
++) {
9272 MonoReflectionGenericParam
*gparam
= mono_array_get (tb
->generic_params
, gpointer
, i
);
9273 MonoGenericParamFull
*param
= (MonoGenericParamFull
*) mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
)->data
.generic_param
;
9274 klass
->generic_container
->type_params
[i
] = *param
;
9275 /*Make sure we are a diferent type instance */
9276 klass
->generic_container
->type_params
[i
].param
.owner
= klass
->generic_container
;
9277 klass
->generic_container
->type_params
[i
].info
.pklass
= NULL
;
9279 g_assert (klass
->generic_container
->type_params
[i
].param
.owner
);
9282 klass
->generic_container
->context
.class_inst
= mono_get_shared_generic_inst (klass
->generic_container
);
9286 * mono_reflection_create_internal_class:
9287 * @tb: a TypeBuilder object
9289 * Actually create the MonoClass that is associated with the TypeBuilder.
9292 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
9296 MONO_ARCH_SAVE_REGS
;
9298 klass
= mono_class_from_mono_type (tb
->type
.type
);
9300 mono_loader_lock ();
9301 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) == NULL
) {
9302 MonoReflectionFieldBuilder
*fb
;
9304 MonoType
*enum_basetype
;
9306 g_assert (tb
->fields
!= NULL
);
9307 g_assert (mono_array_length (tb
->fields
) >= 1);
9309 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, 0);
9311 if (!mono_type_is_valid_enum_basetype (mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
))) {
9312 mono_loader_unlock ();
9316 enum_basetype
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
);
9317 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
9318 if (!klass
->element_class
)
9319 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
9322 * get the element_class from the current corlib.
9324 ec
= default_class_from_mono_type (enum_basetype
);
9325 klass
->instance_size
= ec
->instance_size
;
9326 klass
->size_inited
= 1;
9328 * this is almost safe to do with enums and it's needed to be able
9329 * to create objects of the enum type (for use in SetConstant).
9331 /* FIXME: Does this mean enums can't have method overrides ? */
9332 mono_class_setup_vtable_general (klass
, NULL
, 0);
9334 mono_loader_unlock ();
9337 static MonoMarshalSpec
*
9338 mono_marshal_spec_from_builder (MonoImage
*image
, MonoAssembly
*assembly
,
9339 MonoReflectionMarshal
*minfo
)
9341 MonoMarshalSpec
*res
;
9343 res
= image_g_new0 (image
, MonoMarshalSpec
, 1);
9344 res
->native
= minfo
->type
;
9346 switch (minfo
->type
) {
9347 case MONO_NATIVE_LPARRAY
:
9348 res
->data
.array_data
.elem_type
= minfo
->eltype
;
9349 if (minfo
->has_size
) {
9350 res
->data
.array_data
.param_num
= minfo
->param_num
;
9351 res
->data
.array_data
.num_elem
= minfo
->count
;
9352 res
->data
.array_data
.elem_mult
= minfo
->param_num
== -1 ? 0 : 1;
9355 res
->data
.array_data
.param_num
= -1;
9356 res
->data
.array_data
.num_elem
= -1;
9357 res
->data
.array_data
.elem_mult
= -1;
9361 case MONO_NATIVE_BYVALTSTR
:
9362 case MONO_NATIVE_BYVALARRAY
:
9363 res
->data
.array_data
.num_elem
= minfo
->count
;
9366 case MONO_NATIVE_CUSTOM
:
9367 if (minfo
->marshaltyperef
)
9368 res
->data
.custom_data
.custom_name
=
9369 type_get_fully_qualified_name (mono_reflection_type_get_handle ((MonoReflectionType
*)minfo
->marshaltyperef
));
9371 res
->data
.custom_data
.cookie
= mono_string_to_utf8 (minfo
->mcookie
);
9380 #endif /* !DISABLE_REFLECTION_EMIT */
9382 MonoReflectionMarshal
*
9383 mono_reflection_marshal_from_marshal_spec (MonoDomain
*domain
, MonoClass
*klass
,
9384 MonoMarshalSpec
*spec
)
9386 static MonoClass
*System_Reflection_Emit_UnmanagedMarshalClass
;
9387 MonoReflectionMarshal
*minfo
;
9390 if (!System_Reflection_Emit_UnmanagedMarshalClass
) {
9391 System_Reflection_Emit_UnmanagedMarshalClass
= mono_class_from_name (
9392 mono_defaults
.corlib
, "System.Reflection.Emit", "UnmanagedMarshal");
9393 g_assert (System_Reflection_Emit_UnmanagedMarshalClass
);
9396 minfo
= (MonoReflectionMarshal
*)mono_object_new (domain
, System_Reflection_Emit_UnmanagedMarshalClass
);
9397 minfo
->type
= spec
->native
;
9399 switch (minfo
->type
) {
9400 case MONO_NATIVE_LPARRAY
:
9401 minfo
->eltype
= spec
->data
.array_data
.elem_type
;
9402 minfo
->count
= spec
->data
.array_data
.num_elem
;
9403 minfo
->param_num
= spec
->data
.array_data
.param_num
;
9406 case MONO_NATIVE_BYVALTSTR
:
9407 case MONO_NATIVE_BYVALARRAY
:
9408 minfo
->count
= spec
->data
.array_data
.num_elem
;
9411 case MONO_NATIVE_CUSTOM
:
9412 if (spec
->data
.custom_data
.custom_name
) {
9413 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, klass
->image
);
9415 MONO_OBJECT_SETREF (minfo
, marshaltyperef
, mono_type_get_object (domain
, mtype
));
9417 MONO_OBJECT_SETREF (minfo
, marshaltype
, mono_string_new (domain
, spec
->data
.custom_data
.custom_name
));
9419 if (spec
->data
.custom_data
.cookie
)
9420 MONO_OBJECT_SETREF (minfo
, mcookie
, mono_string_new (domain
, spec
->data
.custom_data
.cookie
));
9430 #ifndef DISABLE_REFLECTION_EMIT
9432 reflection_methodbuilder_to_mono_method (MonoClass
*klass
,
9433 ReflectionMethodBuilder
*rmb
,
9434 MonoMethodSignature
*sig
)
9437 MonoMethodNormal
*pm
;
9438 MonoMarshalSpec
**specs
;
9439 MonoReflectionMethodAux
*method_aux
;
9445 * Methods created using a MethodBuilder should have their memory allocated
9446 * inside the image mempool, while dynamic methods should have their memory
9449 dynamic
= rmb
->refs
!= NULL
;
9450 image
= dynamic
? NULL
: klass
->image
;
9453 g_assert (!klass
->generic_class
);
9455 mono_loader_lock ();
9457 if ((rmb
->attrs
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
9458 (rmb
->iattrs
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
))
9459 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodPInvoke
, 1);
9461 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodWrapper
, 1);
9463 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodNormal
, 1);
9465 pm
= (MonoMethodNormal
*)m
;
9467 m
->dynamic
= dynamic
;
9469 m
->flags
= rmb
->attrs
;
9470 m
->iflags
= rmb
->iattrs
;
9471 m
->name
= mono_string_to_utf8_image (image
, rmb
->name
);
9474 m
->skip_visibility
= rmb
->skip_visibility
;
9476 m
->token
= MONO_TOKEN_METHOD_DEF
| (*rmb
->table_idx
);
9478 if (m
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) {
9479 if (klass
== mono_defaults
.string_class
&& !strcmp (m
->name
, ".ctor"))
9482 m
->signature
->pinvoke
= 1;
9483 } else if (m
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
9484 m
->signature
->pinvoke
= 1;
9486 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9488 method_aux
->dllentry
= rmb
->dllentry
? mono_string_to_utf8_image (image
, rmb
->dllentry
) : image_strdup (image
, m
->name
);
9489 method_aux
->dll
= mono_string_to_utf8_image (image
, rmb
->dll
);
9491 ((MonoMethodPInvoke
*)m
)->piflags
= (rmb
->native_cc
<< 8) | (rmb
->charset
? (rmb
->charset
- 1) * 2 : 0) | rmb
->extra_flags
;
9493 if (klass
->image
->dynamic
)
9494 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
9496 mono_loader_unlock ();
9499 } else if (!(m
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) &&
9500 !(m
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
9501 MonoMethodHeader
*header
;
9503 gint32 max_stack
, i
;
9504 gint32 num_locals
= 0;
9505 gint32 num_clauses
= 0;
9509 code
= mono_array_addr (rmb
->ilgen
->code
, guint8
, 0);
9510 code_size
= rmb
->ilgen
->code_len
;
9511 max_stack
= rmb
->ilgen
->max_stack
;
9512 num_locals
= rmb
->ilgen
->locals
? mono_array_length (rmb
->ilgen
->locals
) : 0;
9513 if (rmb
->ilgen
->ex_handlers
)
9514 num_clauses
= method_count_clauses (rmb
->ilgen
);
9517 code
= mono_array_addr (rmb
->code
, guint8
, 0);
9518 code_size
= mono_array_length (rmb
->code
);
9519 /* we probably need to run a verifier on the code... */
9529 header
= image_g_malloc0 (image
, sizeof (MonoMethodHeader
) +
9530 (num_locals
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoType
*));
9531 header
->code_size
= code_size
;
9532 header
->code
= image_g_malloc (image
, code_size
);
9533 memcpy ((char*)header
->code
, code
, code_size
);
9534 header
->max_stack
= max_stack
;
9535 header
->init_locals
= rmb
->init_locals
;
9536 header
->num_locals
= num_locals
;
9538 for (i
= 0; i
< num_locals
; ++i
) {
9539 MonoReflectionLocalBuilder
*lb
=
9540 mono_array_get (rmb
->ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
9542 header
->locals
[i
] = image_g_new0 (image
, MonoType
, 1);
9543 memcpy (header
->locals
[i
], mono_reflection_type_get_handle ((MonoReflectionType
*)lb
->type
), sizeof (MonoType
));
9546 header
->num_clauses
= num_clauses
;
9548 header
->clauses
= method_encode_clauses (image
, (MonoDynamicImage
*)klass
->image
,
9549 rmb
->ilgen
, num_clauses
);
9552 pm
->header
= header
;
9555 if (rmb
->generic_params
) {
9556 int count
= mono_array_length (rmb
->generic_params
);
9557 MonoGenericContainer
*container
;
9559 container
= rmb
->generic_container
;
9561 m
->is_generic
= TRUE
;
9562 mono_method_set_generic_container (m
, container
);
9564 container
->type_argc
= count
;
9565 container
->type_params
= image_g_new0 (image
, MonoGenericParamFull
, count
);
9566 container
->owner
.method
= m
;
9568 for (i
= 0; i
< count
; i
++) {
9569 MonoReflectionGenericParam
*gp
=
9570 mono_array_get (rmb
->generic_params
, MonoReflectionGenericParam
*, i
);
9571 MonoGenericParamFull
*param
= (MonoGenericParamFull
*) mono_reflection_type_get_handle ((MonoReflectionType
*)gp
)->data
.generic_param
;
9572 container
->type_params
[i
] = *param
;
9575 if (klass
->generic_container
) {
9576 container
->parent
= klass
->generic_container
;
9577 container
->context
.class_inst
= klass
->generic_container
->context
.class_inst
;
9579 container
->context
.method_inst
= mono_get_shared_generic_inst (container
);
9583 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)m
;
9587 m
->wrapper_type
= MONO_WRAPPER_DYNAMIC_METHOD
;
9589 mw
->method_data
= data
= image_g_new (image
, gpointer
, rmb
->nrefs
+ 1);
9590 data
[0] = GUINT_TO_POINTER (rmb
->nrefs
);
9591 for (i
= 0; i
< rmb
->nrefs
; ++i
)
9592 data
[i
+ 1] = rmb
->refs
[i
];
9597 /* Parameter info */
9600 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9601 method_aux
->param_names
= image_g_new0 (image
, char *, mono_method_signature (m
)->param_count
+ 1);
9602 for (i
= 0; i
<= m
->signature
->param_count
; ++i
) {
9603 MonoReflectionParamBuilder
*pb
;
9604 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
9605 if ((i
> 0) && (pb
->attrs
)) {
9606 /* Make a copy since it might point to a shared type structure */
9607 m
->signature
->params
[i
- 1] = mono_metadata_type_dup (klass
->image
, m
->signature
->params
[i
- 1]);
9608 m
->signature
->params
[i
- 1]->attrs
= pb
->attrs
;
9611 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
9612 MonoDynamicImage
*assembly
;
9613 guint32 idx
, def_type
, len
;
9617 if (!method_aux
->param_defaults
) {
9618 method_aux
->param_defaults
= image_g_new0 (image
, guint8
*, m
->signature
->param_count
+ 1);
9619 method_aux
->param_default_types
= image_g_new0 (image
, guint32
, m
->signature
->param_count
+ 1);
9621 assembly
= (MonoDynamicImage
*)klass
->image
;
9622 idx
= encode_constant (assembly
, pb
->def_value
, &def_type
);
9623 /* Copy the data from the blob since it might get realloc-ed */
9624 p
= assembly
->blob
.data
+ idx
;
9625 len
= mono_metadata_decode_blob_size (p
, &p2
);
9627 method_aux
->param_defaults
[i
] = image_g_malloc (image
, len
);
9628 method_aux
->param_default_types
[i
] = def_type
;
9629 memcpy ((gpointer
)method_aux
->param_defaults
[i
], p
, len
);
9633 method_aux
->param_names
[i
] = mono_string_to_utf8_image (image
, pb
->name
);
9635 if (!method_aux
->param_cattr
)
9636 method_aux
->param_cattr
= image_g_new0 (image
, MonoCustomAttrInfo
*, m
->signature
->param_count
+ 1);
9637 method_aux
->param_cattr
[i
] = mono_custom_attrs_from_builders (image
, klass
->image
, pb
->cattrs
);
9643 /* Parameter marshalling */
9646 for (i
= 0; i
< mono_array_length (rmb
->pinfo
); ++i
) {
9647 MonoReflectionParamBuilder
*pb
;
9648 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
9649 if (pb
->marshal_info
) {
9651 specs
= image_g_new0 (image
, MonoMarshalSpec
*, sig
->param_count
+ 1);
9652 specs
[pb
->position
] =
9653 mono_marshal_spec_from_builder (image
, klass
->image
->assembly
, pb
->marshal_info
);
9657 if (specs
!= NULL
) {
9659 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9660 method_aux
->param_marshall
= specs
;
9663 if (klass
->image
->dynamic
&& method_aux
)
9664 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
9666 mono_loader_unlock ();
9672 ctorbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionCtorBuilder
* mb
)
9674 ReflectionMethodBuilder rmb
;
9675 MonoMethodSignature
*sig
;
9677 mono_loader_lock ();
9678 sig
= ctor_builder_to_signature (klass
->image
, mb
);
9679 mono_loader_unlock ();
9681 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
9683 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
9684 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
9686 /* If we are in a generic class, we might be called multiple times from inflate_method */
9687 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
9688 /* ilgen is no longer needed */
9696 methodbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionMethodBuilder
* mb
)
9698 ReflectionMethodBuilder rmb
;
9699 MonoMethodSignature
*sig
;
9701 mono_loader_lock ();
9702 sig
= method_builder_to_signature (klass
->image
, mb
);
9703 mono_loader_unlock ();
9705 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
9707 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
9708 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
9710 /* If we are in a generic class, we might be called multiple times from inflate_method */
9711 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
9712 /* ilgen is no longer needed */
9718 static MonoClassField
*
9719 fieldbuilder_to_mono_class_field (MonoClass
*klass
, MonoReflectionFieldBuilder
* fb
)
9721 MonoClassField
*field
;
9724 field
= g_new0 (MonoClassField
, 1);
9726 field
->name
= mono_string_to_utf8 (fb
->name
);
9727 if (fb
->attrs
|| fb
->modreq
|| fb
->modopt
) {
9728 field
->type
= mono_metadata_type_dup (NULL
, mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
));
9729 field
->type
->attrs
= fb
->attrs
;
9731 g_assert (klass
->image
->dynamic
);
9732 custom
= add_custom_modifiers ((MonoDynamicImage
*)klass
->image
, field
->type
, fb
->modreq
, fb
->modopt
);
9733 g_free (field
->type
);
9734 field
->type
= custom
;
9736 field
->type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
);
9738 if (fb
->offset
!= -1)
9739 field
->offset
= fb
->offset
;
9740 field
->parent
= klass
;
9741 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
9743 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9750 mono_reflection_bind_generic_parameters (MonoReflectionType
*type
, int type_argc
, MonoType
**types
)
9753 MonoReflectionTypeBuilder
*tb
= NULL
;
9754 gboolean is_dynamic
= FALSE
;
9758 mono_loader_lock ();
9760 domain
= mono_object_domain (type
);
9762 if (!strcmp (((MonoObject
*) type
)->vtable
->klass
->name
, "TypeBuilder")) {
9763 tb
= (MonoReflectionTypeBuilder
*) type
;
9766 } else if (!strcmp (((MonoObject
*) type
)->vtable
->klass
->name
, "MonoGenericClass")) {
9767 MonoReflectionGenericClass
*rgi
= (MonoReflectionGenericClass
*) type
;
9769 tb
= rgi
->generic_type
;
9773 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9774 if (tb
&& tb
->generic_container
)
9775 mono_reflection_create_generic_class (tb
);
9777 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle (type
));
9778 if (!klass
->generic_container
) {
9779 mono_loader_unlock ();
9783 if (klass
->wastypebuilder
) {
9784 tb
= (MonoReflectionTypeBuilder
*) klass
->reflection_info
;
9789 mono_loader_unlock ();
9791 geninst
= mono_class_bind_generic_parameters (klass
, type_argc
, types
, is_dynamic
);
9793 return &geninst
->byval_arg
;
9797 mono_class_bind_generic_parameters (MonoClass
*klass
, int type_argc
, MonoType
**types
, gboolean is_dynamic
)
9799 MonoGenericClass
*gclass
;
9800 MonoGenericInst
*inst
;
9802 g_assert (klass
->generic_container
);
9804 inst
= mono_metadata_get_generic_inst (type_argc
, types
);
9805 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, is_dynamic
);
9807 return mono_generic_class_get_class (gclass
);
9810 MonoReflectionMethod
*
9811 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod
*rmethod
, MonoArray
*types
)
9814 MonoMethod
*method
, *inflated
;
9815 MonoMethodInflated
*imethod
;
9816 MonoGenericContext tmp_context
;
9817 MonoGenericInst
*ginst
;
9818 MonoType
**type_argv
;
9821 MONO_ARCH_SAVE_REGS
;
9823 if (!strcmp (rmethod
->object
.vtable
->klass
->name
, "MethodBuilder")) {
9824 #ifndef DISABLE_REFLECTION_EMIT
9825 MonoReflectionMethodBuilder
*mb
= NULL
;
9826 MonoReflectionTypeBuilder
*tb
;
9829 mb
= (MonoReflectionMethodBuilder
*) rmethod
;
9830 tb
= (MonoReflectionTypeBuilder
*) mb
->type
;
9831 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
));
9833 method
= methodbuilder_to_mono_method (klass
, mb
);
9835 g_assert_not_reached ();
9839 method
= rmethod
->method
;
9842 klass
= method
->klass
;
9844 if (method
->is_inflated
)
9845 method
= ((MonoMethodInflated
*) method
)->declaring
;
9847 count
= mono_method_signature (method
)->generic_param_count
;
9848 if (count
!= mono_array_length (types
))
9851 type_argv
= g_new0 (MonoType
*, count
);
9852 for (i
= 0; i
< count
; i
++) {
9853 MonoReflectionType
*garg
= mono_array_get (types
, gpointer
, i
);
9854 type_argv
[i
] = mono_reflection_type_get_handle (garg
);
9856 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
9859 tmp_context
.class_inst
= klass
->generic_class
? klass
->generic_class
->context
.class_inst
: NULL
;
9860 tmp_context
.method_inst
= ginst
;
9862 inflated
= mono_class_inflate_generic_method (method
, &tmp_context
);
9863 imethod
= (MonoMethodInflated
*) inflated
;
9865 if (method
->klass
->image
->dynamic
) {
9866 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
9868 * This table maps metadata structures representing inflated methods/fields
9869 * to the reflection objects representing their generic definitions.
9871 mono_loader_lock ();
9872 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, rmethod
);
9873 mono_loader_unlock ();
9876 return mono_method_get_object (mono_object_domain (rmethod
), inflated
, NULL
);
9879 #ifndef DISABLE_REFLECTION_EMIT
9882 inflate_mono_method (MonoClass
*klass
, MonoMethod
*method
, MonoObject
*obj
)
9884 MonoMethodInflated
*imethod
;
9885 MonoGenericContext
*context
;
9889 * With generic code sharing the klass might not be inflated.
9890 * This can happen because classes inflated with their own
9891 * type arguments are "normalized" to the uninflated class.
9893 if (!klass
->generic_class
)
9896 context
= mono_class_get_context (klass
);
9898 if (klass
->method
.count
) {
9899 /* Find the already created inflated method */
9900 for (i
= 0; i
< klass
->method
.count
; ++i
) {
9901 g_assert (klass
->methods
[i
]->is_inflated
);
9902 if (((MonoMethodInflated
*)klass
->methods
[i
])->declaring
== method
)
9905 g_assert (i
< klass
->method
.count
);
9906 imethod
= (MonoMethodInflated
*)klass
->methods
[i
];
9908 imethod
= (MonoMethodInflated
*) mono_class_inflate_generic_method_full (method
, klass
, context
);
9911 if (method
->is_generic
&& method
->klass
->image
->dynamic
) {
9912 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
9914 mono_loader_lock ();
9915 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, obj
);
9916 mono_loader_unlock ();
9918 return (MonoMethod
*) imethod
;
9922 inflate_method (MonoReflectionGenericClass
*type
, MonoObject
*obj
)
9927 gklass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)type
->generic_type
));
9929 if (!strcmp (obj
->vtable
->klass
->name
, "MethodBuilder"))
9930 if (((MonoReflectionMethodBuilder
*)obj
)->mhandle
)
9931 method
= ((MonoReflectionMethodBuilder
*)obj
)->mhandle
;
9933 method
= methodbuilder_to_mono_method (gklass
, (MonoReflectionMethodBuilder
*) obj
);
9934 else if (!strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder"))
9935 method
= ctorbuilder_to_mono_method (gklass
, (MonoReflectionCtorBuilder
*) obj
);
9936 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoMethod") || !strcmp (obj
->vtable
->klass
->name
, "MonoCMethod"))
9937 method
= ((MonoReflectionMethod
*) obj
)->method
;
9939 method
= NULL
; /* prevent compiler warning */
9940 g_assert_not_reached ();
9943 return inflate_mono_method (mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)type
)), method
, obj
);
9946 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9948 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
9949 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
9952 MonoGenericClass
*gclass
;
9953 MonoDynamicGenericClass
*dgclass
;
9954 MonoClass
*klass
, *gklass
;
9958 MONO_ARCH_SAVE_REGS
;
9960 gtype
= mono_reflection_type_get_handle ((MonoReflectionType
*)type
);
9961 klass
= mono_class_from_mono_type (gtype
);
9962 g_assert (gtype
->type
== MONO_TYPE_GENERICINST
);
9963 gclass
= gtype
->data
.generic_class
;
9965 g_assert (gclass
->is_dynamic
);
9966 dgclass
= (MonoDynamicGenericClass
*) gclass
;
9968 if (dgclass
->initialized
)
9971 gklass
= gclass
->container_class
;
9972 mono_class_init (gklass
);
9974 dgclass
->count_methods
= methods
? mono_array_length (methods
) : 0;
9975 dgclass
->count_ctors
= ctors
? mono_array_length (ctors
) : 0;
9976 dgclass
->count_fields
= fields
? mono_array_length (fields
) : 0;
9977 dgclass
->count_properties
= properties
? mono_array_length (properties
) : 0;
9978 dgclass
->count_events
= events
? mono_array_length (events
) : 0;
9980 dgclass
->methods
= g_new0 (MonoMethod
*, dgclass
->count_methods
);
9981 dgclass
->ctors
= g_new0 (MonoMethod
*, dgclass
->count_ctors
);
9982 dgclass
->fields
= g_new0 (MonoClassField
, dgclass
->count_fields
);
9983 dgclass
->properties
= g_new0 (MonoProperty
, dgclass
->count_properties
);
9984 dgclass
->events
= g_new0 (MonoEvent
, dgclass
->count_events
);
9985 dgclass
->field_objects
= g_new0 (MonoObject
*, dgclass
->count_fields
);
9986 dgclass
->field_generic_types
= g_new0 (MonoType
*, dgclass
->count_fields
);
9988 for (i
= 0; i
< dgclass
->count_methods
; i
++) {
9989 MonoObject
*obj
= mono_array_get (methods
, gpointer
, i
);
9991 dgclass
->methods
[i
] = inflate_method (type
, obj
);
9994 for (i
= 0; i
< dgclass
->count_ctors
; i
++) {
9995 MonoObject
*obj
= mono_array_get (ctors
, gpointer
, i
);
9997 dgclass
->ctors
[i
] = inflate_method (type
, obj
);
10000 for (i
= 0; i
< dgclass
->count_fields
; i
++) {
10001 MonoObject
*obj
= mono_array_get (fields
, gpointer
, i
);
10002 MonoClassField
*field
, *inflated_field
= NULL
;
10004 if (!strcmp (obj
->vtable
->klass
->name
, "FieldBuilder"))
10005 inflated_field
= field
= fieldbuilder_to_mono_class_field (klass
, (MonoReflectionFieldBuilder
*) obj
);
10006 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoField"))
10007 field
= ((MonoReflectionField
*) obj
)->field
;
10009 field
= NULL
; /* prevent compiler warning */
10010 g_assert_not_reached ();
10013 dgclass
->fields
[i
] = *field
;
10014 dgclass
->fields
[i
].parent
= klass
;
10015 dgclass
->fields
[i
].type
= mono_class_inflate_generic_type (
10016 field
->type
, mono_generic_class_get_context ((MonoGenericClass
*) dgclass
));
10017 dgclass
->field_generic_types
[i
] = field
->type
;
10018 MOVING_GC_REGISTER (&dgclass
->field_objects
[i
]);
10019 dgclass
->field_objects
[i
] = obj
;
10021 if (inflated_field
) {
10022 g_free (inflated_field
);
10024 dgclass
->fields
[i
].name
= g_strdup (dgclass
->fields
[i
].name
);
10028 for (i
= 0; i
< dgclass
->count_properties
; i
++) {
10029 MonoObject
*obj
= mono_array_get (properties
, gpointer
, i
);
10030 MonoProperty
*property
= &dgclass
->properties
[i
];
10032 if (!strcmp (obj
->vtable
->klass
->name
, "PropertyBuilder")) {
10033 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*) obj
;
10035 property
->parent
= klass
;
10036 property
->attrs
= pb
->attrs
;
10037 property
->name
= mono_string_to_utf8 (pb
->name
);
10038 if (pb
->get_method
)
10039 property
->get
= inflate_method (type
, (MonoObject
*) pb
->get_method
);
10040 if (pb
->set_method
)
10041 property
->set
= inflate_method (type
, (MonoObject
*) pb
->set_method
);
10042 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoProperty")) {
10043 *property
= *((MonoReflectionProperty
*) obj
)->property
;
10044 property
->name
= g_strdup (property
->name
);
10047 property
->get
= inflate_mono_method (klass
, property
->get
, NULL
);
10049 property
->set
= inflate_mono_method (klass
, property
->set
, NULL
);
10051 g_assert_not_reached ();
10054 for (i
= 0; i
< dgclass
->count_events
; i
++) {
10055 MonoObject
*obj
= mono_array_get (events
, gpointer
, i
);
10056 MonoEvent
*event
= &dgclass
->events
[i
];
10058 if (!strcmp (obj
->vtable
->klass
->name
, "EventBuilder")) {
10059 MonoReflectionEventBuilder
*eb
= (MonoReflectionEventBuilder
*) obj
;
10061 event
->parent
= klass
;
10062 event
->attrs
= eb
->attrs
;
10063 event
->name
= mono_string_to_utf8 (eb
->name
);
10064 if (eb
->add_method
)
10065 event
->add
= inflate_method (type
, (MonoObject
*) eb
->add_method
);
10066 if (eb
->remove_method
)
10067 event
->remove
= inflate_method (type
, (MonoObject
*) eb
->remove_method
);
10068 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoEvent")) {
10069 *event
= *((MonoReflectionMonoEvent
*) obj
)->event
;
10070 event
->name
= g_strdup (event
->name
);
10073 event
->add
= inflate_mono_method (klass
, event
->add
, NULL
);
10075 event
->remove
= inflate_mono_method (klass
, event
->remove
, NULL
);
10077 g_assert_not_reached ();
10080 dgclass
->initialized
= TRUE
;
10084 ensure_generic_class_runtime_vtable (MonoClass
*klass
)
10086 MonoClass
*gklass
= klass
->generic_class
->container_class
;
10089 if (klass
->wastypebuilder
)
10092 ensure_runtime_vtable (gklass
);
10094 klass
->method
.count
= gklass
->method
.count
;
10095 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * (klass
->method
.count
+ 1));
10097 for (i
= 0; i
< klass
->method
.count
; i
++) {
10098 klass
->methods
[i
] = mono_class_inflate_generic_method_full (
10099 gklass
->methods
[i
], klass
, mono_class_get_context (klass
));
10102 klass
->interface_count
= gklass
->interface_count
;
10103 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
10104 for (i
= 0; i
< klass
->interface_count
; ++i
) {
10105 MonoType
*iface_type
= mono_class_inflate_generic_type (&gklass
->interfaces
[i
]->byval_arg
, mono_class_get_context (klass
));
10106 klass
->interfaces
[i
] = mono_class_from_mono_type (iface_type
);
10107 mono_metadata_free_type (iface_type
);
10109 ensure_runtime_vtable (klass
->interfaces
[i
]);
10111 klass
->interfaces_inited
= 1;
10113 /*We can only finish with this klass once it's parent has as well*/
10114 if (gklass
->wastypebuilder
)
10115 klass
->wastypebuilder
= TRUE
;
10120 ensure_runtime_vtable (MonoClass
*klass
)
10122 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10125 if (!klass
->image
->dynamic
|| (!tb
&& !klass
->generic_class
) || klass
->wastypebuilder
)
10128 ensure_runtime_vtable (klass
->parent
);
10131 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
10132 num
+= tb
->num_methods
;
10133 klass
->method
.count
= num
;
10134 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * num
);
10135 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
10136 for (i
= 0; i
< num
; ++i
)
10137 klass
->methods
[i
] = ctorbuilder_to_mono_method (klass
, mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
));
10138 num
= tb
->num_methods
;
10140 for (i
= 0; i
< num
; ++i
)
10141 klass
->methods
[j
++] = methodbuilder_to_mono_method (klass
, mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
));
10143 if (tb
->interfaces
) {
10144 klass
->interface_count
= mono_array_length (tb
->interfaces
);
10145 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
10146 for (i
= 0; i
< klass
->interface_count
; ++i
) {
10147 MonoType
*iface
= mono_type_array_get_and_resolve (tb
->interfaces
, i
);
10148 klass
->interfaces
[i
] = mono_class_from_mono_type (iface
);
10149 ensure_runtime_vtable (klass
->interfaces
[i
]);
10151 klass
->interfaces_inited
= 1;
10153 } else if (klass
->generic_class
){
10154 ensure_generic_class_runtime_vtable (klass
);
10157 if (klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
10158 for (i
= 0; i
< klass
->method
.count
; ++i
)
10159 klass
->methods
[i
]->slot
= i
;
10161 mono_class_setup_interface_offsets (klass
);
10162 mono_class_setup_interface_id (klass
);
10166 * The generic vtable is needed even if image->run is not set since some
10167 * runtime code like ves_icall_Type_GetMethodsByName depends on
10168 * method->slot being defined.
10172 * tb->methods could not be freed since it is used for determining
10173 * overrides during dynamic vtable construction.
10178 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
10180 MonoReflectionTypeBuilder
*tb
;
10184 *num_overrides
= 0;
10186 g_assert (klass
->image
->dynamic
);
10188 if (!klass
->reflection_info
)
10191 g_assert (strcmp (((MonoObject
*)klass
->reflection_info
)->vtable
->klass
->name
, "TypeBuilder") == 0);
10193 tb
= (MonoReflectionTypeBuilder
*)klass
->reflection_info
;
10197 for (i
= 0; i
< tb
->num_methods
; ++i
) {
10198 MonoReflectionMethodBuilder
*mb
=
10199 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
10200 if (mb
->override_method
)
10206 *overrides
= g_new0 (MonoMethod
*, onum
* 2);
10209 for (i
= 0; i
< tb
->num_methods
; ++i
) {
10210 MonoReflectionMethodBuilder
*mb
=
10211 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
10212 if (mb
->override_method
) {
10213 (*overrides
) [onum
* 2] =
10214 mb
->override_method
->method
;
10215 (*overrides
) [onum
* 2 + 1] =
10218 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10219 g_assert (mb
->override_method
->method
);
10220 g_assert (mb
->mhandle
);
10227 *num_overrides
= onum
;
10231 typebuilder_setup_fields (MonoClass
*klass
)
10233 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10234 MonoReflectionFieldBuilder
*fb
;
10235 MonoClassField
*field
;
10236 MonoImage
*image
= klass
->image
;
10237 const char *p
, *p2
;
10239 guint32 len
, idx
, real_size
= 0;
10241 klass
->field
.count
= tb
->num_fields
;
10242 klass
->field
.first
= 0;
10244 if (tb
->class_size
) {
10245 g_assert ((tb
->packing_size
& 0xfffffff0) == 0);
10246 klass
->packing_size
= tb
->packing_size
;
10247 real_size
= klass
->instance_size
+ tb
->class_size
;
10250 if (!klass
->field
.count
) {
10251 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10255 klass
->fields
= image_g_new0 (image
, MonoClassField
, klass
->field
.count
);
10256 mono_class_alloc_ext (klass
);
10257 klass
->ext
->field_def_values
= image_g_new0 (image
, MonoFieldDefaultValue
, klass
->field
.count
);
10259 for (i
= 0; i
< klass
->field
.count
; ++i
) {
10260 fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10261 field
= &klass
->fields
[i
];
10262 field
->name
= mono_string_to_utf8_image (image
, fb
->name
);
10264 field
->type
= mono_metadata_type_dup (klass
->image
, mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
));
10265 field
->type
->attrs
= fb
->attrs
;
10267 field
->type
= mono_reflection_type_get_handle ((MonoReflectionType
*)fb
->type
);
10269 if ((fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) && fb
->rva_data
)
10270 klass
->ext
->field_def_values
[i
].data
= mono_array_addr (fb
->rva_data
, char, 0);
10271 if (fb
->offset
!= -1)
10272 field
->offset
= fb
->offset
;
10273 field
->parent
= klass
;
10274 fb
->handle
= field
;
10275 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
10277 if (fb
->def_value
) {
10278 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)klass
->image
;
10279 field
->type
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
10280 idx
= encode_constant (assembly
, fb
->def_value
, &klass
->ext
->field_def_values
[i
].def_type
);
10281 /* Copy the data from the blob since it might get realloc-ed */
10282 p
= assembly
->blob
.data
+ idx
;
10283 len
= mono_metadata_decode_blob_size (p
, &p2
);
10285 klass
->ext
->field_def_values
[i
].data
= mono_image_alloc (image
, len
);
10286 memcpy ((gpointer
)klass
->ext
->field_def_values
[i
].data
, p
, len
);
10290 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10291 mono_class_layout_fields (klass
);
10295 typebuilder_setup_properties (MonoClass
*klass
)
10297 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10298 MonoReflectionPropertyBuilder
*pb
;
10299 MonoImage
*image
= klass
->image
;
10300 MonoProperty
*properties
;
10304 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
10306 klass
->ext
->property
.count
= tb
->properties
? mono_array_length (tb
->properties
) : 0;
10307 klass
->ext
->property
.first
= 0;
10309 properties
= image_g_new0 (image
, MonoProperty
, klass
->ext
->property
.count
);
10310 klass
->ext
->properties
= properties
;
10311 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
10312 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
10313 properties
[i
].parent
= klass
;
10314 properties
[i
].attrs
= pb
->attrs
;
10315 properties
[i
].name
= mono_string_to_utf8_image (image
, pb
->name
);
10316 if (pb
->get_method
)
10317 properties
[i
].get
= pb
->get_method
->mhandle
;
10318 if (pb
->set_method
)
10319 properties
[i
].set
= pb
->set_method
->mhandle
;
10321 mono_save_custom_attrs (klass
->image
, &properties
[i
], pb
->cattrs
);
10325 MonoReflectionEvent
*
10326 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
10328 MonoEvent
*event
= g_new0 (MonoEvent
, 1);
10332 klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
));
10334 event
->parent
= klass
;
10335 event
->attrs
= eb
->attrs
;
10336 event
->name
= mono_string_to_utf8 (eb
->name
);
10337 if (eb
->add_method
)
10338 event
->add
= eb
->add_method
->mhandle
;
10339 if (eb
->remove_method
)
10340 event
->remove
= eb
->remove_method
->mhandle
;
10341 if (eb
->raise_method
)
10342 event
->raise
= eb
->raise_method
->mhandle
;
10344 if (eb
->other_methods
) {
10345 event
->other
= g_new0 (MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10346 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10347 MonoReflectionMethodBuilder
*mb
=
10348 mono_array_get (eb
->other_methods
,
10349 MonoReflectionMethodBuilder
*, j
);
10350 event
->other
[j
] = mb
->mhandle
;
10354 return mono_event_get_object (mono_object_domain (tb
), klass
, event
);
10358 typebuilder_setup_events (MonoClass
*klass
)
10360 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10361 MonoReflectionEventBuilder
*eb
;
10362 MonoImage
*image
= klass
->image
;
10367 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
10369 klass
->ext
->event
.count
= tb
->events
? mono_array_length (tb
->events
) : 0;
10370 klass
->ext
->event
.first
= 0;
10372 events
= image_g_new0 (image
, MonoEvent
, klass
->ext
->event
.count
);
10373 klass
->ext
->events
= events
;
10374 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
10375 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
10376 events
[i
].parent
= klass
;
10377 events
[i
].attrs
= eb
->attrs
;
10378 events
[i
].name
= mono_string_to_utf8_image (image
, eb
->name
);
10379 if (eb
->add_method
)
10380 events
[i
].add
= eb
->add_method
->mhandle
;
10381 if (eb
->remove_method
)
10382 events
[i
].remove
= eb
->remove_method
->mhandle
;
10383 if (eb
->raise_method
)
10384 events
[i
].raise
= eb
->raise_method
->mhandle
;
10386 if (eb
->other_methods
) {
10387 events
[i
].other
= image_g_new0 (image
, MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10388 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10389 MonoReflectionMethodBuilder
*mb
=
10390 mono_array_get (eb
->other_methods
,
10391 MonoReflectionMethodBuilder
*, j
);
10392 events
[i
].other
[j
] = mb
->mhandle
;
10395 mono_save_custom_attrs (klass
->image
, &events
[i
], eb
->cattrs
);
10400 remove_instantiations_of (gpointer key
,
10402 gpointer user_data
)
10404 MonoType
*type
= (MonoType
*)key
;
10405 MonoClass
*klass
= (MonoClass
*)user_data
;
10407 if ((type
->type
== MONO_TYPE_GENERICINST
) && (type
->data
.generic_class
->container_class
== klass
))
10414 check_array_for_usertypes (MonoArray
*arr
)
10421 for (i
= 0; i
< mono_array_length (arr
); ++i
)
10422 RESOLVE_ARRAY_TYPE_ELEMENT (arr
, i
);
10425 MonoReflectionType
*
10426 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
10429 MonoDomain
* domain
;
10430 MonoReflectionType
* res
;
10433 MONO_ARCH_SAVE_REGS
;
10435 domain
= mono_object_domain (tb
);
10436 klass
= mono_class_from_mono_type (tb
->type
.type
);
10439 * Check for user defined Type subclasses.
10441 RESOLVE_TYPE (tb
->parent
);
10442 check_array_for_usertypes (tb
->interfaces
);
10444 for (i
= 0; i
< mono_array_length (tb
->fields
); ++i
) {
10445 MonoReflectionFieldBuilder
*fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10447 RESOLVE_TYPE (fb
->type
);
10448 check_array_for_usertypes (fb
->modreq
);
10449 check_array_for_usertypes (fb
->modopt
);
10450 if (fb
->marshal_info
&& fb
->marshal_info
->marshaltyperef
)
10451 RESOLVE_TYPE (fb
->marshal_info
->marshaltyperef
);
10456 for (i
= 0; i
< mono_array_length (tb
->methods
); ++i
) {
10457 MonoReflectionMethodBuilder
*mb
= mono_array_get (tb
->methods
, gpointer
, i
);
10459 RESOLVE_TYPE (mb
->rtype
);
10460 check_array_for_usertypes (mb
->return_modreq
);
10461 check_array_for_usertypes (mb
->return_modopt
);
10462 check_array_for_usertypes (mb
->parameters
);
10463 if (mb
->param_modreq
)
10464 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
)
10465 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
));
10466 if (mb
->param_modopt
)
10467 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
)
10468 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
));
10473 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
10474 MonoReflectionCtorBuilder
*mb
= mono_array_get (tb
->ctors
, gpointer
, i
);
10476 check_array_for_usertypes (mb
->parameters
);
10477 if (mb
->param_modreq
)
10478 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
)
10479 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
));
10480 if (mb
->param_modopt
)
10481 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
)
10482 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
));
10487 mono_save_custom_attrs (klass
->image
, klass
, tb
->cattrs
);
10490 * we need to lock the domain because the lock will be taken inside
10491 * So, we need to keep the locking order correct.
10493 mono_loader_lock ();
10494 mono_domain_lock (domain
);
10495 if (klass
->wastypebuilder
) {
10496 mono_domain_unlock (domain
);
10497 mono_loader_unlock ();
10498 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10501 * Fields to set in klass:
10502 * the various flags: delegate/unicode/contextbound etc.
10504 klass
->flags
= tb
->attrs
;
10505 klass
->has_cctor
= 1;
10506 klass
->has_finalize
= 1;
10509 if (!((MonoDynamicImage
*)klass
->image
)->run
) {
10510 if (klass
->generic_container
) {
10511 /* FIXME: The code below can't handle generic classes */
10512 klass
->wastypebuilder
= TRUE
;
10513 mono_loader_unlock ();
10514 mono_domain_unlock (domain
);
10515 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10520 /* enums are done right away */
10521 if (!klass
->enumtype
)
10522 ensure_runtime_vtable (klass
);
10524 if (tb
->subtypes
) {
10525 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
10526 MonoReflectionTypeBuilder
*subtb
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
10527 mono_class_alloc_ext (klass
);
10528 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
)));
10532 klass
->nested_classes_inited
= TRUE
;
10534 /* fields and object layout */
10535 if (klass
->parent
) {
10536 if (!klass
->parent
->size_inited
)
10537 mono_class_init (klass
->parent
);
10538 klass
->instance_size
= klass
->parent
->instance_size
;
10539 klass
->sizes
.class_size
= 0;
10540 klass
->min_align
= klass
->parent
->min_align
;
10541 /* if the type has no fields we won't call the field_setup
10542 * routine which sets up klass->has_references.
10544 klass
->has_references
|= klass
->parent
->has_references
;
10546 klass
->instance_size
= sizeof (MonoObject
);
10547 klass
->min_align
= 1;
10550 /* FIXME: handle packing_size and instance_size */
10551 typebuilder_setup_fields (klass
);
10553 typebuilder_setup_properties (klass
);
10555 typebuilder_setup_events (klass
);
10557 klass
->wastypebuilder
= TRUE
;
10560 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10561 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10562 * we want to return normal System.MonoType objects, so clear these out from the cache.
10564 if (domain
->type_hash
&& klass
->generic_container
)
10565 mono_g_hash_table_foreach_remove (domain
->type_hash
, remove_instantiations_of
, klass
);
10567 mono_domain_unlock (domain
);
10568 mono_loader_unlock ();
10570 if (klass
->enumtype
&& !mono_class_is_valid_enum (klass
)) {
10571 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
10572 mono_raise_exception (mono_get_exception_type_load (tb
->name
, NULL
));
10575 res
= mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10576 g_assert (res
!= (MonoReflectionType
*)tb
);
10582 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
10584 MonoGenericParamFull
*param
;
10588 MONO_ARCH_SAVE_REGS
;
10590 param
= g_new0 (MonoGenericParamFull
, 1);
10592 if (gparam
->mbuilder
) {
10593 if (!gparam
->mbuilder
->generic_container
) {
10594 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)gparam
->mbuilder
->type
;
10595 MonoClass
*klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)tb
));
10596 gparam
->mbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
10597 gparam
->mbuilder
->generic_container
->is_method
= TRUE
;
10599 * Cannot set owner.method, since the MonoMethod is not created yet.
10600 * Set the image field instead, so type_in_image () works.
10602 gparam
->mbuilder
->generic_container
->image
= klass
->image
;
10604 param
->param
.owner
= gparam
->mbuilder
->generic_container
;
10605 } else if (gparam
->tbuilder
) {
10606 if (!gparam
->tbuilder
->generic_container
) {
10607 MonoClass
*klass
= mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)gparam
->tbuilder
));
10608 gparam
->tbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
10609 gparam
->tbuilder
->generic_container
->owner
.klass
= klass
;
10611 param
->param
.owner
= gparam
->tbuilder
->generic_container
;
10614 param
->info
.name
= mono_string_to_utf8 (gparam
->name
);
10615 param
->param
.num
= gparam
->index
;
10617 image
= &gparam
->tbuilder
->module
->dynamic_image
->image
;
10618 pklass
= mono_class_from_generic_parameter ((MonoGenericParam
*) param
, image
, gparam
->mbuilder
!= NULL
);
10620 gparam
->type
.type
= &pklass
->byval_arg
;
10622 MOVING_GC_REGISTER (&pklass
->reflection_info
);
10623 pklass
->reflection_info
= gparam
; /* FIXME: GC pin gparam */
10627 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
10629 MonoReflectionModuleBuilder
*module
= sig
->module
;
10630 MonoDynamicImage
*assembly
= module
!= NULL
? module
->dynamic_image
: NULL
;
10631 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
10636 check_array_for_usertypes (sig
->arguments
);
10638 sigbuffer_init (&buf
, 32);
10640 sigbuffer_add_value (&buf
, 0x07);
10641 sigbuffer_add_value (&buf
, na
);
10642 if (assembly
!= NULL
){
10643 for (i
= 0; i
< na
; ++i
) {
10644 MonoReflectionType
*type
= mono_array_get (sig
->arguments
, MonoReflectionType
*, i
);
10645 encode_reflection_type (assembly
, type
, &buf
);
10649 buflen
= buf
.p
- buf
.buf
;
10650 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
10651 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
10652 sigbuffer_free (&buf
);
10658 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
10660 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
10661 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
10666 check_array_for_usertypes (sig
->arguments
);
10668 sigbuffer_init (&buf
, 32);
10670 sigbuffer_add_value (&buf
, 0x06);
10671 for (i
= 0; i
< na
; ++i
) {
10672 MonoReflectionType
*type
= mono_array_get (sig
->arguments
, MonoReflectionType
*, i
);
10673 encode_reflection_type (assembly
, type
, &buf
);
10676 buflen
= buf
.p
- buf
.buf
;
10677 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
10678 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
10679 sigbuffer_free (&buf
);
10685 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10687 ReflectionMethodBuilder rmb
;
10688 MonoMethodSignature
*sig
;
10693 sig
= dynamic_method_to_signature (mb
);
10695 reflection_methodbuilder_from_dynamic_method (&rmb
, mb
);
10698 * Resolve references.
10701 * Every second entry in the refs array is reserved for storing handle_class,
10702 * which is needed by the ldtoken implementation in the JIT.
10704 rmb
.nrefs
= mb
->nrefs
;
10705 rmb
.refs
= g_new0 (gpointer
, mb
->nrefs
+ 1);
10706 for (i
= 0; i
< mb
->nrefs
; i
+= 2) {
10707 MonoClass
*handle_class
;
10709 MonoObject
*obj
= mono_array_get (mb
->refs
, MonoObject
*, i
);
10711 if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
10712 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
10714 * The referenced DynamicMethod should already be created by the managed
10715 * code, except in the case of circular references. In that case, we store
10716 * method in the refs array, and fix it up later when the referenced
10717 * DynamicMethod is created.
10719 if (method
->mhandle
) {
10720 ref
= method
->mhandle
;
10722 /* FIXME: GC object stored in unmanaged memory */
10725 /* FIXME: GC object stored in unmanaged memory */
10726 method
->referenced_by
= g_slist_append (method
->referenced_by
, mb
);
10728 handle_class
= mono_defaults
.methodhandle_class
;
10730 MonoException
*ex
= NULL
;
10731 ref
= resolve_object (mb
->module
->image
, obj
, &handle_class
, NULL
);
10733 ex
= mono_get_exception_type_load (NULL
, NULL
);
10734 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
10735 ex
= mono_security_core_clr_ensure_dynamic_method_resolved_object (ref
, handle_class
);
10739 mono_raise_exception (ex
);
10744 rmb
.refs
[i
] = ref
; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10745 rmb
.refs
[i
+ 1] = handle_class
;
10748 klass
= mb
->owner
? mono_class_from_mono_type (mono_reflection_type_get_handle ((MonoReflectionType
*)mb
->owner
)) : mono_defaults
.object_class
;
10750 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
10752 /* Fix up refs entries pointing at us */
10753 for (l
= mb
->referenced_by
; l
; l
= l
->next
) {
10754 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)l
->data
;
10755 MonoMethodWrapper
*wrapper
= (MonoMethodWrapper
*)method
->mhandle
;
10758 g_assert (method
->mhandle
);
10760 data
= (gpointer
*)wrapper
->method_data
;
10761 for (i
= 0; i
< GPOINTER_TO_UINT (data
[0]); i
+= 2) {
10762 if ((data
[i
+ 1] == mb
) && (data
[i
+ 1 + 1] == mono_defaults
.methodhandle_class
))
10763 data
[i
+ 1] = mb
->mhandle
;
10766 g_slist_free (mb
->referenced_by
);
10770 /* ilgen is no longer needed */
10774 #endif /* DISABLE_REFLECTION_EMIT */
10777 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10782 mono_runtime_free_method (
10783 mono_object_get_domain ((MonoObject
*)mb
), mb
->mhandle
);
10788 * mono_reflection_is_valid_dynamic_token:
10790 * Returns TRUE if token is valid.
10794 mono_reflection_is_valid_dynamic_token (MonoDynamicImage
*image
, guint32 token
)
10796 return mono_g_hash_table_lookup (image
->tokens
, GUINT_TO_POINTER (token
)) != NULL
;
10799 #ifndef DISABLE_REFLECTION_EMIT
10802 * mono_reflection_lookup_dynamic_token:
10804 * Finish the Builder object pointed to by TOKEN and return the corresponding
10805 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10806 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10809 * LOCKING: Take the loader lock
10812 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10814 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)image
;
10818 mono_loader_lock ();
10819 obj
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
10820 mono_loader_unlock ();
10823 g_error ("Could not find required dynamic token 0x%08x", token
);
10829 handle_class
= &klass
;
10830 return resolve_object (image
, obj
, handle_class
, context
);
10834 * ensure_complete_type:
10836 * Ensure that KLASS is completed if it is a dynamic type, or references
10840 ensure_complete_type (MonoClass
*klass
)
10842 if (klass
->image
->dynamic
&& !klass
->wastypebuilder
) {
10843 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10845 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10847 // Asserting here could break a lot of code
10848 //g_assert (klass->wastypebuilder);
10851 if (klass
->generic_class
) {
10852 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
10855 for (i
= 0; i
< inst
->type_argc
; ++i
) {
10856 ensure_complete_type (mono_class_from_mono_type (inst
->type_argv
[i
]));
10862 resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10864 gpointer result
= NULL
;
10866 if (strcmp (obj
->vtable
->klass
->name
, "String") == 0) {
10867 result
= mono_string_intern ((MonoString
*)obj
);
10868 *handle_class
= NULL
;
10870 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoType") == 0) {
10871 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
10873 MonoType
*inflated
= mono_class_inflate_generic_type (type
, context
);
10874 result
= mono_class_from_mono_type (inflated
);
10875 mono_metadata_free_type (inflated
);
10877 result
= mono_class_from_mono_type (type
);
10879 *handle_class
= mono_defaults
.typehandle_class
;
10881 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoMethod") == 0 ||
10882 strcmp (obj
->vtable
->klass
->name
, "MonoCMethod") == 0 ||
10883 strcmp (obj
->vtable
->klass
->name
, "MonoGenericCMethod") == 0 ||
10884 strcmp (obj
->vtable
->klass
->name
, "MonoGenericMethod") == 0) {
10885 result
= ((MonoReflectionMethod
*)obj
)->method
;
10887 result
= mono_class_inflate_generic_method (result
, context
);
10888 *handle_class
= mono_defaults
.methodhandle_class
;
10890 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodBuilder") == 0) {
10891 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
10892 result
= mb
->mhandle
;
10894 /* Type is not yet created */
10895 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
10897 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10900 * Hopefully this has been filled in by calling CreateType() on the
10904 * TODO: This won't work if the application finishes another
10905 * TypeBuilder instance instead of this one.
10907 result
= mb
->mhandle
;
10910 result
= mono_class_inflate_generic_method (result
, context
);
10911 *handle_class
= mono_defaults
.methodhandle_class
;
10912 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder") == 0) {
10913 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
10915 result
= cb
->mhandle
;
10917 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)cb
->type
;
10919 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10920 result
= cb
->mhandle
;
10923 result
= mono_class_inflate_generic_method (result
, context
);
10924 *handle_class
= mono_defaults
.methodhandle_class
;
10925 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoField") == 0) {
10926 MonoClassField
*field
= ((MonoReflectionField
*)obj
)->field
;
10928 ensure_complete_type (field
->parent
);
10930 MonoType
*inflated
= mono_class_inflate_generic_type (&field
->parent
->byval_arg
, context
);
10931 MonoClass
*class = mono_class_from_mono_type (inflated
);
10932 MonoClassField
*inflated_field
;
10933 gpointer iter
= NULL
;
10934 mono_metadata_free_type (inflated
);
10935 while ((inflated_field
= mono_class_get_fields (class, &iter
))) {
10936 if (!strcmp (field
->name
, inflated_field
->name
))
10939 g_assert (inflated_field
&& !strcmp (field
->name
, inflated_field
->name
));
10940 result
= inflated_field
;
10944 *handle_class
= mono_defaults
.fieldhandle_class
;
10946 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldBuilder") == 0) {
10947 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
10948 result
= fb
->handle
;
10951 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
10953 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10954 result
= fb
->handle
;
10957 if (fb
->handle
&& fb
->handle
->parent
->generic_container
) {
10958 MonoClass
*klass
= fb
->handle
->parent
;
10959 MonoType
*type
= mono_class_inflate_generic_type (&klass
->byval_arg
, context
);
10960 MonoClass
*inflated
= mono_class_from_mono_type (type
);
10962 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (fb
->handle
));
10964 mono_metadata_free_type (type
);
10966 *handle_class
= mono_defaults
.fieldhandle_class
;
10967 } else if (strcmp (obj
->vtable
->klass
->name
, "TypeBuilder") == 0) {
10968 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
10969 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)tb
);
10972 klass
= type
->data
.klass
;
10973 if (klass
->wastypebuilder
) {
10974 /* Already created */
10978 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10979 result
= type
->data
.klass
;
10982 *handle_class
= mono_defaults
.typehandle_class
;
10983 } else if (strcmp (obj
->vtable
->klass
->name
, "SignatureHelper") == 0) {
10984 MonoReflectionSigHelper
*helper
= (MonoReflectionSigHelper
*)obj
;
10985 MonoMethodSignature
*sig
;
10988 if (helper
->arguments
)
10989 nargs
= mono_array_length (helper
->arguments
);
10993 sig
= mono_metadata_signature_alloc (image
, nargs
);
10994 sig
->explicit_this
= helper
->call_conv
& 64 ? 1 : 0;
10995 sig
->hasthis
= helper
->call_conv
& 32 ? 1 : 0;
10997 if (helper
->call_conv
== 0) /* unmanaged */
10998 sig
->call_convention
= helper
->unmanaged_call_conv
- 1;
11000 if (helper
->call_conv
& 0x02)
11001 sig
->call_convention
= MONO_CALL_VARARG
;
11003 sig
->call_convention
= MONO_CALL_DEFAULT
;
11005 sig
->param_count
= nargs
;
11006 /* TODO: Copy type ? */
11007 sig
->ret
= helper
->return_type
->type
;
11008 for (i
= 0; i
< nargs
; ++i
)
11009 sig
->params
[i
] = mono_type_array_get_and_resolve (helper
->arguments
, i
);
11012 *handle_class
= NULL
;
11013 } else if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
11014 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
11015 /* Already created by the managed code */
11016 g_assert (method
->mhandle
);
11017 result
= method
->mhandle
;
11018 *handle_class
= mono_defaults
.methodhandle_class
;
11019 } else if (strcmp (obj
->vtable
->klass
->name
, "GenericTypeParameterBuilder") == 0) {
11020 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
11021 type
= mono_class_inflate_generic_type (type
, context
);
11022 result
= mono_class_from_mono_type (type
);
11023 *handle_class
= mono_defaults
.typehandle_class
;
11025 mono_metadata_free_type (type
);
11026 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoGenericClass") == 0) {
11027 MonoType
*type
= mono_reflection_type_get_handle ((MonoReflectionType
*)obj
);
11028 type
= mono_class_inflate_generic_type (type
, context
);
11029 result
= mono_class_from_mono_type (type
);
11030 *handle_class
= mono_defaults
.typehandle_class
;
11032 mono_metadata_free_type (type
);
11033 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldOnTypeBuilderInst") == 0) {
11034 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
11035 MonoClass
*inflated
;
11038 type
= mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType
*)f
->inst
), context
);
11039 inflated
= mono_class_from_mono_type (type
);
11041 g_assert (f
->fb
->handle
);
11042 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (f
->fb
->handle
));
11044 mono_metadata_free_type (type
);
11045 *handle_class
= mono_defaults
.fieldhandle_class
;
11046 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
11047 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
11048 MonoType
*type
= mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType
*)c
->inst
), context
);
11049 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
11050 g_assert (c
->cb
->mhandle
);
11051 result
= inflate_mono_method (inflated_klass
, c
->cb
->mhandle
, (MonoObject
*)c
->cb
);
11052 *handle_class
= mono_defaults
.methodhandle_class
;
11053 mono_metadata_free_type (type
);
11054 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodOnTypeBuilderInst") == 0) {
11055 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
11056 MonoType
*type
= mono_class_inflate_generic_type (mono_reflection_type_get_handle ((MonoReflectionType
*)m
->inst
), context
);
11057 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
11058 g_assert (m
->mb
->mhandle
);
11059 result
= inflate_mono_method (inflated_klass
, m
->mb
->mhandle
, (MonoObject
*)m
->mb
);
11060 *handle_class
= mono_defaults
.methodhandle_class
;
11061 mono_metadata_free_type (type
);
11062 } else if (is_sre_array (mono_object_get_class(obj
)) ||
11063 is_sre_byref (mono_object_get_class(obj
)) ||
11064 is_sre_pointer (mono_object_get_class(obj
))) {
11065 MonoReflectionType
*ref_type
= (MonoReflectionType
*)obj
;
11066 MonoType
*type
= mono_reflection_type_get_handle (ref_type
);
11067 result
= mono_class_from_mono_type (type
);
11068 *handle_class
= mono_defaults
.typehandle_class
;
11070 g_print (obj
->vtable
->klass
->name
);
11071 g_assert_not_reached ();
11076 #else /* DISABLE_REFLECTION_EMIT */
11079 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
11081 g_assert_not_reached ();
11086 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
11088 g_assert_not_reached ();
11092 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
11094 g_assert_not_reached ();
11098 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
11100 g_assert_not_reached ();
11104 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
11106 g_assert_not_reached ();
11110 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
11112 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
11116 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
11118 g_assert_not_reached ();
11122 mono_image_set_wrappers_type (MonoReflectionModuleBuilder
*moduleb
, MonoReflectionType
*type
)
11124 g_assert_not_reached ();
11127 MonoReflectionModule
*
11128 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
11130 g_assert_not_reached ();
11135 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
11137 g_assert_not_reached ();
11142 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
11144 g_assert_not_reached ();
11149 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
11150 gboolean create_methodspec
, gboolean register_token
)
11152 g_assert_not_reached ();
11157 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
11162 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
11163 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
11166 g_assert_not_reached ();
11170 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
11173 *num_overrides
= 0;
11176 MonoReflectionEvent
*
11177 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
11179 g_assert_not_reached ();
11183 MonoReflectionType
*
11184 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
11186 g_assert_not_reached ();
11191 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
11193 g_assert_not_reached ();
11197 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
11199 g_assert_not_reached ();
11204 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
11206 g_assert_not_reached ();
11211 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
11216 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
11222 mono_reflection_type_get_handle (MonoReflectionType
* ref
)
11229 #endif /* DISABLE_REFLECTION_EMIT */
11231 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11232 const static guint32 declsec_flags_map
[] = {
11233 0x00000000, /* empty */
11234 MONO_DECLSEC_FLAG_REQUEST
, /* SECURITY_ACTION_REQUEST (x01) */
11235 MONO_DECLSEC_FLAG_DEMAND
, /* SECURITY_ACTION_DEMAND (x02) */
11236 MONO_DECLSEC_FLAG_ASSERT
, /* SECURITY_ACTION_ASSERT (x03) */
11237 MONO_DECLSEC_FLAG_DENY
, /* SECURITY_ACTION_DENY (x04) */
11238 MONO_DECLSEC_FLAG_PERMITONLY
, /* SECURITY_ACTION_PERMITONLY (x05) */
11239 MONO_DECLSEC_FLAG_LINKDEMAND
, /* SECURITY_ACTION_LINKDEMAND (x06) */
11240 MONO_DECLSEC_FLAG_INHERITANCEDEMAND
, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11241 MONO_DECLSEC_FLAG_REQUEST_MINIMUM
, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11242 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL
, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11243 MONO_DECLSEC_FLAG_REQUEST_REFUSE
, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11244 MONO_DECLSEC_FLAG_PREJIT_GRANT
, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11245 MONO_DECLSEC_FLAG_PREJIT_DENY
, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11246 MONO_DECLSEC_FLAG_NONCAS_DEMAND
, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11247 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11248 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11249 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11250 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11251 MONO_DECLSEC_FLAG_DEMAND_CHOICE
, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11255 * Returns flags that includes all available security action associated to the handle.
11256 * @token: metadata token (either for a class or a method)
11257 * @image: image where resides the metadata.
11260 mono_declsec_get_flags (MonoImage
*image
, guint32 token
)
11262 int index
= mono_metadata_declsec_from_index (image
, token
);
11263 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11264 guint32 result
= 0;
11268 /* HasSecurity can be present for other, not specially encoded, attributes,
11269 e.g. SuppressUnmanagedCodeSecurityAttribute */
11273 for (i
= index
; i
< t
->rows
; i
++) {
11274 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11276 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11277 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
11280 action
= cols
[MONO_DECL_SECURITY_ACTION
];
11281 if ((action
>= MONO_DECLSEC_ACTION_MIN
) && (action
<= MONO_DECLSEC_ACTION_MAX
)) {
11282 result
|= declsec_flags_map
[action
];
11284 g_assert_not_reached ();
11291 * Get the security actions (in the form of flags) associated with the specified method.
11293 * @method: The method for which we want the declarative security flags.
11294 * Return the declarative security flags for the method (only).
11296 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11297 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11300 mono_declsec_flags_from_method (MonoMethod
*method
)
11302 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11303 /* FIXME: No cache (for the moment) */
11304 guint32 idx
= mono_method_get_index (method
);
11305 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11306 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11307 return mono_declsec_get_flags (method
->klass
->image
, idx
);
11313 * Get the security actions (in the form of flags) associated with the specified class.
11315 * @klass: The class for which we want the declarative security flags.
11316 * Return the declarative security flags for the class.
11318 * Note: We cache the flags inside the MonoClass structure as this will get
11319 * called very often (at least for each method).
11322 mono_declsec_flags_from_class (MonoClass
*klass
)
11324 if (klass
->flags
& TYPE_ATTRIBUTE_HAS_SECURITY
) {
11325 if (!klass
->ext
|| !klass
->ext
->declsec_flags
) {
11328 idx
= mono_metadata_token_index (klass
->type_token
);
11329 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11330 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11331 mono_loader_lock ();
11332 mono_class_alloc_ext (klass
);
11333 mono_loader_unlock ();
11334 /* we cache the flags on classes */
11335 klass
->ext
->declsec_flags
= mono_declsec_get_flags (klass
->image
, idx
);
11337 return klass
->ext
->declsec_flags
;
11343 * Get the security actions (in the form of flags) associated with the specified assembly.
11345 * @assembly: The assembly for which we want the declarative security flags.
11346 * Return the declarative security flags for the assembly.
11349 mono_declsec_flags_from_assembly (MonoAssembly
*assembly
)
11351 guint32 idx
= 1; /* there is only one assembly */
11352 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11353 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
11354 return mono_declsec_get_flags (assembly
->image
, idx
);
11359 * Fill actions for the specific index (which may either be an encoded class token or
11360 * an encoded method token) from the metadata image.
11361 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11364 fill_actions_from_index (MonoImage
*image
, guint32 token
, MonoDeclSecurityActions
* actions
,
11365 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11367 MonoBoolean result
= FALSE
;
11369 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11370 int index
= mono_metadata_declsec_from_index (image
, token
);
11373 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11374 for (i
= index
; i
< t
->rows
; i
++) {
11375 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11377 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
11380 /* if present only replace (class) permissions with method permissions */
11381 /* if empty accept either class or method permissions */
11382 if (cols
[MONO_DECL_SECURITY_ACTION
] == id_std
) {
11383 if (!actions
->demand
.blob
) {
11384 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11385 actions
->demand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11386 actions
->demand
.blob
= (char*) (blob
+ 2);
11387 actions
->demand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11390 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_noncas
) {
11391 if (!actions
->noncasdemand
.blob
) {
11392 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11393 actions
->noncasdemand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11394 actions
->noncasdemand
.blob
= (char*) (blob
+ 2);
11395 actions
->noncasdemand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11398 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_choice
) {
11399 if (!actions
->demandchoice
.blob
) {
11400 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11401 actions
->demandchoice
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11402 actions
->demandchoice
.blob
= (char*) (blob
+ 2);
11403 actions
->demandchoice
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11413 mono_declsec_get_class_demands_params (MonoClass
*klass
, MonoDeclSecurityActions
* demands
,
11414 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11416 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
11417 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11418 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11419 return fill_actions_from_index (klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
11423 mono_declsec_get_method_demands_params (MonoMethod
*method
, MonoDeclSecurityActions
* demands
,
11424 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11426 guint32 idx
= mono_method_get_index (method
);
11427 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11428 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11429 return fill_actions_from_index (method
->klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
11433 * Collect all actions (that requires to generate code in mini) assigned for
11434 * the specified method.
11435 * Note: Don't use the content of actions if the function return FALSE.
11438 mono_declsec_get_demands (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
11440 guint32 mask
= MONO_DECLSEC_FLAG_DEMAND
| MONO_DECLSEC_FLAG_NONCAS_DEMAND
|
11441 MONO_DECLSEC_FLAG_DEMAND_CHOICE
;
11442 MonoBoolean result
= FALSE
;
11445 /* quick exit if no declarative security is present in the metadata */
11446 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11449 /* we want the original as the wrapper is "free" of the security informations */
11450 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11451 method
= mono_marshal_method_from_wrapper (method
);
11456 /* First we look for method-level attributes */
11457 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11458 mono_class_init (method
->klass
);
11459 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11461 result
= mono_declsec_get_method_demands_params (method
, demands
,
11462 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
11465 /* Here we use (or create) the class declarative cache to look for demands */
11466 flags
= mono_declsec_flags_from_class (method
->klass
);
11467 if (flags
& mask
) {
11469 mono_class_init (method
->klass
);
11470 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11472 result
|= mono_declsec_get_class_demands_params (method
->klass
, demands
,
11473 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
11476 /* The boolean return value is used as a shortcut in case nothing needs to
11477 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11483 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11485 * Note: Don't use the content of actions if the function return FALSE.
11488 mono_declsec_get_linkdemands (MonoMethod
*method
, MonoDeclSecurityActions
* klass
, MonoDeclSecurityActions
*cmethod
)
11490 MonoBoolean result
= FALSE
;
11493 /* quick exit if no declarative security is present in the metadata */
11494 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11497 /* we want the original as the wrapper is "free" of the security informations */
11498 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11499 method
= mono_marshal_method_from_wrapper (method
);
11504 /* results are independant - zeroize both */
11505 memset (cmethod
, 0, sizeof (MonoDeclSecurityActions
));
11506 memset (klass
, 0, sizeof (MonoDeclSecurityActions
));
11508 /* First we look for method-level attributes */
11509 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11510 mono_class_init (method
->klass
);
11512 result
= mono_declsec_get_method_demands_params (method
, cmethod
,
11513 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
11516 /* Here we use (or create) the class declarative cache to look for demands */
11517 flags
= mono_declsec_flags_from_class (method
->klass
);
11518 if (flags
& (MONO_DECLSEC_FLAG_LINKDEMAND
| MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
| MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
)) {
11519 mono_class_init (method
->klass
);
11521 result
|= mono_declsec_get_class_demands_params (method
->klass
, klass
,
11522 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
11529 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11531 * @klass The inherited class - this is the class that provides the security check (attributes)
11533 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11535 * Note: Don't use the content of actions if the function return FALSE.
11538 mono_declsec_get_inheritdemands_class (MonoClass
*klass
, MonoDeclSecurityActions
* demands
)
11540 MonoBoolean result
= FALSE
;
11543 /* quick exit if no declarative security is present in the metadata */
11544 if (!klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11547 /* Here we use (or create) the class declarative cache to look for demands */
11548 flags
= mono_declsec_flags_from_class (klass
);
11549 if (flags
& (MONO_DECLSEC_FLAG_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
)) {
11550 mono_class_init (klass
);
11551 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11553 result
|= mono_declsec_get_class_demands_params (klass
, demands
,
11554 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
11561 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11563 * Note: Don't use the content of actions if the function return FALSE.
11566 mono_declsec_get_inheritdemands_method (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
11568 /* quick exit if no declarative security is present in the metadata */
11569 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11572 /* we want the original as the wrapper is "free" of the security informations */
11573 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11574 method
= mono_marshal_method_from_wrapper (method
);
11579 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11580 mono_class_init (method
->klass
);
11581 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11583 return mono_declsec_get_method_demands_params (method
, demands
,
11584 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
11591 get_declsec_action (MonoImage
*image
, guint32 token
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11593 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11597 int index
= mono_metadata_declsec_from_index (image
, token
);
11601 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11602 for (i
= index
; i
< t
->rows
; i
++) {
11603 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11605 /* shortcut - index are ordered */
11606 if (token
!= cols
[MONO_DECL_SECURITY_PARENT
])
11609 if (cols
[MONO_DECL_SECURITY_ACTION
] == action
) {
11610 const char *metadata
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11611 entry
->blob
= (char*) (metadata
+ 2);
11612 entry
->size
= mono_metadata_decode_blob_size (metadata
, &metadata
);
11621 mono_declsec_get_method_action (MonoMethod
*method
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11623 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11624 guint32 idx
= mono_method_get_index (method
);
11625 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11626 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11627 return get_declsec_action (method
->klass
->image
, idx
, action
, entry
);
11633 mono_declsec_get_class_action (MonoClass
*klass
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11636 guint32 flags
= mono_declsec_flags_from_class (klass
);
11637 if (declsec_flags_map
[action
] & flags
) {
11638 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
11639 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11640 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11641 return get_declsec_action (klass
->image
, idx
, action
, entry
);
11647 mono_declsec_get_assembly_action (MonoAssembly
*assembly
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11649 guint32 idx
= 1; /* there is only one assembly */
11650 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11651 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
11653 return get_declsec_action (assembly
->image
, idx
, action
, entry
);
11657 mono_reflection_call_is_assignable_to (MonoClass
*klass
, MonoClass
*oklass
)
11659 MonoObject
*res
, *exc
;
11661 static MonoClass
*System_Reflection_Emit_TypeBuilder
= NULL
;
11662 static MonoMethod
*method
= NULL
;
11664 if (!System_Reflection_Emit_TypeBuilder
) {
11665 System_Reflection_Emit_TypeBuilder
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection.Emit", "TypeBuilder");
11666 g_assert (System_Reflection_Emit_TypeBuilder
);
11668 if (method
== NULL
) {
11669 method
= mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder
, "IsAssignableTo", 1);
11674 * The result of mono_type_get_object () might be a System.MonoType but we
11675 * need a TypeBuilder so use klass->reflection_info.
11677 g_assert (klass
->reflection_info
);
11678 g_assert (!strcmp (((MonoObject
*)(klass
->reflection_info
))->vtable
->klass
->name
, "TypeBuilder"));
11680 params
[0] = mono_type_get_object (mono_domain_get (), &oklass
->byval_arg
);
11682 res
= mono_runtime_invoke (method
, (MonoObject
*)(klass
->reflection_info
), params
, &exc
);
11686 return *(MonoBoolean
*)mono_object_unbox (res
);