2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * (C) 2001, 2002 Ximian, Inc. http://www.ximian.com
14 #include "mono/utils/mono-digest.h"
15 #include "mono/utils/mono-membar.h"
16 #include "mono/metadata/reflection.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/metadata-internals.h"
19 #include <mono/metadata/profiler-private.h>
20 #include "mono/metadata/class-internals.h"
21 #include "mono/metadata/gc-internal.h"
22 #include "mono/metadata/tokentype.h"
23 #include "mono/metadata/domain-internals.h"
24 #include "mono/metadata/opcodes.h"
25 #include "mono/metadata/assembly.h"
26 #include "mono/metadata/object-internals.h"
27 #include <mono/metadata/exception.h>
28 #include <mono/metadata/marshal.h>
29 #include <mono/metadata/security-manager.h>
38 #include "mono-endian.h"
39 #include <mono/metadata/gc-internal.h>
40 #include <mono/metadata/mempool-internals.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 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
);
153 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
);
154 static guint32
mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
);
155 static guint32
mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
);
156 static guint32
mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
);
157 static guint32
mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
);
158 static guint32
mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*cb
);
159 static guint32
mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
);
160 static void mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
);
161 static guint32
encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
);
162 static guint32
encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
);
163 static char* type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
);
164 static void ensure_runtime_vtable (MonoClass
*klass
);
165 static gpointer
resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
);
166 static void encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
);
167 static void get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
);
168 static MonoObject
*mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
);
169 static MonoReflectionType
*mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
);
170 static MonoType
* mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
);
171 static guint32
mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
);
172 static guint32
encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
);
174 #define mono_reflection_lock() EnterCriticalSection (&reflection_mutex)
175 #define mono_reflection_unlock() LeaveCriticalSection (&reflection_mutex)
176 static CRITICAL_SECTION reflection_mutex
;
179 mono_reflection_init (void)
181 InitializeCriticalSection (&reflection_mutex
);
185 sigbuffer_init (SigBuffer
*buf
, int size
)
187 buf
->buf
= g_malloc (size
);
189 buf
->end
= buf
->buf
+ size
;
193 sigbuffer_make_room (SigBuffer
*buf
, int size
)
195 if (buf
->end
- buf
->p
< size
) {
196 int new_size
= buf
->end
- buf
->buf
+ size
+ 32;
197 char *p
= g_realloc (buf
->buf
, new_size
);
198 size
= buf
->p
- buf
->buf
;
201 buf
->end
= buf
->buf
+ new_size
;
206 sigbuffer_add_value (SigBuffer
*buf
, guint32 val
)
208 sigbuffer_make_room (buf
, 6);
209 mono_metadata_encode_value (val
, buf
->p
, &buf
->p
);
213 sigbuffer_add_byte (SigBuffer
*buf
, guint8 val
)
215 sigbuffer_make_room (buf
, 1);
221 sigbuffer_add_mem (SigBuffer
*buf
, char *p
, guint32 size
)
223 sigbuffer_make_room (buf
, size
);
224 memcpy (buf
->p
, p
, size
);
229 sigbuffer_free (SigBuffer
*buf
)
237 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
241 mp_g_malloc (MonoMemPool
*mp
, guint size
)
244 return mono_mempool_alloc (mp
, size
);
246 return g_malloc (size
);
252 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate memory
256 mp_g_malloc0 (MonoMemPool
*mp
, guint size
)
259 return mono_mempool_alloc0 (mp
, size
);
261 return g_malloc0 (size
);
267 * Allocate memory from the mempool MP if it is non-NULL. Otherwise, allocate
268 * memory from the C heap.
271 mp_string_to_utf8 (MonoMemPool
*mp
, MonoString
*s
)
274 return mono_string_to_utf8_mp (mp
, s
);
276 return mono_string_to_utf8 (s
);
279 #define mp_g_new(mp,struct_type, n_structs) \
280 ((struct_type *) mp_g_malloc (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
282 #define mp_g_new0(mp,struct_type, n_structs) \
283 ((struct_type *) mp_g_malloc0 (mp, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
286 alloc_table (MonoDynamicTable
*table
, guint nrows
)
289 g_assert (table
->columns
);
290 if (nrows
+ 1 >= table
->alloc_rows
) {
291 while (nrows
+ 1 >= table
->alloc_rows
) {
292 if (table
->alloc_rows
== 0)
293 table
->alloc_rows
= 16;
295 table
->alloc_rows
*= 2;
298 table
->values
= g_renew (guint32
, table
->values
, (table
->alloc_rows
) * table
->columns
);
303 make_room_in_stream (MonoDynamicStream
*stream
, int size
)
305 if (size
<= stream
->alloc_size
)
308 while (stream
->alloc_size
<= size
) {
309 if (stream
->alloc_size
< 4096)
310 stream
->alloc_size
= 4096;
312 stream
->alloc_size
*= 2;
315 stream
->data
= g_realloc (stream
->data
, stream
->alloc_size
);
319 string_heap_insert (MonoDynamicStream
*sh
, const char *str
)
323 gpointer oldkey
, oldval
;
325 if (g_hash_table_lookup_extended (sh
->hash
, str
, &oldkey
, &oldval
))
326 return GPOINTER_TO_UINT (oldval
);
328 len
= strlen (str
) + 1;
331 make_room_in_stream (sh
, idx
+ len
);
334 * We strdup the string even if we already copy them in sh->data
335 * so that the string pointers in the hash remain valid even if
336 * we need to realloc sh->data. We may want to avoid that later.
338 g_hash_table_insert (sh
->hash
, g_strdup (str
), GUINT_TO_POINTER (idx
));
339 memcpy (sh
->data
+ idx
, str
, len
);
345 string_heap_insert_mstring (MonoDynamicStream
*sh
, MonoString
*str
)
347 char *name
= mono_string_to_utf8 (str
);
349 idx
= string_heap_insert (sh
, name
);
355 string_heap_init (MonoDynamicStream
*sh
)
358 sh
->alloc_size
= 4096;
359 sh
->data
= g_malloc (4096);
360 sh
->hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
361 string_heap_insert (sh
, "");
365 mono_image_add_stream_data (MonoDynamicStream
*stream
, const char *data
, guint32 len
)
369 make_room_in_stream (stream
, stream
->index
+ len
);
370 memcpy (stream
->data
+ stream
->index
, data
, len
);
372 stream
->index
+= len
;
374 * align index? Not without adding an additional param that controls it since
375 * we may store a blob value in pieces.
381 mono_image_add_stream_zero (MonoDynamicStream
*stream
, guint32 len
)
385 make_room_in_stream (stream
, stream
->index
+ len
);
386 memset (stream
->data
+ stream
->index
, 0, len
);
388 stream
->index
+= len
;
393 stream_data_align (MonoDynamicStream
*stream
)
396 guint32 count
= stream
->index
% 4;
398 /* we assume the stream data will be aligned */
400 mono_image_add_stream_data (stream
, buf
, 4 - count
);
404 mono_blob_entry_hash (const char* str
)
408 len
= mono_metadata_decode_blob_size (str
, &str
);
412 for (str
+= 1; str
< end
; str
++)
413 h
= (h
<< 5) - h
+ *str
;
421 mono_blob_entry_equal (const char *str1
, const char *str2
) {
425 len
= mono_metadata_decode_blob_size (str1
, &end1
);
426 len2
= mono_metadata_decode_blob_size (str2
, &end2
);
429 return memcmp (end1
, end2
, len
) == 0;
433 add_to_blob_cached (MonoDynamicImage
*assembly
, char *b1
, int s1
, char *b2
, int s2
)
437 gpointer oldkey
, oldval
;
439 copy
= g_malloc (s1
+s2
);
440 memcpy (copy
, b1
, s1
);
441 memcpy (copy
+ s1
, b2
, s2
);
442 if (g_hash_table_lookup_extended (assembly
->blob_cache
, copy
, &oldkey
, &oldval
)) {
444 idx
= GPOINTER_TO_UINT (oldval
);
446 idx
= mono_image_add_stream_data (&assembly
->blob
, b1
, s1
);
447 mono_image_add_stream_data (&assembly
->blob
, b2
, s2
);
448 g_hash_table_insert (assembly
->blob_cache
, copy
, GUINT_TO_POINTER (idx
));
454 sigbuffer_add_to_blob_cached (MonoDynamicImage
*assembly
, SigBuffer
*buf
)
458 guint32 size
= buf
->p
- buf
->buf
;
460 g_assert (size
<= (buf
->end
- buf
->buf
));
461 mono_metadata_encode_value (size
, b
, &b
);
462 return add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, buf
->buf
, size
);
466 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
467 * dest may be misaligned.
470 swap_with_size (char *dest
, const char* val
, int len
, int nelem
) {
471 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
474 for (elem
= 0; elem
< nelem
; ++elem
) {
500 g_assert_not_reached ();
506 memcpy (dest
, val
, len
* nelem
);
511 add_mono_string_to_blob_cached (MonoDynamicImage
*assembly
, MonoString
*str
)
515 guint32 idx
= 0, len
;
517 len
= str
->length
* 2;
518 mono_metadata_encode_value (len
, b
, &b
);
519 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
521 char *swapped
= g_malloc (2 * mono_string_length (str
));
522 const char *p
= (const char*)mono_string_chars (str
);
524 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
525 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
529 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
534 /* modified version needed to handle building corlib */
536 my_mono_class_from_mono_type (MonoType
*type
) {
537 switch (type
->type
) {
538 case MONO_TYPE_ARRAY
:
540 case MONO_TYPE_SZARRAY
:
541 case MONO_TYPE_GENERICINST
:
542 return mono_class_from_mono_type (type
);
545 g_assert (type
->data
.generic_param
->pklass
);
546 return type
->data
.generic_param
->pklass
;
548 /* should be always valid when we reach this case... */
549 return type
->data
.klass
;
554 default_class_from_mono_type (MonoType
*type
)
556 switch (type
->type
) {
557 case MONO_TYPE_OBJECT
:
558 return mono_defaults
.object_class
;
560 return mono_defaults
.void_class
;
561 case MONO_TYPE_BOOLEAN
:
562 return mono_defaults
.boolean_class
;
564 return mono_defaults
.char_class
;
566 return mono_defaults
.sbyte_class
;
568 return mono_defaults
.byte_class
;
570 return mono_defaults
.int16_class
;
572 return mono_defaults
.uint16_class
;
574 return mono_defaults
.int32_class
;
576 return mono_defaults
.uint32_class
;
578 return mono_defaults
.int_class
;
580 return mono_defaults
.uint_class
;
582 return mono_defaults
.int64_class
;
584 return mono_defaults
.uint64_class
;
586 return mono_defaults
.single_class
;
588 return mono_defaults
.double_class
;
589 case MONO_TYPE_STRING
:
590 return mono_defaults
.string_class
;
592 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type
->type
);
593 g_assert_not_reached ();
600 encode_generic_class (MonoDynamicImage
*assembly
, MonoGenericClass
*gclass
, SigBuffer
*buf
)
603 MonoGenericInst
*class_inst
;
608 class_inst
= gclass
->context
.class_inst
;
610 sigbuffer_add_value (buf
, MONO_TYPE_GENERICINST
);
611 klass
= gclass
->container_class
;
612 sigbuffer_add_value (buf
, klass
->byval_arg
.type
);
613 sigbuffer_add_value (buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
615 sigbuffer_add_value (buf
, class_inst
->type_argc
);
616 for (i
= 0; i
< class_inst
->type_argc
; ++i
)
617 encode_type (assembly
, class_inst
->type_argv
[i
], buf
);
622 encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
)
625 g_assert_not_reached ();
630 sigbuffer_add_value (buf
, MONO_TYPE_BYREF
);
634 case MONO_TYPE_BOOLEAN
:
648 case MONO_TYPE_STRING
:
649 case MONO_TYPE_OBJECT
:
650 case MONO_TYPE_TYPEDBYREF
:
651 sigbuffer_add_value (buf
, type
->type
);
654 sigbuffer_add_value (buf
, type
->type
);
655 encode_type (assembly
, type
->data
.type
, buf
);
657 case MONO_TYPE_SZARRAY
:
658 sigbuffer_add_value (buf
, type
->type
);
659 encode_type (assembly
, &type
->data
.klass
->byval_arg
, buf
);
661 case MONO_TYPE_VALUETYPE
:
662 case MONO_TYPE_CLASS
: {
663 MonoClass
*k
= mono_class_from_mono_type (type
);
665 if (k
->generic_container
) {
666 MonoGenericClass
*gclass
= mono_metadata_lookup_generic_class (k
, k
->generic_container
->context
.class_inst
, TRUE
);
667 encode_generic_class (assembly
, gclass
, buf
);
670 * Make sure we use the correct type.
672 sigbuffer_add_value (buf
, k
->byval_arg
.type
);
674 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
675 * otherwise two typerefs could point to the same type, leading to
676 * verification errors.
678 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, &k
->byval_arg
));
682 case MONO_TYPE_ARRAY
:
683 sigbuffer_add_value (buf
, type
->type
);
684 encode_type (assembly
, &type
->data
.array
->eklass
->byval_arg
, buf
);
685 sigbuffer_add_value (buf
, type
->data
.array
->rank
);
686 sigbuffer_add_value (buf
, 0); /* FIXME: set to 0 for now */
687 sigbuffer_add_value (buf
, 0);
689 case MONO_TYPE_GENERICINST
:
690 encode_generic_class (assembly
, type
->data
.generic_class
, buf
);
694 sigbuffer_add_value (buf
, type
->type
);
695 sigbuffer_add_value (buf
, type
->data
.generic_param
->num
);
698 g_error ("need to encode type %x", type
->type
);
703 encode_reflection_type (MonoDynamicImage
*assembly
, MonoReflectionType
*type
, SigBuffer
*buf
)
706 sigbuffer_add_value (buf
, MONO_TYPE_VOID
);
711 ((type
= mono_reflection_type_get_underlying_system_type (type
)) && type
->type
)) {
712 encode_type (assembly
, type
->type
, buf
);
716 g_assert_not_reached ();
721 encode_custom_modifiers (MonoDynamicImage
*assembly
, MonoArray
*modreq
, MonoArray
*modopt
, SigBuffer
*buf
)
726 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
727 MonoReflectionType
*mod
= mono_array_get (modreq
, MonoReflectionType
*, i
);
728 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_REQD
);
729 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
->type
));
733 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
734 MonoReflectionType
*mod
= mono_array_get (modopt
, MonoReflectionType
*, i
);
735 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_OPT
);
736 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
->type
));
742 method_encode_signature (MonoDynamicImage
*assembly
, MonoMethodSignature
*sig
)
746 guint32 nparams
= sig
->param_count
;
752 sigbuffer_init (&buf
, 32);
754 * FIXME: vararg, explicit_this, differenc call_conv values...
756 idx
= sig
->call_convention
;
758 idx
|= 0x20; /* hasthis */
759 if (sig
->generic_param_count
)
760 idx
|= 0x10; /* generic */
761 sigbuffer_add_byte (&buf
, idx
);
762 if (sig
->generic_param_count
)
763 sigbuffer_add_value (&buf
, sig
->generic_param_count
);
764 sigbuffer_add_value (&buf
, nparams
);
765 encode_type (assembly
, sig
->ret
, &buf
);
766 for (i
= 0; i
< nparams
; ++i
) {
767 if (i
== sig
->sentinelpos
)
768 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
769 encode_type (assembly
, sig
->params
[i
], &buf
);
771 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
772 sigbuffer_free (&buf
);
777 method_builder_encode_signature (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
780 * FIXME: reuse code from method_encode_signature().
784 guint32 nparams
= mb
->parameters
? mono_array_length (mb
->parameters
): 0;
785 guint32 ngparams
= mb
->generic_params
? mono_array_length (mb
->generic_params
): 0;
786 guint32 notypes
= mb
->opt_types
? mono_array_length (mb
->opt_types
): 0;
789 sigbuffer_init (&buf
, 32);
790 /* LAMESPEC: all the call conv spec is foobared */
791 idx
= mb
->call_conv
& 0x60; /* has-this, explicit-this */
792 if (mb
->call_conv
& 2)
793 idx
|= 0x5; /* vararg */
794 if (!(mb
->attrs
& METHOD_ATTRIBUTE_STATIC
))
795 idx
|= 0x20; /* hasthis */
797 idx
|= 0x10; /* generic */
798 sigbuffer_add_byte (&buf
, idx
);
800 sigbuffer_add_value (&buf
, ngparams
);
801 sigbuffer_add_value (&buf
, nparams
+ notypes
);
802 encode_custom_modifiers (assembly
, mb
->return_modreq
, mb
->return_modopt
, &buf
);
803 encode_reflection_type (assembly
, mb
->rtype
, &buf
);
804 for (i
= 0; i
< nparams
; ++i
) {
805 MonoArray
*modreq
= NULL
;
806 MonoArray
*modopt
= NULL
;
807 MonoReflectionType
*pt
;
809 if (mb
->param_modreq
&& (i
< mono_array_length (mb
->param_modreq
)))
810 modreq
= mono_array_get (mb
->param_modreq
, MonoArray
*, i
);
811 if (mb
->param_modopt
&& (i
< mono_array_length (mb
->param_modopt
)))
812 modopt
= mono_array_get (mb
->param_modopt
, MonoArray
*, i
);
813 encode_custom_modifiers (assembly
, modreq
, modopt
, &buf
);
814 pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
815 encode_reflection_type (assembly
, pt
, &buf
);
818 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
819 for (i
= 0; i
< notypes
; ++i
) {
820 MonoReflectionType
*pt
;
822 pt
= mono_array_get (mb
->opt_types
, MonoReflectionType
*, i
);
823 encode_reflection_type (assembly
, pt
, &buf
);
826 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
827 sigbuffer_free (&buf
);
832 encode_locals (MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
)
834 MonoDynamicTable
*table
;
836 guint32 idx
, sig_idx
;
837 guint nl
= mono_array_length (ilgen
->locals
);
841 sigbuffer_init (&buf
, 32);
842 sigbuffer_add_value (&buf
, 0x07);
843 sigbuffer_add_value (&buf
, nl
);
844 for (i
= 0; i
< nl
; ++i
) {
845 MonoReflectionLocalBuilder
*lb
= mono_array_get (ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
848 sigbuffer_add_value (&buf
, MONO_TYPE_PINNED
);
850 encode_reflection_type (assembly
, lb
->type
, &buf
);
852 sig_idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
853 sigbuffer_free (&buf
);
855 if (assembly
->standalonesig_cache
== NULL
)
856 assembly
->standalonesig_cache
= g_hash_table_new (NULL
, NULL
);
857 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
)));
861 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
862 idx
= table
->next_idx
++;
864 alloc_table (table
, table
->rows
);
865 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
867 values
[MONO_STAND_ALONE_SIGNATURE
] = sig_idx
;
869 g_hash_table_insert (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
), GUINT_TO_POINTER (idx
));
875 method_count_clauses (MonoReflectionILGen
*ilgen
)
877 guint32 num_clauses
= 0;
880 MonoILExceptionInfo
*ex_info
;
881 for (i
= 0; i
< mono_array_length (ilgen
->ex_handlers
); ++i
) {
882 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
883 if (ex_info
->handlers
)
884 num_clauses
+= mono_array_length (ex_info
->handlers
);
892 static MonoExceptionClause
*
893 method_encode_clauses (MonoMemPool
*mp
, MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
, guint32 num_clauses
)
895 MonoExceptionClause
*clauses
;
896 MonoExceptionClause
*clause
;
897 MonoILExceptionInfo
*ex_info
;
898 MonoILExceptionBlock
*ex_block
;
899 guint32 finally_start
;
900 int i
, j
, clause_index
;;
902 clauses
= mp_g_new0 (mp
, MonoExceptionClause
, num_clauses
);
905 for (i
= mono_array_length (ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
906 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
907 finally_start
= ex_info
->start
+ ex_info
->len
;
908 if (!ex_info
->handlers
)
910 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
911 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
912 clause
= &(clauses
[clause_index
]);
914 clause
->flags
= ex_block
->type
;
915 clause
->try_offset
= ex_info
->start
;
917 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
918 clause
->try_len
= finally_start
- ex_info
->start
;
920 clause
->try_len
= ex_info
->len
;
921 clause
->handler_offset
= ex_block
->start
;
922 clause
->handler_len
= ex_block
->len
;
923 if (ex_block
->extype
) {
924 clause
->data
.catch_class
= mono_class_from_mono_type (ex_block
->extype
->type
);
926 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
927 clause
->data
.filter_offset
= ex_block
->filter_offset
;
929 clause
->data
.filter_offset
= 0;
931 finally_start
= ex_block
->start
+ ex_block
->len
;
941 method_encode_code (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
947 gint32 num_locals
= 0;
948 gint32 num_exception
= 0;
951 char fat_header
[12];
954 guint32 local_sig
= 0;
955 guint32 header_size
= 12;
958 if ((mb
->attrs
& (METHOD_ATTRIBUTE_PINVOKE_IMPL
| METHOD_ATTRIBUTE_ABSTRACT
)) ||
959 (mb
->iattrs
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)))
963 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
965 code
= mb
->ilgen
->code
;
966 code_size
= mb
->ilgen
->code_len
;
967 max_stack
= mb
->ilgen
->max_stack
;
968 num_locals
= mb
->ilgen
->locals
? mono_array_length (mb
->ilgen
->locals
) : 0;
969 if (mb
->ilgen
->ex_handlers
)
970 num_exception
= method_count_clauses (mb
->ilgen
);
974 char *name
= mono_string_to_utf8 (mb
->name
);
975 char *str
= g_strdup_printf ("Method %s does not have any IL associated", name
);
976 MonoException
*exception
= mono_get_exception_argument (NULL
, "a method does not have any IL associated");
979 mono_raise_exception (exception
);
982 code_size
= mono_array_length (code
);
983 max_stack
= 8; /* we probably need to run a verifier on the code... */
986 stream_data_align (&assembly
->code
);
988 /* check for exceptions, maxstack, locals */
989 maybe_small
= (max_stack
<= 8) && (!num_locals
) && (!num_exception
);
991 if (code_size
< 64 && !(code_size
& 1)) {
992 flags
= (code_size
<< 2) | 0x2;
993 } else if (code_size
< 32 && (code_size
& 1)) {
994 flags
= (code_size
<< 2) | 0x6; /* LAMESPEC: see metadata.c */
998 idx
= mono_image_add_stream_data (&assembly
->code
, &flags
, 1);
999 /* add to the fixup todo list */
1000 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1001 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 1));
1002 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1003 return assembly
->text_rva
+ idx
;
1007 local_sig
= MONO_TOKEN_SIGNATURE
| encode_locals (assembly
, mb
->ilgen
);
1009 * FIXME: need to set also the header size in fat_flags.
1010 * (and more sects and init locals flags)
1014 fat_flags
|= METHOD_HEADER_MORE_SECTS
;
1015 if (mb
->init_locals
)
1016 fat_flags
|= METHOD_HEADER_INIT_LOCALS
;
1017 fat_header
[0] = fat_flags
;
1018 fat_header
[1] = (header_size
/ 4 ) << 4;
1019 short_value
= GUINT16_TO_LE (max_stack
);
1020 memcpy (fat_header
+ 2, &short_value
, 2);
1021 int_value
= GUINT32_TO_LE (code_size
);
1022 memcpy (fat_header
+ 4, &int_value
, 4);
1023 int_value
= GUINT32_TO_LE (local_sig
);
1024 memcpy (fat_header
+ 8, &int_value
, 4);
1025 idx
= mono_image_add_stream_data (&assembly
->code
, fat_header
, 12);
1026 /* add to the fixup todo list */
1027 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1028 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 12));
1030 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1031 if (num_exception
) {
1032 unsigned char sheader
[4];
1033 MonoILExceptionInfo
* ex_info
;
1034 MonoILExceptionBlock
* ex_block
;
1037 stream_data_align (&assembly
->code
);
1038 /* always use fat format for now */
1039 sheader
[0] = METHOD_HEADER_SECTION_FAT_FORMAT
| METHOD_HEADER_SECTION_EHTABLE
;
1040 num_exception
*= 6 * sizeof (guint32
);
1041 num_exception
+= 4; /* include the size of the header */
1042 sheader
[1] = num_exception
& 0xff;
1043 sheader
[2] = (num_exception
>> 8) & 0xff;
1044 sheader
[3] = (num_exception
>> 16) & 0xff;
1045 mono_image_add_stream_data (&assembly
->code
, (char*)sheader
, 4);
1046 /* fat header, so we are already aligned */
1048 for (i
= mono_array_length (mb
->ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
1049 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (mb
->ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
1050 if (ex_info
->handlers
) {
1051 int finally_start
= ex_info
->start
+ ex_info
->len
;
1052 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
1054 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
1056 val
= GUINT32_TO_LE (ex_block
->type
);
1057 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1059 val
= GUINT32_TO_LE (ex_info
->start
);
1060 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1061 /* need fault, too, probably */
1062 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
1063 val
= GUINT32_TO_LE (finally_start
- ex_info
->start
);
1065 val
= GUINT32_TO_LE (ex_info
->len
);
1066 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1067 /* handler offset */
1068 val
= GUINT32_TO_LE (ex_block
->start
);
1069 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1071 val
= GUINT32_TO_LE (ex_block
->len
);
1072 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1073 finally_start
= ex_block
->start
+ ex_block
->len
;
1074 if (ex_block
->extype
) {
1075 val
= mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly
, ex_block
->extype
->type
));
1077 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
1078 val
= ex_block
->filter_offset
;
1082 val
= GUINT32_TO_LE (val
);
1083 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1084 /*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",
1085 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);*/
1088 g_error ("No clauses for ex info block %d", i
);
1092 return assembly
->text_rva
+ idx
;
1096 find_index_in_table (MonoDynamicImage
*assembly
, int table_idx
, int col
, guint32 token
)
1099 MonoDynamicTable
*table
;
1102 table
= &assembly
->tables
[table_idx
];
1104 g_assert (col
< table
->columns
);
1106 values
= table
->values
+ table
->columns
;
1107 for (i
= 1; i
<= table
->rows
; ++i
) {
1108 if (values
[col
] == token
)
1110 values
+= table
->columns
;
1116 * LOCKING: Acquires the loader lock.
1118 static MonoCustomAttrInfo
*
1119 lookup_custom_attr (MonoImage
*image
, gpointer member
)
1121 MonoCustomAttrInfo
* res
;
1123 mono_loader_lock ();
1124 res
= mono_property_hash_lookup (image
->property_hash
, member
, MONO_PROP_DYNAMIC_CATTR
);
1125 mono_loader_unlock ();
1130 return g_memdup (res
, sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (res
->num_attrs
- MONO_ZERO_LEN_ARRAY
));
1134 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttr
*cattr
)
1136 /* FIXME: Need to do more checks */
1137 if (cattr
->ctor
->method
&& (cattr
->ctor
->method
->klass
->image
!= image
)) {
1138 int visibility
= cattr
->ctor
->method
->klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
1140 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
1147 static MonoCustomAttrInfo
*
1148 mono_custom_attrs_from_builders (MonoMemPool
*mp
, MonoImage
*image
, MonoArray
*cattrs
)
1150 int i
, index
, count
, not_visible
;
1151 MonoCustomAttrInfo
*ainfo
;
1152 MonoReflectionCustomAttr
*cattr
;
1156 /* FIXME: check in assembly the Run flag is set */
1158 count
= mono_array_length (cattrs
);
1160 /* Skip nonpublic attributes since MS.NET seems to do the same */
1161 /* FIXME: This needs to be done more globally */
1163 for (i
= 0; i
< count
; ++i
) {
1164 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1165 if (!custom_attr_visible (image
, cattr
))
1168 count
-= not_visible
;
1170 ainfo
= mp_g_malloc0 (mp
, sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (count
- MONO_ZERO_LEN_ARRAY
));
1172 ainfo
->image
= image
;
1173 ainfo
->num_attrs
= count
;
1174 ainfo
->cached
= mp
!= NULL
;
1176 mono_loader_lock ();
1177 for (i
= 0; i
< count
; ++i
) {
1178 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1179 if (custom_attr_visible (image
, cattr
)) {
1180 unsigned char *saved
= mono_image_alloc (image
, mono_array_length (cattr
->data
));
1181 memcpy (saved
, mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1182 ainfo
->attrs
[index
].ctor
= cattr
->ctor
->method
;
1183 ainfo
->attrs
[index
].data
= saved
;
1184 ainfo
->attrs
[index
].data_size
= mono_array_length (cattr
->data
);
1188 mono_loader_unlock ();
1194 * LOCKING: Acquires the loader lock.
1197 mono_save_custom_attrs (MonoImage
*image
, void *obj
, MonoArray
*cattrs
)
1199 MonoCustomAttrInfo
*ainfo
, *tmp
;
1201 if (!cattrs
|| !mono_array_length (cattrs
))
1204 ainfo
= mono_custom_attrs_from_builders (image
->mempool
, image
, cattrs
);
1205 mono_loader_lock ();
1206 tmp
= mono_property_hash_lookup (image
->property_hash
, obj
, MONO_PROP_DYNAMIC_CATTR
);
1208 mono_custom_attrs_free (tmp
);
1209 mono_property_hash_insert (image
->property_hash
, obj
, MONO_PROP_DYNAMIC_CATTR
, ainfo
);
1210 mono_loader_unlock ();
1214 mono_custom_attrs_free (MonoCustomAttrInfo
*ainfo
)
1221 * idx is the table index of the object
1222 * type is one of MONO_CUSTOM_ATTR_*
1225 mono_image_add_cattrs (MonoDynamicImage
*assembly
, guint32 idx
, guint32 type
, MonoArray
*cattrs
)
1227 MonoDynamicTable
*table
;
1228 MonoReflectionCustomAttr
*cattr
;
1230 guint32 count
, i
, token
;
1232 char *p
= blob_size
;
1234 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1237 count
= mono_array_length (cattrs
);
1238 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1239 table
->rows
+= count
;
1240 alloc_table (table
, table
->rows
);
1241 values
= table
->values
+ table
->next_idx
* MONO_CUSTOM_ATTR_SIZE
;
1242 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1244 for (i
= 0; i
< count
; ++i
) {
1245 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1246 values
[MONO_CUSTOM_ATTR_PARENT
] = idx
;
1247 token
= mono_image_create_token (assembly
, (MonoObject
*)cattr
->ctor
, FALSE
, FALSE
);
1248 type
= mono_metadata_token_index (token
);
1249 type
<<= MONO_CUSTOM_ATTR_TYPE_BITS
;
1250 switch (mono_metadata_token_table (token
)) {
1251 case MONO_TABLE_METHOD
:
1252 type
|= MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
1254 case MONO_TABLE_MEMBERREF
:
1255 type
|= MONO_CUSTOM_ATTR_TYPE_MEMBERREF
;
1258 g_warning ("got wrong token in custom attr");
1261 values
[MONO_CUSTOM_ATTR_TYPE
] = type
;
1263 mono_metadata_encode_value (mono_array_length (cattr
->data
), p
, &p
);
1264 values
[MONO_CUSTOM_ATTR_VALUE
] = add_to_blob_cached (assembly
, blob_size
, p
- blob_size
,
1265 mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1266 values
+= MONO_CUSTOM_ATTR_SIZE
;
1272 mono_image_add_decl_security (MonoDynamicImage
*assembly
, guint32 parent_token
, MonoArray
*permissions
)
1274 MonoDynamicTable
*table
;
1276 guint32 count
, i
, idx
;
1277 MonoReflectionPermissionSet
*perm
;
1282 count
= mono_array_length (permissions
);
1283 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
1284 table
->rows
+= count
;
1285 alloc_table (table
, table
->rows
);
1287 for (i
= 0; i
< mono_array_length (permissions
); ++i
) {
1288 perm
= (MonoReflectionPermissionSet
*)mono_array_addr (permissions
, MonoReflectionPermissionSet
, i
);
1290 values
= table
->values
+ table
->next_idx
* MONO_DECL_SECURITY_SIZE
;
1292 idx
= mono_metadata_token_index (parent_token
);
1293 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
1294 switch (mono_metadata_token_table (parent_token
)) {
1295 case MONO_TABLE_TYPEDEF
:
1296 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
1298 case MONO_TABLE_METHOD
:
1299 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
1301 case MONO_TABLE_ASSEMBLY
:
1302 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
1305 g_assert_not_reached ();
1308 values
[MONO_DECL_SECURITY_ACTION
] = perm
->action
;
1309 values
[MONO_DECL_SECURITY_PARENT
] = idx
;
1310 values
[MONO_DECL_SECURITY_PERMISSIONSET
] = add_mono_string_to_blob_cached (assembly
, perm
->pset
);
1317 * Fill in the MethodDef and ParamDef tables for a method.
1318 * This is used for both normal methods and constructors.
1321 mono_image_basic_method (ReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1323 MonoDynamicTable
*table
;
1327 /* room in this table is already allocated */
1328 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
1329 *mb
->table_idx
= table
->next_idx
++;
1330 g_hash_table_insert (assembly
->method_to_table_idx
, mb
->mhandle
, GUINT_TO_POINTER ((*mb
->table_idx
)));
1331 values
= table
->values
+ *mb
->table_idx
* MONO_METHOD_SIZE
;
1332 values
[MONO_METHOD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1333 values
[MONO_METHOD_FLAGS
] = mb
->attrs
;
1334 values
[MONO_METHOD_IMPLFLAGS
] = mb
->iattrs
;
1335 values
[MONO_METHOD_SIGNATURE
] = method_builder_encode_signature (assembly
, mb
);
1336 values
[MONO_METHOD_RVA
] = method_encode_code (assembly
, mb
);
1338 table
= &assembly
->tables
[MONO_TABLE_PARAM
];
1339 values
[MONO_METHOD_PARAMLIST
] = table
->next_idx
;
1341 mono_image_add_decl_security (assembly
,
1342 mono_metadata_make_token (MONO_TABLE_METHOD
, *mb
->table_idx
), mb
->permissions
);
1345 MonoDynamicTable
*mtable
;
1348 mtable
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1349 mvalues
= mtable
->values
+ mtable
->next_idx
* MONO_FIELD_MARSHAL_SIZE
;
1352 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1353 if (mono_array_get (mb
->pinfo
, gpointer
, i
))
1356 table
->rows
+= count
;
1357 alloc_table (table
, table
->rows
);
1358 values
= table
->values
+ table
->next_idx
* MONO_PARAM_SIZE
;
1359 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1360 MonoReflectionParamBuilder
*pb
;
1361 if ((pb
= mono_array_get (mb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
1362 values
[MONO_PARAM_FLAGS
] = pb
->attrs
;
1363 values
[MONO_PARAM_SEQUENCE
] = i
;
1364 if (pb
->name
!= NULL
) {
1365 values
[MONO_PARAM_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1367 values
[MONO_PARAM_NAME
] = 0;
1369 values
+= MONO_PARAM_SIZE
;
1370 if (pb
->marshal_info
) {
1372 alloc_table (mtable
, mtable
->rows
);
1373 mvalues
= mtable
->values
+ mtable
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1374 mvalues
[MONO_FIELD_MARSHAL_PARENT
] = (table
->next_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_PARAMDEF
;
1375 mvalues
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, pb
->marshal_info
);
1377 pb
->table_idx
= table
->next_idx
++;
1378 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
1379 guint32 field_type
= 0;
1380 mtable
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1382 alloc_table (mtable
, mtable
->rows
);
1383 mvalues
= mtable
->values
+ mtable
->rows
* MONO_CONSTANT_SIZE
;
1384 mvalues
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_PARAM
| (pb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1385 mvalues
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, pb
->def_value
, &field_type
);
1386 mvalues
[MONO_CONSTANT_TYPE
] = field_type
;
1387 mvalues
[MONO_CONSTANT_PADDING
] = 0;
1395 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
)
1397 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1399 rmb
->ilgen
= mb
->ilgen
;
1400 rmb
->rtype
= mb
->rtype
;
1401 rmb
->parameters
= mb
->parameters
;
1402 rmb
->generic_params
= mb
->generic_params
;
1403 rmb
->generic_container
= mb
->generic_container
;
1404 rmb
->opt_types
= NULL
;
1405 rmb
->pinfo
= mb
->pinfo
;
1406 rmb
->attrs
= mb
->attrs
;
1407 rmb
->iattrs
= mb
->iattrs
;
1408 rmb
->call_conv
= mb
->call_conv
;
1409 rmb
->code
= mb
->code
;
1410 rmb
->type
= mb
->type
;
1411 rmb
->name
= mb
->name
;
1412 rmb
->table_idx
= &mb
->table_idx
;
1413 rmb
->init_locals
= mb
->init_locals
;
1414 rmb
->skip_visibility
= FALSE
;
1415 rmb
->return_modreq
= mb
->return_modreq
;
1416 rmb
->return_modopt
= mb
->return_modopt
;
1417 rmb
->param_modreq
= mb
->param_modreq
;
1418 rmb
->param_modopt
= mb
->param_modopt
;
1419 rmb
->permissions
= mb
->permissions
;
1420 rmb
->mhandle
= mb
->mhandle
;
1425 rmb
->charset
= mb
->charset
;
1426 rmb
->extra_flags
= mb
->extra_flags
;
1427 rmb
->native_cc
= mb
->native_cc
;
1428 rmb
->dllentry
= mb
->dllentry
;
1434 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
)
1436 const char *name
= mb
->attrs
& METHOD_ATTRIBUTE_STATIC
? ".cctor": ".ctor";
1438 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1440 rmb
->ilgen
= mb
->ilgen
;
1441 rmb
->rtype
= mono_type_get_object (mono_domain_get (), &mono_defaults
.void_class
->byval_arg
);
1442 rmb
->parameters
= mb
->parameters
;
1443 rmb
->generic_params
= NULL
;
1444 rmb
->generic_container
= NULL
;
1445 rmb
->opt_types
= NULL
;
1446 rmb
->pinfo
= mb
->pinfo
;
1447 rmb
->attrs
= mb
->attrs
;
1448 rmb
->iattrs
= mb
->iattrs
;
1449 rmb
->call_conv
= mb
->call_conv
;
1451 rmb
->type
= mb
->type
;
1452 rmb
->name
= mono_string_new (mono_domain_get (), name
);
1453 rmb
->table_idx
= &mb
->table_idx
;
1454 rmb
->init_locals
= mb
->init_locals
;
1455 rmb
->skip_visibility
= FALSE
;
1456 rmb
->return_modreq
= NULL
;
1457 rmb
->return_modopt
= NULL
;
1458 rmb
->param_modreq
= mb
->param_modreq
;
1459 rmb
->param_modopt
= mb
->param_modopt
;
1460 rmb
->permissions
= mb
->permissions
;
1461 rmb
->mhandle
= mb
->mhandle
;
1467 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder
*rmb
, MonoReflectionDynamicMethod
*mb
)
1469 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1471 rmb
->ilgen
= mb
->ilgen
;
1472 rmb
->rtype
= mb
->rtype
;
1473 rmb
->parameters
= mb
->parameters
;
1474 rmb
->generic_params
= NULL
;
1475 rmb
->generic_container
= NULL
;
1476 rmb
->opt_types
= NULL
;
1478 rmb
->attrs
= mb
->attrs
;
1480 rmb
->call_conv
= mb
->call_conv
;
1482 rmb
->type
= (MonoObject
*) mb
->owner
;
1483 rmb
->name
= mb
->name
;
1484 rmb
->table_idx
= NULL
;
1485 rmb
->init_locals
= mb
->init_locals
;
1486 rmb
->skip_visibility
= mb
->skip_visibility
;
1487 rmb
->return_modreq
= NULL
;
1488 rmb
->return_modopt
= NULL
;
1489 rmb
->param_modreq
= NULL
;
1490 rmb
->param_modopt
= NULL
;
1491 rmb
->permissions
= NULL
;
1492 rmb
->mhandle
= mb
->mhandle
;
1498 mono_image_add_methodimpl (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
1500 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
1501 MonoDynamicTable
*table
;
1505 if (!mb
->override_method
)
1508 table
= &assembly
->tables
[MONO_TABLE_METHODIMPL
];
1510 alloc_table (table
, table
->rows
);
1511 values
= table
->values
+ table
->rows
* MONO_METHODIMPL_SIZE
;
1512 values
[MONO_METHODIMPL_CLASS
] = tb
->table_idx
;
1513 values
[MONO_METHODIMPL_BODY
] = MONO_METHODDEFORREF_METHODDEF
| (mb
->table_idx
<< MONO_METHODDEFORREF_BITS
);
1515 tok
= mono_image_create_token (assembly
, (MonoObject
*)mb
->override_method
, FALSE
, FALSE
);
1516 switch (mono_metadata_token_table (tok
)) {
1517 case MONO_TABLE_MEMBERREF
:
1518 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
1520 case MONO_TABLE_METHOD
:
1521 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
1524 g_assert_not_reached ();
1526 values
[MONO_METHODIMPL_DECLARATION
] = tok
;
1530 mono_image_get_method_info (MonoReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1532 MonoDynamicTable
*table
;
1534 ReflectionMethodBuilder rmb
;
1537 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
1539 mono_image_basic_method (&rmb
, assembly
);
1540 mb
->table_idx
= *rmb
.table_idx
;
1542 if (mb
->dll
) { /* It's a P/Invoke method */
1544 /* map CharSet values to on-disk values */
1545 int ncharset
= (mb
->charset
? (mb
->charset
- 1) * 2 : 0);
1546 int extra_flags
= mb
->extra_flags
;
1547 table
= &assembly
->tables
[MONO_TABLE_IMPLMAP
];
1549 alloc_table (table
, table
->rows
);
1550 values
= table
->values
+ table
->rows
* MONO_IMPLMAP_SIZE
;
1552 values
[MONO_IMPLMAP_FLAGS
] = (mb
->native_cc
<< 8) | ncharset
| extra_flags
;
1553 values
[MONO_IMPLMAP_MEMBER
] = (mb
->table_idx
<< 1) | 1; /* memberforwarded: method */
1555 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->dllentry
);
1557 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1558 moduleref
= string_heap_insert_mstring (&assembly
->sheap
, mb
->dll
);
1559 if (!(values
[MONO_IMPLMAP_SCOPE
] = find_index_in_table (assembly
, MONO_TABLE_MODULEREF
, MONO_MODULEREF_NAME
, moduleref
))) {
1560 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
1562 alloc_table (table
, table
->rows
);
1563 table
->values
[table
->rows
* MONO_MODULEREF_SIZE
+ MONO_MODULEREF_NAME
] = moduleref
;
1564 values
[MONO_IMPLMAP_SCOPE
] = table
->rows
;
1568 if (mb
->generic_params
) {
1569 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
1570 table
->rows
+= mono_array_length (mb
->generic_params
);
1571 alloc_table (table
, table
->rows
);
1572 for (i
= 0; i
< mono_array_length (mb
->generic_params
); ++i
) {
1573 guint32 owner
= MONO_TYPEORMETHOD_METHOD
| (mb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
1575 mono_image_get_generic_param_info (
1576 mono_array_get (mb
->generic_params
, gpointer
, i
), owner
, assembly
);
1583 mono_image_get_ctor_info (MonoDomain
*domain
, MonoReflectionCtorBuilder
*mb
, MonoDynamicImage
*assembly
)
1585 ReflectionMethodBuilder rmb
;
1587 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
1589 mono_image_basic_method (&rmb
, assembly
);
1590 mb
->table_idx
= *rmb
.table_idx
;
1594 type_get_fully_qualified_name (MonoType
*type
)
1596 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1600 type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
) {
1604 klass
= my_mono_class_from_mono_type (type
);
1606 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1607 ta
= klass
->image
->assembly
;
1608 if (ta
->dynamic
|| (ta
== ass
)) {
1609 if (klass
->generic_class
|| klass
->generic_container
)
1610 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1611 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_FULL_NAME
);
1613 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1616 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1620 fieldref_encode_signature (MonoDynamicImage
*assembly
, MonoType
*type
)
1625 if (!assembly
->save
)
1628 sigbuffer_init (&buf
, 32);
1630 sigbuffer_add_value (&buf
, 0x06);
1631 /* encode custom attributes before the type */
1632 /* FIXME: This should probably go in encode_type () */
1633 if (type
->num_mods
) {
1634 for (i
= 0; i
< type
->num_mods
; ++i
) {
1635 if (type
->modifiers
[i
].required
)
1636 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_REQD
);
1638 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_OPT
);
1639 sigbuffer_add_value (&buf
, type
->modifiers
[i
].token
);
1642 encode_type (assembly
, type
, &buf
);
1643 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1644 sigbuffer_free (&buf
);
1649 field_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
1654 sigbuffer_init (&buf
, 32);
1656 sigbuffer_add_value (&buf
, 0x06);
1657 encode_custom_modifiers (assembly
, fb
->modreq
, fb
->modopt
, &buf
);
1658 /* encode custom attributes before the type */
1659 encode_reflection_type (assembly
, fb
->type
, &buf
);
1660 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1661 sigbuffer_free (&buf
);
1666 encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
) {
1667 char blob_size
[64];
1668 char *b
= blob_size
;
1671 guint32 idx
= 0, len
= 0, dummy
= 0;
1673 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1674 guint32 fpa_double
[2];
1679 p
= buf
= g_malloc (64);
1681 *ret_type
= MONO_TYPE_CLASS
;
1683 box_val
= (char*)&dummy
;
1685 box_val
= ((char*)val
) + sizeof (MonoObject
);
1686 *ret_type
= val
->vtable
->klass
->byval_arg
.type
;
1689 switch (*ret_type
) {
1690 case MONO_TYPE_BOOLEAN
:
1695 case MONO_TYPE_CHAR
:
1712 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1713 fpa_p
= (guint32
*)box_val
;
1714 fpa_double
[0] = fpa_p
[1];
1715 fpa_double
[1] = fpa_p
[0];
1716 box_val
= (char*)fpa_double
;
1720 case MONO_TYPE_VALUETYPE
:
1721 if (val
->vtable
->klass
->enumtype
) {
1722 *ret_type
= val
->vtable
->klass
->enum_basetype
->type
;
1725 g_error ("we can't encode valuetypes");
1726 case MONO_TYPE_CLASS
:
1728 case MONO_TYPE_STRING
: {
1729 MonoString
*str
= (MonoString
*)val
;
1730 /* there is no signature */
1731 len
= str
->length
* 2;
1732 mono_metadata_encode_value (len
, b
, &b
);
1733 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1735 char *swapped
= g_malloc (2 * mono_string_length (str
));
1736 const char *p
= (const char*)mono_string_chars (str
);
1738 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
1739 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
1743 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
1749 case MONO_TYPE_GENERICINST
:
1750 *ret_type
= val
->vtable
->klass
->generic_class
->container_class
->byval_arg
.type
;
1753 g_error ("we don't encode constant type 0x%02x yet", *ret_type
);
1756 /* there is no signature */
1757 mono_metadata_encode_value (len
, b
, &b
);
1758 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1759 idx
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
1760 swap_with_size (blob_size
, box_val
, len
, 1);
1761 mono_image_add_stream_data (&assembly
->blob
, blob_size
, len
);
1763 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, box_val
, len
);
1771 encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
) {
1776 sigbuffer_init (&buf
, 32);
1778 sigbuffer_add_value (&buf
, minfo
->type
);
1780 switch (minfo
->type
) {
1781 case MONO_NATIVE_BYVALTSTR
:
1782 case MONO_NATIVE_BYVALARRAY
:
1783 sigbuffer_add_value (&buf
, minfo
->count
);
1785 case MONO_NATIVE_LPARRAY
:
1786 if (minfo
->eltype
|| minfo
->has_size
) {
1787 sigbuffer_add_value (&buf
, minfo
->eltype
);
1788 if (minfo
->has_size
) {
1789 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? minfo
->param_num
: 0);
1790 sigbuffer_add_value (&buf
, minfo
->count
!= -1? minfo
->count
: 0);
1792 /* LAMESPEC: ElemMult is undocumented */
1793 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? 1: 0);
1797 case MONO_NATIVE_CUSTOM
:
1799 str
= mono_string_to_utf8 (minfo
->guid
);
1801 sigbuffer_add_value (&buf
, len
);
1802 sigbuffer_add_mem (&buf
, str
, len
);
1805 sigbuffer_add_value (&buf
, 0);
1807 /* native type name */
1808 sigbuffer_add_value (&buf
, 0);
1809 /* custom marshaler type name */
1810 if (minfo
->marshaltype
|| minfo
->marshaltyperef
) {
1811 if (minfo
->marshaltyperef
)
1812 str
= type_get_fully_qualified_name (minfo
->marshaltyperef
->type
);
1814 str
= mono_string_to_utf8 (minfo
->marshaltype
);
1816 sigbuffer_add_value (&buf
, len
);
1817 sigbuffer_add_mem (&buf
, str
, len
);
1820 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1821 sigbuffer_add_value (&buf
, 0);
1823 if (minfo
->mcookie
) {
1824 str
= mono_string_to_utf8 (minfo
->mcookie
);
1826 sigbuffer_add_value (&buf
, len
);
1827 sigbuffer_add_mem (&buf
, str
, len
);
1830 sigbuffer_add_value (&buf
, 0);
1836 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1837 sigbuffer_free (&buf
);
1842 mono_image_get_field_info (MonoReflectionFieldBuilder
*fb
, MonoDynamicImage
*assembly
)
1844 MonoDynamicTable
*table
;
1847 /* maybe this fixup should be done in the C# code */
1848 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
)
1849 fb
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
1850 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
1851 fb
->table_idx
= table
->next_idx
++;
1852 g_hash_table_insert (assembly
->field_to_table_idx
, fb
->handle
, GUINT_TO_POINTER (fb
->table_idx
));
1853 values
= table
->values
+ fb
->table_idx
* MONO_FIELD_SIZE
;
1854 values
[MONO_FIELD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, fb
->name
);
1855 values
[MONO_FIELD_FLAGS
] = fb
->attrs
;
1856 values
[MONO_FIELD_SIGNATURE
] = field_encode_signature (assembly
, fb
);
1858 if (fb
->offset
!= -1) {
1859 table
= &assembly
->tables
[MONO_TABLE_FIELDLAYOUT
];
1861 alloc_table (table
, table
->rows
);
1862 values
= table
->values
+ table
->rows
* MONO_FIELD_LAYOUT_SIZE
;
1863 values
[MONO_FIELD_LAYOUT_FIELD
] = fb
->table_idx
;
1864 values
[MONO_FIELD_LAYOUT_OFFSET
] = fb
->offset
;
1866 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
) {
1867 guint32 field_type
= 0;
1868 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1870 alloc_table (table
, table
->rows
);
1871 values
= table
->values
+ table
->rows
* MONO_CONSTANT_SIZE
;
1872 values
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_FIEDDEF
| (fb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1873 values
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, fb
->def_value
, &field_type
);
1874 values
[MONO_CONSTANT_TYPE
] = field_type
;
1875 values
[MONO_CONSTANT_PADDING
] = 0;
1877 if (fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
1879 table
= &assembly
->tables
[MONO_TABLE_FIELDRVA
];
1881 alloc_table (table
, table
->rows
);
1882 values
= table
->values
+ table
->rows
* MONO_FIELD_RVA_SIZE
;
1883 values
[MONO_FIELD_RVA_FIELD
] = fb
->table_idx
;
1885 * We store it in the code section because it's simpler for now.
1888 if (mono_array_length (fb
->rva_data
) >= 10)
1889 stream_data_align (&assembly
->code
);
1890 rva_idx
= mono_image_add_stream_data (&assembly
->code
, mono_array_addr (fb
->rva_data
, char, 0), mono_array_length (fb
->rva_data
));
1892 rva_idx
= mono_image_add_stream_zero (&assembly
->code
, mono_class_value_size (fb
->handle
->parent
, NULL
));
1893 values
[MONO_FIELD_RVA_RVA
] = rva_idx
+ assembly
->text_rva
;
1895 if (fb
->marshal_info
) {
1896 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1898 alloc_table (table
, table
->rows
);
1899 values
= table
->values
+ table
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1900 values
[MONO_FIELD_MARSHAL_PARENT
] = (fb
->table_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_FIELDSREF
;
1901 values
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, fb
->marshal_info
);
1906 property_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionPropertyBuilder
*fb
)
1909 guint32 nparams
= 0;
1910 MonoReflectionMethodBuilder
*mb
= fb
->get_method
;
1911 MonoReflectionMethodBuilder
*smb
= fb
->set_method
;
1914 if (mb
&& mb
->parameters
)
1915 nparams
= mono_array_length (mb
->parameters
);
1916 if (!mb
&& smb
&& smb
->parameters
)
1917 nparams
= mono_array_length (smb
->parameters
) - 1;
1918 sigbuffer_init (&buf
, 32);
1919 sigbuffer_add_byte (&buf
, 0x08);
1920 sigbuffer_add_value (&buf
, nparams
);
1922 encode_reflection_type (assembly
, mb
->rtype
, &buf
);
1923 for (i
= 0; i
< nparams
; ++i
) {
1924 MonoReflectionType
*pt
= mono_array_get (mb
->parameters
, MonoReflectionType
*, i
);
1925 encode_reflection_type (assembly
, pt
, &buf
);
1927 } else if (smb
&& smb
->parameters
) {
1928 /* the property type is the last param */
1929 encode_reflection_type (assembly
, mono_array_get (smb
->parameters
, MonoReflectionType
*, nparams
), &buf
);
1930 for (i
= 0; i
< nparams
; ++i
) {
1931 MonoReflectionType
*pt
= mono_array_get (smb
->parameters
, MonoReflectionType
*, i
);
1932 encode_reflection_type (assembly
, pt
, &buf
);
1935 encode_reflection_type (assembly
, fb
->type
, &buf
);
1938 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1939 sigbuffer_free (&buf
);
1944 mono_image_get_property_info (MonoReflectionPropertyBuilder
*pb
, MonoDynamicImage
*assembly
)
1946 MonoDynamicTable
*table
;
1948 guint num_methods
= 0;
1952 * we need to set things in the following tables:
1953 * PROPERTYMAP (info already filled in _get_type_info ())
1954 * PROPERTY (rows already preallocated in _get_type_info ())
1955 * METHOD (method info already done with the generic method code)
1958 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
1959 pb
->table_idx
= table
->next_idx
++;
1960 values
= table
->values
+ pb
->table_idx
* MONO_PROPERTY_SIZE
;
1961 values
[MONO_PROPERTY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1962 values
[MONO_PROPERTY_FLAGS
] = pb
->attrs
;
1963 values
[MONO_PROPERTY_TYPE
] = property_encode_signature (assembly
, pb
);
1965 /* FIXME: we still don't handle 'other' methods */
1966 if (pb
->get_method
) num_methods
++;
1967 if (pb
->set_method
) num_methods
++;
1969 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
1970 table
->rows
+= num_methods
;
1971 alloc_table (table
, table
->rows
);
1973 if (pb
->get_method
) {
1974 semaidx
= table
->next_idx
++;
1975 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
1976 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_GETTER
;
1977 values
[MONO_METHOD_SEMA_METHOD
] = pb
->get_method
->table_idx
;
1978 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
1980 if (pb
->set_method
) {
1981 semaidx
= table
->next_idx
++;
1982 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
1983 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_SETTER
;
1984 values
[MONO_METHOD_SEMA_METHOD
] = pb
->set_method
->table_idx
;
1985 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
1990 mono_image_get_event_info (MonoReflectionEventBuilder
*eb
, MonoDynamicImage
*assembly
)
1992 MonoDynamicTable
*table
;
1994 guint num_methods
= 0;
1998 * we need to set things in the following tables:
1999 * EVENTMAP (info already filled in _get_type_info ())
2000 * EVENT (rows already preallocated in _get_type_info ())
2001 * METHOD (method info already done with the generic method code)
2004 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
2005 eb
->table_idx
= table
->next_idx
++;
2006 values
= table
->values
+ eb
->table_idx
* MONO_EVENT_SIZE
;
2007 values
[MONO_EVENT_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, eb
->name
);
2008 values
[MONO_EVENT_FLAGS
] = eb
->attrs
;
2009 values
[MONO_EVENT_TYPE
] = mono_image_typedef_or_ref (assembly
, eb
->type
->type
);
2012 * FIXME: we still don't handle 'other' methods
2014 if (eb
->add_method
) num_methods
++;
2015 if (eb
->remove_method
) num_methods
++;
2016 if (eb
->raise_method
) num_methods
++;
2018 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
2019 table
->rows
+= num_methods
;
2020 alloc_table (table
, table
->rows
);
2022 if (eb
->add_method
) {
2023 semaidx
= table
->next_idx
++;
2024 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2025 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_ADD_ON
;
2026 values
[MONO_METHOD_SEMA_METHOD
] = eb
->add_method
->table_idx
;
2027 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2029 if (eb
->remove_method
) {
2030 semaidx
= table
->next_idx
++;
2031 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2032 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_REMOVE_ON
;
2033 values
[MONO_METHOD_SEMA_METHOD
] = eb
->remove_method
->table_idx
;
2034 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2036 if (eb
->raise_method
) {
2037 semaidx
= table
->next_idx
++;
2038 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2039 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_FIRE
;
2040 values
[MONO_METHOD_SEMA_METHOD
] = eb
->raise_method
->table_idx
;
2041 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2046 encode_constraints (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2048 MonoDynamicTable
*table
;
2049 guint32 num_constraints
, i
;
2053 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
2054 num_constraints
= gparam
->iface_constraints
?
2055 mono_array_length (gparam
->iface_constraints
) : 0;
2056 table
->rows
+= num_constraints
;
2057 if (gparam
->base_type
)
2059 alloc_table (table
, table
->rows
);
2061 if (gparam
->base_type
) {
2062 table_idx
= table
->next_idx
++;
2063 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2065 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2066 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2067 assembly
, gparam
->base_type
->type
);
2070 for (i
= 0; i
< num_constraints
; i
++) {
2071 MonoReflectionType
*constraint
= mono_array_get (
2072 gparam
->iface_constraints
, gpointer
, i
);
2074 table_idx
= table
->next_idx
++;
2075 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2077 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2078 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2079 assembly
, constraint
->type
);
2084 mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2086 GenericParamTableEntry
*entry
;
2089 * The GenericParam table must be sorted according to the `owner' field.
2090 * We need to do this sorting prior to writing the GenericParamConstraint
2091 * table, since we have to use the final GenericParam table indices there
2092 * and they must also be sorted.
2095 entry
= g_new0 (GenericParamTableEntry
, 1);
2096 entry
->owner
= owner
;
2097 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2098 MOVING_GC_REGISTER (&entry
->gparam
);
2099 entry
->gparam
= gparam
;
2101 g_ptr_array_add (assembly
->gen_params
, entry
);
2105 write_generic_param_entry (MonoDynamicImage
*assembly
, GenericParamTableEntry
*entry
)
2107 MonoDynamicTable
*table
;
2108 MonoGenericParam
*param
;
2112 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
2113 table_idx
= table
->next_idx
++;
2114 values
= table
->values
+ table_idx
* MONO_GENERICPARAM_SIZE
;
2116 param
= entry
->gparam
->type
.type
->data
.generic_param
;
2118 values
[MONO_GENERICPARAM_OWNER
] = entry
->owner
;
2119 values
[MONO_GENERICPARAM_FLAGS
] = entry
->gparam
->attrs
;
2120 values
[MONO_GENERICPARAM_NUMBER
] = param
->num
;
2121 values
[MONO_GENERICPARAM_NAME
] = string_heap_insert (&assembly
->sheap
, param
->name
);
2123 mono_image_add_cattrs (assembly
, table_idx
, MONO_CUSTOM_ATTR_GENERICPAR
, entry
->gparam
->cattrs
);
2125 encode_constraints (entry
->gparam
, table_idx
, assembly
);
2129 resolution_scope_from_image (MonoDynamicImage
*assembly
, MonoImage
*image
)
2131 MonoDynamicTable
*table
;
2134 guint32 cols
[MONO_ASSEMBLY_SIZE
];
2138 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, image
))))
2141 if (image
->assembly
->dynamic
&& (image
->assembly
== assembly
->image
.assembly
)) {
2142 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
2143 token
= table
->next_idx
++;
2145 alloc_table (table
, table
->rows
);
2146 values
= table
->values
+ token
* MONO_MODULEREF_SIZE
;
2147 values
[MONO_MODULEREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->module_name
);
2149 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2150 token
|= MONO_RESOLTION_SCOPE_MODULEREF
;
2151 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2156 if (image
->assembly
->dynamic
)
2158 memset (cols
, 0, sizeof (cols
));
2160 /* image->assembly->image is the manifest module */
2161 image
= image
->assembly
->image
;
2162 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_ASSEMBLY
], 0, cols
, MONO_ASSEMBLY_SIZE
);
2165 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLYREF
];
2166 token
= table
->next_idx
++;
2168 alloc_table (table
, table
->rows
);
2169 values
= table
->values
+ token
* MONO_ASSEMBLYREF_SIZE
;
2170 values
[MONO_ASSEMBLYREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->assembly_name
);
2171 values
[MONO_ASSEMBLYREF_MAJOR_VERSION
] = cols
[MONO_ASSEMBLY_MAJOR_VERSION
];
2172 values
[MONO_ASSEMBLYREF_MINOR_VERSION
] = cols
[MONO_ASSEMBLY_MINOR_VERSION
];
2173 values
[MONO_ASSEMBLYREF_BUILD_NUMBER
] = cols
[MONO_ASSEMBLY_BUILD_NUMBER
];
2174 values
[MONO_ASSEMBLYREF_REV_NUMBER
] = cols
[MONO_ASSEMBLY_REV_NUMBER
];
2175 values
[MONO_ASSEMBLYREF_FLAGS
] = 0;
2176 values
[MONO_ASSEMBLYREF_CULTURE
] = 0;
2177 values
[MONO_ASSEMBLYREF_HASH_VALUE
] = 0;
2179 if (strcmp ("", image
->assembly
->aname
.culture
)) {
2180 values
[MONO_ASSEMBLYREF_CULTURE
] = string_heap_insert (&assembly
->sheap
,
2181 image
->assembly
->aname
.culture
);
2184 if ((pubkey
= mono_image_get_public_key (image
, &publen
))) {
2185 guchar pubtoken
[9];
2187 mono_digest_get_public_token (pubtoken
+ 1, (guchar
*)pubkey
, publen
);
2188 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = mono_image_add_stream_data (&assembly
->blob
, (char*)pubtoken
, 9);
2190 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = 0;
2192 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2193 token
|= MONO_RESOLTION_SCOPE_ASSEMBLYREF
;
2194 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2199 create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
)
2201 MonoDynamicTable
*table
;
2206 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
))))
2209 sigbuffer_init (&buf
, 32);
2210 switch (type
->type
) {
2211 case MONO_TYPE_FNPTR
:
2213 case MONO_TYPE_SZARRAY
:
2214 case MONO_TYPE_ARRAY
:
2216 case MONO_TYPE_MVAR
:
2217 case MONO_TYPE_GENERICINST
:
2218 encode_type (assembly
, type
, &buf
);
2220 case MONO_TYPE_CLASS
:
2221 case MONO_TYPE_VALUETYPE
: {
2222 MonoClass
*k
= mono_class_from_mono_type (type
);
2223 if (!k
|| !k
->generic_container
) {
2224 sigbuffer_free (&buf
);
2227 encode_type (assembly
, type
, &buf
);
2231 sigbuffer_free (&buf
);
2235 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2236 if (assembly
->save
) {
2237 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2238 alloc_table (table
, table
->rows
+ 1);
2239 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2240 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2242 sigbuffer_free (&buf
);
2244 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2245 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
2251 mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
)
2253 MonoDynamicTable
*table
;
2255 guint32 token
, scope
, enclosing
;
2258 /* if the type requires a typespec, we must try that first*/
2259 if (try_typespec
&& (token
= create_typespec (assembly
, type
)))
2261 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typeref
, type
));
2264 klass
= my_mono_class_from_mono_type (type
);
2266 klass
= mono_class_from_mono_type (type
);
2269 * If it's in the same module and not a generic type parameter:
2271 if ((klass
->image
== &assembly
->image
) && (type
->type
!= MONO_TYPE_VAR
) &&
2272 (type
->type
!= MONO_TYPE_MVAR
)) {
2273 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
2274 token
= MONO_TYPEDEFORREF_TYPEDEF
| (tb
->table_idx
<< MONO_TYPEDEFORREF_BITS
);
2275 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), klass
->reflection_info
);
2279 if (klass
->nested_in
) {
2280 enclosing
= mono_image_typedef_or_ref_full (assembly
, &klass
->nested_in
->byval_arg
, FALSE
);
2281 /* get the typeref idx of the enclosing type */
2282 enclosing
>>= MONO_TYPEDEFORREF_BITS
;
2283 scope
= (enclosing
<< MONO_RESOLTION_SCOPE_BITS
) | MONO_RESOLTION_SCOPE_TYPEREF
;
2285 scope
= resolution_scope_from_image (assembly
, klass
->image
);
2287 table
= &assembly
->tables
[MONO_TABLE_TYPEREF
];
2288 if (assembly
->save
) {
2289 alloc_table (table
, table
->rows
+ 1);
2290 values
= table
->values
+ table
->next_idx
* MONO_TYPEREF_SIZE
;
2291 values
[MONO_TYPEREF_SCOPE
] = scope
;
2292 values
[MONO_TYPEREF_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
2293 values
[MONO_TYPEREF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
2295 token
= MONO_TYPEDEFORREF_TYPEREF
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
); /* typeref */
2296 g_hash_table_insert (assembly
->typeref
, type
, GUINT_TO_POINTER(token
));
2298 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), klass
->reflection_info
);
2303 * Despite the name, we handle also TypeSpec (with the above helper).
2306 mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
)
2308 return mono_image_typedef_or_ref_full (assembly
, type
, TRUE
);
2312 * Insert a memberef row into the metadata: the token that point to the memberref
2313 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2314 * mono_image_get_fieldref_token()).
2315 * The sig param is an index to an already built signature.
2318 mono_image_get_memberref_token (MonoDynamicImage
*assembly
, MonoType
*type
, const char *name
, guint32 sig
)
2320 MonoDynamicTable
*table
;
2322 guint32 token
, pclass
;
2325 parent
= mono_image_typedef_or_ref (assembly
, type
);
2326 switch (parent
& MONO_TYPEDEFORREF_MASK
) {
2327 case MONO_TYPEDEFORREF_TYPEREF
:
2328 pclass
= MONO_MEMBERREF_PARENT_TYPEREF
;
2330 case MONO_TYPEDEFORREF_TYPESPEC
:
2331 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2333 case MONO_TYPEDEFORREF_TYPEDEF
:
2334 pclass
= MONO_MEMBERREF_PARENT_TYPEDEF
;
2337 g_warning ("unknown typeref or def token 0x%08x for %s", parent
, name
);
2340 /* extract the index */
2341 parent
>>= MONO_TYPEDEFORREF_BITS
;
2343 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2345 if (assembly
->save
) {
2346 alloc_table (table
, table
->rows
+ 1);
2347 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2348 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2349 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2350 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2353 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2360 mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
)
2363 MonoMethodSignature
*sig
;
2365 create_typespec
= create_typespec
&& method
->is_generic
&& method
->klass
->image
!= &assembly
->image
;
2367 if (create_typespec
) {
2368 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1)));
2373 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2374 if (token
&& !create_typespec
)
2377 g_assert (!method
->is_inflated
);
2380 * A methodref signature can't contain an unmanaged calling convention.
2382 sig
= mono_metadata_signature_dup (mono_method_signature (method
));
2383 if ((sig
->call_convention
!= MONO_CALL_DEFAULT
) && (sig
->call_convention
!= MONO_CALL_VARARG
))
2384 sig
->call_convention
= MONO_CALL_DEFAULT
;
2385 token
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
,
2386 method
->name
, method_encode_signature (assembly
, sig
));
2388 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2391 if (create_typespec
) {
2392 MonoDynamicTable
*table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2393 g_assert (mono_metadata_token_table (token
) == MONO_TABLE_MEMBERREF
);
2394 token
= (mono_metadata_token_index (token
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2396 if (assembly
->save
) {
2399 alloc_table (table
, table
->rows
+ 1);
2400 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2401 values
[MONO_METHODSPEC_METHOD
] = token
;
2402 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_sig (assembly
, &mono_method_get_generic_container (method
)->context
);
2405 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2407 /*methodspec and memberef tokens are diferent, */
2408 g_hash_table_insert (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1), GUINT_TO_POINTER (token
));
2415 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
)
2418 ReflectionMethodBuilder rmb
;
2421 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2425 name
= mono_string_to_utf8 (method
->name
);
2426 reflection_methodbuilder_from_method_builder (&rmb
, method
);
2429 * A methodref signature can't contain an unmanaged calling convention.
2430 * Since some flags are encoded as part of call_conv, we need to check against it.
2432 if ((rmb
.call_conv
& ~0x60) != MONO_CALL_DEFAULT
&& (rmb
.call_conv
& ~0x60) != MONO_CALL_VARARG
)
2433 rmb
.call_conv
= (rmb
.call_conv
& 0x60) | MONO_CALL_DEFAULT
;
2434 token
= mono_image_get_memberref_token (assembly
, ((MonoReflectionTypeBuilder
*)rmb
.type
)->type
.type
,
2435 name
, method_builder_encode_signature (assembly
, &rmb
));
2438 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2443 mono_image_get_varargs_method_token (MonoDynamicImage
*assembly
, guint32 original
,
2444 const gchar
*name
, guint32 sig
)
2446 MonoDynamicTable
*table
;
2450 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2452 if (assembly
->save
) {
2453 alloc_table (table
, table
->rows
+ 1);
2454 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2455 values
[MONO_MEMBERREF_CLASS
] = original
;
2456 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2457 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2460 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2467 encode_generic_method_definition_sig (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2471 guint32 nparams
= mono_array_length (mb
->generic_params
);
2474 if (!assembly
->save
)
2477 sigbuffer_init (&buf
, 32);
2479 sigbuffer_add_value (&buf
, 0xa);
2480 sigbuffer_add_value (&buf
, nparams
);
2482 for (i
= 0; i
< nparams
; i
++) {
2483 sigbuffer_add_value (&buf
, MONO_TYPE_MVAR
);
2484 sigbuffer_add_value (&buf
, i
);
2487 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2488 sigbuffer_free (&buf
);
2493 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2495 MonoDynamicTable
*table
;
2497 guint32 token
, mtoken
= 0;
2499 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->methodspec
, mb
));
2503 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2505 mtoken
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2506 switch (mono_metadata_token_table (mtoken
)) {
2507 case MONO_TABLE_MEMBERREF
:
2508 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2510 case MONO_TABLE_METHOD
:
2511 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2514 g_assert_not_reached ();
2517 if (assembly
->save
) {
2518 alloc_table (table
, table
->rows
+ 1);
2519 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2520 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2521 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_definition_sig (assembly
, mb
);
2524 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2527 mono_g_hash_table_insert (assembly
->methodspec
, mb
, GUINT_TO_POINTER(token
));
2532 mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
)
2536 if (mb
->generic_params
&& create_methodspec
)
2537 return mono_image_get_methodspec_token_for_generic_method_definition (assembly
, mb
);
2539 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, mb
));
2543 token
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2544 g_hash_table_insert (assembly
->handleref
, mb
, GUINT_TO_POINTER(token
));
2549 mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*mb
)
2552 ReflectionMethodBuilder rmb
;
2555 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, mb
));
2559 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
2561 name
= mono_string_to_utf8 (rmb
.name
);
2562 token
= mono_image_get_memberref_token (assembly
, ((MonoReflectionTypeBuilder
*)rmb
.type
)->type
.type
,
2563 name
, method_builder_encode_signature (assembly
, &rmb
));
2566 g_hash_table_insert (assembly
->handleref
, mb
, GUINT_TO_POINTER(token
));
2571 is_field_on_inst (MonoClassField
*field
)
2573 return (field
->parent
->generic_class
&& field
->parent
->generic_class
->is_dynamic
&& ((MonoDynamicGenericClass
*)field
->parent
->generic_class
)->fields
);
2577 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2580 get_field_on_inst_generic_type (MonoClassField
*field
)
2582 MonoDynamicGenericClass
*dgclass
;
2585 g_assert (is_field_on_inst (field
));
2587 dgclass
= (MonoDynamicGenericClass
*)field
->parent
->generic_class
;
2588 field_index
= field
- dgclass
->fields
;
2590 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
2591 return dgclass
->field_generic_types
[field_index
];
2595 mono_image_get_fieldref_token (MonoDynamicImage
*assembly
, MonoReflectionField
*f
)
2599 MonoClassField
*field
;
2601 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, f
));
2604 g_assert (f
->field
->parent
);
2607 if (field
->parent
->generic_class
&& field
->parent
->generic_class
->container_class
&& field
->parent
->generic_class
->container_class
->fields
) {
2608 int index
= field
- field
->parent
->fields
;
2609 type
= field
->parent
->generic_class
->container_class
->fields
[index
].type
;
2611 if (is_field_on_inst (f
->field
))
2612 type
= get_field_on_inst_generic_type (f
->field
);
2614 type
= f
->field
->type
;
2616 token
= mono_image_get_memberref_token (assembly
, &f
->field
->parent
->byval_arg
,
2617 mono_field_get_name (f
->field
),
2618 fieldref_encode_signature (assembly
, type
));
2619 g_hash_table_insert (assembly
->handleref
, f
, GUINT_TO_POINTER(token
));
2624 mono_image_get_field_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionFieldOnTypeBuilderInst
*f
)
2628 MonoGenericClass
*gclass
;
2629 MonoDynamicGenericClass
*dgclass
;
2630 MonoReflectionFieldBuilder
*fb
= f
->fb
;
2633 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, f
));
2636 klass
= mono_class_from_mono_type (f
->inst
->type
.type
);
2637 gclass
= f
->inst
->type
.type
->data
.generic_class
;
2638 g_assert (gclass
->is_dynamic
);
2639 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2641 name
= mono_string_to_utf8 (fb
->name
);
2642 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
,
2643 field_encode_signature (assembly
, fb
));
2645 g_hash_table_insert (assembly
->handleref
, f
, GUINT_TO_POINTER (token
));
2650 mono_image_get_ctor_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionCtorOnTypeBuilderInst
*c
, gboolean create_methodspec
)
2654 MonoGenericClass
*gclass
;
2655 MonoDynamicGenericClass
*dgclass
;
2656 MonoReflectionCtorBuilder
*cb
= c
->cb
;
2657 ReflectionMethodBuilder rmb
;
2660 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2662 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, c
));
2665 klass
= mono_class_from_mono_type (c
->inst
->type
.type
);
2666 gclass
= c
->inst
->type
.type
->data
.generic_class
;
2667 g_assert (gclass
->is_dynamic
);
2668 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2670 reflection_methodbuilder_from_ctor_builder (&rmb
, cb
);
2672 name
= mono_string_to_utf8 (rmb
.name
);
2674 sig
= method_builder_encode_signature (assembly
, &rmb
);
2676 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2679 g_hash_table_insert (assembly
->handleref
, c
, GUINT_TO_POINTER (token
));
2684 mono_image_get_method_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionMethodOnTypeBuilderInst
*m
, gboolean create_methodspec
)
2688 MonoGenericClass
*gclass
;
2689 MonoReflectionMethodBuilder
*mb
= m
->mb
;
2690 ReflectionMethodBuilder rmb
;
2693 if (create_methodspec
&& mb
->generic_params
)
2695 g_assert_not_reached ();
2697 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, m
));
2700 klass
= mono_class_from_mono_type (m
->inst
->type
.type
);
2701 gclass
= m
->inst
->type
.type
->data
.generic_class
;
2702 g_assert (gclass
->is_dynamic
);
2704 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
2706 name
= mono_string_to_utf8 (rmb
.name
);
2708 sig
= method_builder_encode_signature (assembly
, &rmb
);
2710 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2713 g_hash_table_insert (assembly
->handleref
, m
, GUINT_TO_POINTER (token
));
2718 encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
)
2722 guint32 nparams
= context
->method_inst
->type_argc
;
2725 if (!assembly
->save
)
2728 sigbuffer_init (&buf
, 32);
2730 * FIXME: vararg, explicit_this, differenc call_conv values...
2732 sigbuffer_add_value (&buf
, 0xa); /* FIXME FIXME FIXME */
2733 sigbuffer_add_value (&buf
, nparams
);
2735 for (i
= 0; i
< nparams
; i
++)
2736 encode_type (assembly
, context
->method_inst
->type_argv
[i
], &buf
);
2738 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2739 sigbuffer_free (&buf
);
2744 method_encode_methodspec (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2746 MonoDynamicTable
*table
;
2748 guint32 token
, mtoken
= 0, sig
;
2749 MonoMethodInflated
*imethod
;
2750 MonoMethod
*declaring
;
2752 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2754 g_assert (method
->is_inflated
);
2755 imethod
= (MonoMethodInflated
*) method
;
2756 declaring
= imethod
->declaring
;
2758 sig
= method_encode_signature (assembly
, mono_method_signature (declaring
));
2759 mtoken
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
, declaring
->name
, sig
);
2761 if (!mono_method_signature (declaring
)->generic_param_count
)
2764 switch (mono_metadata_token_table (mtoken
)) {
2765 case MONO_TABLE_MEMBERREF
:
2766 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2768 case MONO_TABLE_METHOD
:
2769 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2772 g_assert_not_reached ();
2775 sig
= encode_generic_method_sig (assembly
, mono_method_get_context (method
));
2777 if (assembly
->save
) {
2778 alloc_table (table
, table
->rows
+ 1);
2779 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2780 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2781 values
[MONO_METHODSPEC_SIGNATURE
] = sig
;
2784 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2791 mono_image_get_methodspec_token (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2793 MonoMethodInflated
*imethod
;
2796 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2800 g_assert (method
->is_inflated
);
2801 imethod
= (MonoMethodInflated
*) method
;
2803 if (mono_method_signature (imethod
->declaring
)->generic_param_count
) {
2804 token
= method_encode_methodspec (assembly
, method
);
2806 guint32 sig
= method_encode_signature (
2807 assembly
, mono_method_signature (imethod
->declaring
));
2808 token
= mono_image_get_memberref_token (
2809 assembly
, &method
->klass
->byval_arg
, method
->name
, sig
);
2812 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2817 mono_image_get_inflated_method_token (MonoDynamicImage
*assembly
, MonoMethod
*m
)
2819 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) m
;
2822 sig
= method_encode_signature (assembly
, mono_method_signature (imethod
->declaring
));
2823 token
= mono_image_get_memberref_token (
2824 assembly
, &m
->klass
->byval_arg
, m
->name
, sig
);
2830 create_generic_typespec (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
)
2832 MonoDynamicTable
*table
;
2840 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2841 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2842 * Because of this, we must not insert it into the `typeref' hash table.
2845 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, tb
->type
.type
));
2849 sigbuffer_init (&buf
, 32);
2851 g_assert (tb
->generic_params
);
2852 klass
= mono_class_from_mono_type (tb
->type
.type
);
2854 if (tb
->generic_container
)
2855 mono_reflection_create_generic_class (tb
);
2857 sigbuffer_add_value (&buf
, MONO_TYPE_GENERICINST
);
2858 g_assert (klass
->generic_container
);
2859 sigbuffer_add_value (&buf
, klass
->byval_arg
.type
);
2860 sigbuffer_add_value (&buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
2862 count
= mono_array_length (tb
->generic_params
);
2863 sigbuffer_add_value (&buf
, count
);
2864 for (i
= 0; i
< count
; i
++) {
2865 MonoReflectionGenericParam
*gparam
;
2867 gparam
= mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
);
2869 encode_type (assembly
, gparam
->type
.type
, &buf
);
2872 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2874 if (assembly
->save
) {
2875 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2876 alloc_table (table
, table
->rows
+ 1);
2877 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2878 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2880 sigbuffer_free (&buf
);
2882 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2883 g_hash_table_insert (assembly
->typespec
, tb
->type
.type
, GUINT_TO_POINTER(token
));
2889 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2892 add_custom_modifiers (MonoDynamicImage
*assembly
, MonoType
*type
, MonoArray
*modreq
, MonoArray
*modopt
)
2894 int i
, count
, len
, pos
;
2899 count
+= mono_array_length (modreq
);
2901 count
+= mono_array_length (modopt
);
2904 return mono_metadata_type_dup (NULL
, type
);
2906 len
= sizeof (MonoType
) + ((gint32
)count
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoCustomMod
);
2908 memcpy (t
, type
, len
);
2910 t
->num_mods
= count
;
2913 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
2914 MonoReflectionType
*mod
= mono_array_get (modreq
, MonoReflectionType
*, i
);
2915 t
->modifiers
[pos
].required
= 1;
2916 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
->type
);
2921 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
2922 MonoReflectionType
*mod
= mono_array_get (modopt
, MonoReflectionType
*, i
);
2923 t
->modifiers
[pos
].required
= 0;
2924 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
->type
);
2933 mono_image_get_generic_field_token (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
2935 MonoDynamicTable
*table
;
2937 MonoType
*custom
= NULL
;
2939 guint32 token
, pclass
, parent
, sig
;
2942 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, fb
));
2946 klass
= mono_class_from_mono_type (fb
->typeb
->type
);
2947 name
= mono_string_to_utf8 (fb
->name
);
2949 /* fb->type does not include the custom modifiers */
2950 /* FIXME: We should do this in one place when a fieldbuilder is created */
2951 if (fb
->modreq
|| fb
->modopt
) {
2952 custom
= add_custom_modifiers (assembly
, fb
->type
->type
, fb
->modreq
, fb
->modopt
);
2953 sig
= fieldref_encode_signature (assembly
, custom
);
2956 sig
= fieldref_encode_signature (assembly
, fb
->type
->type
);
2959 parent
= create_generic_typespec (assembly
, (MonoReflectionTypeBuilder
*) fb
->typeb
);
2960 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_TYPEDEFORREF_TYPESPEC
);
2962 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2963 parent
>>= MONO_TYPEDEFORREF_BITS
;
2965 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2967 if (assembly
->save
) {
2968 alloc_table (table
, table
->rows
+ 1);
2969 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2970 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2971 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2972 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2975 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2977 g_hash_table_insert (assembly
->handleref
, fb
, GUINT_TO_POINTER(token
));
2983 mono_reflection_encode_sighelper (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
2990 if (!assembly
->save
)
2993 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2994 g_assert (helper
->type
== 2);
2996 if (helper
->arguments
)
2997 nargs
= mono_array_length (helper
->arguments
);
3001 size
= 10 + (nargs
* 10);
3003 sigbuffer_init (&buf
, 32);
3005 /* Encode calling convention */
3006 /* Change Any to Standard */
3007 if ((helper
->call_conv
& 0x03) == 0x03)
3008 helper
->call_conv
= 0x01;
3009 /* explicit_this implies has_this */
3010 if (helper
->call_conv
& 0x40)
3011 helper
->call_conv
&= 0x20;
3013 if (helper
->call_conv
== 0) { /* Unmanaged */
3014 idx
= helper
->unmanaged_call_conv
- 1;
3017 idx
= helper
->call_conv
& 0x60; /* has_this + explicit_this */
3018 if (helper
->call_conv
& 0x02) /* varargs */
3022 sigbuffer_add_byte (&buf
, idx
);
3023 sigbuffer_add_value (&buf
, nargs
);
3024 encode_reflection_type (assembly
, helper
->return_type
, &buf
);
3025 for (i
= 0; i
< nargs
; ++i
) {
3026 MonoArray
*modreqs
= NULL
;
3027 MonoArray
*modopts
= NULL
;
3028 MonoReflectionType
*pt
;
3030 if (helper
->modreqs
&& (i
< mono_array_length (helper
->modreqs
)))
3031 modreqs
= mono_array_get (helper
->modreqs
, MonoArray
*, i
);
3032 if (helper
->modopts
&& (i
< mono_array_length (helper
->modopts
)))
3033 modopts
= mono_array_get (helper
->modopts
, MonoArray
*, i
);
3035 encode_custom_modifiers (assembly
, modreqs
, modopts
, &buf
);
3036 pt
= mono_array_get (helper
->arguments
, MonoReflectionType
*, i
);
3037 encode_reflection_type (assembly
, pt
, &buf
);
3039 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3040 sigbuffer_free (&buf
);
3046 mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
3049 MonoDynamicTable
*table
;
3052 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
3053 idx
= table
->next_idx
++;
3055 alloc_table (table
, table
->rows
);
3056 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
3058 values
[MONO_STAND_ALONE_SIGNATURE
] =
3059 mono_reflection_encode_sighelper (assembly
, helper
);
3065 reflection_cc_to_file (int call_conv
) {
3066 switch (call_conv
& 0x3) {
3068 case 1: return MONO_CALL_DEFAULT
;
3069 case 2: return MONO_CALL_VARARG
;
3071 g_assert_not_reached ();
3078 MonoMethodSignature
*sig
;
3084 mono_image_get_array_token (MonoDynamicImage
*assembly
, MonoReflectionArrayMethod
*m
)
3089 MonoMethodSignature
*sig
;
3092 name
= mono_string_to_utf8 (m
->name
);
3093 nparams
= mono_array_length (m
->parameters
);
3094 sig
= g_malloc0 (sizeof (MonoMethodSignature
) + sizeof (MonoType
*) * nparams
);
3096 sig
->sentinelpos
= -1;
3097 sig
->call_convention
= reflection_cc_to_file (m
->call_conv
);
3098 sig
->param_count
= nparams
;
3099 sig
->ret
= m
->ret
? m
->ret
->type
: &mono_defaults
.void_class
->byval_arg
;
3100 for (i
= 0; i
< nparams
; ++i
) {
3101 MonoReflectionType
*t
= mono_array_get (m
->parameters
, gpointer
, i
);
3102 sig
->params
[i
] = t
->type
;
3105 for (tmp
= assembly
->array_methods
; tmp
; tmp
= tmp
->next
) {
3107 if (strcmp (name
, am
->name
) == 0 &&
3108 mono_metadata_type_equal (am
->parent
, m
->parent
->type
) &&
3109 mono_metadata_signature_equal (am
->sig
, sig
)) {
3112 m
->table_idx
= am
->token
& 0xffffff;
3116 am
= g_new0 (ArrayMethod
, 1);
3119 am
->parent
= m
->parent
->type
;
3120 am
->token
= mono_image_get_memberref_token (assembly
, am
->parent
, name
,
3121 method_encode_signature (assembly
, sig
));
3122 assembly
->array_methods
= g_list_prepend (assembly
->array_methods
, am
);
3123 m
->table_idx
= am
->token
& 0xffffff;
3128 * Insert into the metadata tables all the info about the TypeBuilder tb.
3129 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3132 mono_image_get_type_info (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
, MonoDynamicImage
*assembly
)
3134 MonoDynamicTable
*table
;
3136 int i
, is_object
= 0, is_system
= 0;
3139 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
3140 values
= table
->values
+ tb
->table_idx
* MONO_TYPEDEF_SIZE
;
3141 values
[MONO_TYPEDEF_FLAGS
] = tb
->attrs
;
3142 n
= mono_string_to_utf8 (tb
->name
);
3143 if (strcmp (n
, "Object") == 0)
3145 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, n
);
3147 n
= mono_string_to_utf8 (tb
->nspace
);
3148 if (strcmp (n
, "System") == 0)
3150 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, n
);
3152 if (tb
->parent
&& !(is_system
&& is_object
) &&
3153 !(tb
->attrs
& TYPE_ATTRIBUTE_INTERFACE
)) { /* interfaces don't have a parent */
3154 values
[MONO_TYPEDEF_EXTENDS
] = mono_image_typedef_or_ref (assembly
, tb
->parent
->type
);
3156 values
[MONO_TYPEDEF_EXTENDS
] = 0;
3158 values
[MONO_TYPEDEF_FIELD_LIST
] = assembly
->tables
[MONO_TABLE_FIELD
].next_idx
;
3159 values
[MONO_TYPEDEF_METHOD_LIST
] = assembly
->tables
[MONO_TABLE_METHOD
].next_idx
;
3162 * if we have explicitlayout or sequentiallayouts, output data in the
3163 * ClassLayout table.
3165 if (((tb
->attrs
& TYPE_ATTRIBUTE_LAYOUT_MASK
) != TYPE_ATTRIBUTE_AUTO_LAYOUT
) &&
3166 ((tb
->class_size
> 0) || (tb
->packing_size
> 0))) {
3167 table
= &assembly
->tables
[MONO_TABLE_CLASSLAYOUT
];
3169 alloc_table (table
, table
->rows
);
3170 values
= table
->values
+ table
->rows
* MONO_CLASS_LAYOUT_SIZE
;
3171 values
[MONO_CLASS_LAYOUT_PARENT
] = tb
->table_idx
;
3172 values
[MONO_CLASS_LAYOUT_CLASS_SIZE
] = tb
->class_size
;
3173 values
[MONO_CLASS_LAYOUT_PACKING_SIZE
] = tb
->packing_size
;
3176 /* handle interfaces */
3177 if (tb
->interfaces
) {
3178 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3180 table
->rows
+= mono_array_length (tb
->interfaces
);
3181 alloc_table (table
, table
->rows
);
3182 values
= table
->values
+ (i
+ 1) * MONO_INTERFACEIMPL_SIZE
;
3183 for (i
= 0; i
< mono_array_length (tb
->interfaces
); ++i
) {
3184 MonoReflectionType
* iface
= (MonoReflectionType
*) mono_array_get (tb
->interfaces
, gpointer
, i
);
3185 values
[MONO_INTERFACEIMPL_CLASS
] = tb
->table_idx
;
3186 values
[MONO_INTERFACEIMPL_INTERFACE
] = mono_image_typedef_or_ref (assembly
, iface
->type
);
3187 values
+= MONO_INTERFACEIMPL_SIZE
;
3193 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
3194 table
->rows
+= tb
->num_fields
;
3195 alloc_table (table
, table
->rows
);
3196 for (i
= 0; i
< tb
->num_fields
; ++i
)
3197 mono_image_get_field_info (
3198 mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
3201 /* handle constructors */
3203 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3204 table
->rows
+= mono_array_length (tb
->ctors
);
3205 alloc_table (table
, table
->rows
);
3206 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
)
3207 mono_image_get_ctor_info (domain
,
3208 mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
), assembly
);
3211 /* handle methods */
3213 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3214 table
->rows
+= tb
->num_methods
;
3215 alloc_table (table
, table
->rows
);
3216 for (i
= 0; i
< tb
->num_methods
; ++i
)
3217 mono_image_get_method_info (
3218 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
3221 /* Do the same with properties etc.. */
3222 if (tb
->events
&& mono_array_length (tb
->events
)) {
3223 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
3224 table
->rows
+= mono_array_length (tb
->events
);
3225 alloc_table (table
, table
->rows
);
3226 table
= &assembly
->tables
[MONO_TABLE_EVENTMAP
];
3228 alloc_table (table
, table
->rows
);
3229 values
= table
->values
+ table
->rows
* MONO_EVENT_MAP_SIZE
;
3230 values
[MONO_EVENT_MAP_PARENT
] = tb
->table_idx
;
3231 values
[MONO_EVENT_MAP_EVENTLIST
] = assembly
->tables
[MONO_TABLE_EVENT
].next_idx
;
3232 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
)
3233 mono_image_get_event_info (
3234 mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
), assembly
);
3236 if (tb
->properties
&& mono_array_length (tb
->properties
)) {
3237 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
3238 table
->rows
+= mono_array_length (tb
->properties
);
3239 alloc_table (table
, table
->rows
);
3240 table
= &assembly
->tables
[MONO_TABLE_PROPERTYMAP
];
3242 alloc_table (table
, table
->rows
);
3243 values
= table
->values
+ table
->rows
* MONO_PROPERTY_MAP_SIZE
;
3244 values
[MONO_PROPERTY_MAP_PARENT
] = tb
->table_idx
;
3245 values
[MONO_PROPERTY_MAP_PROPERTY_LIST
] = assembly
->tables
[MONO_TABLE_PROPERTY
].next_idx
;
3246 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
)
3247 mono_image_get_property_info (
3248 mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
), assembly
);
3251 /* handle generic parameters */
3252 if (tb
->generic_params
) {
3253 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
3254 table
->rows
+= mono_array_length (tb
->generic_params
);
3255 alloc_table (table
, table
->rows
);
3256 for (i
= 0; i
< mono_array_length (tb
->generic_params
); ++i
) {
3257 guint32 owner
= MONO_TYPEORMETHOD_TYPE
| (tb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
3259 mono_image_get_generic_param_info (
3260 mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
), owner
, assembly
);
3264 mono_image_add_decl_security (assembly
,
3265 mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
), tb
->permissions
);
3268 MonoDynamicTable
*ntable
;
3270 ntable
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3271 ntable
->rows
+= mono_array_length (tb
->subtypes
);
3272 alloc_table (ntable
, ntable
->rows
);
3273 values
= ntable
->values
+ ntable
->next_idx
* MONO_NESTED_CLASS_SIZE
;
3275 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
3276 MonoReflectionTypeBuilder
*subtype
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3278 values
[MONO_NESTED_CLASS_NESTED
] = subtype
->table_idx
;
3279 values
[MONO_NESTED_CLASS_ENCLOSING
] = tb
->table_idx
;
3280 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3281 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3282 mono_string_to_utf8 (tb->name), tb->table_idx,
3283 ntable->next_idx, ntable->rows);*/
3284 values
+= MONO_NESTED_CLASS_SIZE
;
3291 collect_types (GPtrArray
*types
, MonoReflectionTypeBuilder
*type
)
3295 g_ptr_array_add (types
, type
); /* FIXME: GC object added to unmanaged memory */
3297 if (!type
->subtypes
)
3300 for (i
= 0; i
< mono_array_length (type
->subtypes
); ++i
) {
3301 MonoReflectionTypeBuilder
*subtype
= mono_array_get (type
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3302 collect_types (types
, subtype
);
3307 compare_types_by_table_idx (MonoReflectionTypeBuilder
**type1
, MonoReflectionTypeBuilder
**type2
)
3309 if ((*type1
)->table_idx
< (*type2
)->table_idx
)
3312 if ((*type1
)->table_idx
> (*type2
)->table_idx
)
3319 params_add_cattrs (MonoDynamicImage
*assembly
, MonoArray
*pinfo
) {
3324 for (i
= 0; i
< mono_array_length (pinfo
); ++i
) {
3325 MonoReflectionParamBuilder
*pb
;
3326 pb
= mono_array_get (pinfo
, MonoReflectionParamBuilder
*, i
);
3329 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PARAMDEF
, pb
->cattrs
);
3334 type_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
) {
3337 mono_image_add_cattrs (assembly
, tb
->table_idx
, MONO_CUSTOM_ATTR_TYPEDEF
, tb
->cattrs
);
3339 for (i
= 0; i
< tb
->num_fields
; ++i
) {
3340 MonoReflectionFieldBuilder
* fb
;
3341 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
);
3342 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3346 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
) {
3347 MonoReflectionEventBuilder
* eb
;
3348 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
3349 mono_image_add_cattrs (assembly
, eb
->table_idx
, MONO_CUSTOM_ATTR_EVENT
, eb
->cattrs
);
3352 if (tb
->properties
) {
3353 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
) {
3354 MonoReflectionPropertyBuilder
* pb
;
3355 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
3356 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PROPERTY
, pb
->cattrs
);
3360 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
3361 MonoReflectionCtorBuilder
* cb
;
3362 cb
= mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
);
3363 mono_image_add_cattrs (assembly
, cb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, cb
->cattrs
);
3364 params_add_cattrs (assembly
, cb
->pinfo
);
3369 for (i
= 0; i
< tb
->num_methods
; ++i
) {
3370 MonoReflectionMethodBuilder
* mb
;
3371 mb
= mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
3372 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3373 params_add_cattrs (assembly
, mb
->pinfo
);
3378 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3379 type_add_cattrs (assembly
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
));
3384 module_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionModuleBuilder
*moduleb
)
3388 mono_image_add_cattrs (assembly
, moduleb
->table_idx
, MONO_CUSTOM_ATTR_MODULE
, moduleb
->cattrs
);
3390 if (moduleb
->global_methods
) {
3391 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
3392 MonoReflectionMethodBuilder
* mb
= mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
3393 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3394 params_add_cattrs (assembly
, mb
->pinfo
);
3398 if (moduleb
->global_fields
) {
3399 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
) {
3400 MonoReflectionFieldBuilder
*fb
= mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
);
3401 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3405 if (moduleb
->types
) {
3406 for (i
= 0; i
< moduleb
->num_types
; ++i
)
3407 type_add_cattrs (assembly
, mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
));
3412 mono_image_fill_file_table (MonoDomain
*domain
, MonoReflectionModule
*module
, MonoDynamicImage
*assembly
)
3414 MonoDynamicTable
*table
;
3418 char *b
= blob_size
;
3421 table
= &assembly
->tables
[MONO_TABLE_FILE
];
3423 alloc_table (table
, table
->rows
);
3424 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
3425 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_METADATA
;
3426 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, module
->image
->module_name
);
3427 if (module
->image
->dynamic
) {
3428 /* This depends on the fact that the main module is emitted last */
3429 dir
= mono_string_to_utf8 (((MonoReflectionModuleBuilder
*)module
)->assemblyb
->dir
);
3430 path
= g_strdup_printf ("%s%c%s", dir
, G_DIR_SEPARATOR
, module
->image
->module_name
);
3433 path
= g_strdup (module
->image
->name
);
3435 mono_sha1_get_digest_from_file (path
, hash
);
3438 mono_metadata_encode_value (20, b
, &b
);
3439 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
3440 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
3445 mono_image_fill_module_table (MonoDomain
*domain
, MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
)
3447 MonoDynamicTable
*table
;
3450 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
3451 mb
->table_idx
= table
->next_idx
++;
3452 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->module
.name
);
3453 i
= mono_image_add_stream_data (&assembly
->guid
, mono_array_addr (mb
->guid
, char, 0), 16);
3456 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_GENERATION
] = 0;
3457 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_MVID
] = i
;
3458 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENC
] = 0;
3459 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENCBASE
] = 0;
3463 mono_image_fill_export_table_from_class (MonoDomain
*domain
, MonoClass
*klass
,
3464 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3466 MonoDynamicTable
*table
;
3470 visib
= klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
3471 if (! ((visib
& TYPE_ATTRIBUTE_PUBLIC
) || (visib
& TYPE_ATTRIBUTE_NESTED_PUBLIC
)))
3474 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3476 alloc_table (table
, table
->rows
);
3477 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3479 values
[MONO_EXP_TYPE_FLAGS
] = klass
->flags
;
3480 values
[MONO_EXP_TYPE_TYPEDEF
] = klass
->type_token
;
3481 if (klass
->nested_in
)
3482 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (parent_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
3484 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (module_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_FILE
;
3485 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3486 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3488 res
= table
->next_idx
;
3492 /* Emit nested types */
3493 if (klass
->nested_classes
) {
3496 for (tmp
= klass
->nested_classes
; tmp
; tmp
= tmp
->next
)
3497 mono_image_fill_export_table_from_class (domain
, tmp
->data
, module_index
, table
->next_idx
- 1, assembly
);
3504 mono_image_fill_export_table (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
,
3505 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3510 klass
= mono_class_from_mono_type (tb
->type
.type
);
3512 klass
->type_token
= mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
);
3514 idx
= mono_image_fill_export_table_from_class (domain
, klass
, module_index
,
3515 parent_index
, assembly
);
3519 * We need to do this ourselves since klass->nested_classes is not set up.
3522 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3523 mono_image_fill_export_table (domain
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
), module_index
, idx
, assembly
);
3528 mono_image_fill_export_table_from_module (MonoDomain
*domain
, MonoReflectionModule
*module
,
3529 guint32 module_index
, MonoDynamicImage
*assembly
)
3531 MonoImage
*image
= module
->image
;
3535 t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
3537 for (i
= 0; i
< t
->rows
; ++i
) {
3538 MonoClass
*klass
= mono_class_get (image
, mono_metadata_make_token (MONO_TABLE_TYPEDEF
, i
+ 1));
3540 if (klass
->flags
& TYPE_ATTRIBUTE_PUBLIC
)
3541 mono_image_fill_export_table_from_class (domain
, klass
, module_index
, 0, assembly
);
3546 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
)
3548 MonoDynamicTable
*table
;
3554 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3556 if (assemblyb
->type_forwarders
) {
3557 for (i
= 0; i
< mono_array_length (assemblyb
->type_forwarders
); ++i
) {
3558 MonoReflectionType
*t
= mono_array_get (assemblyb
->type_forwarders
, MonoReflectionType
*, i
);
3564 klass
= mono_class_from_mono_type (t
->type
);
3566 scope
= resolution_scope_from_image (assembly
, klass
->image
);
3567 g_assert ((scope
& MONO_RESOLTION_SCOPE_MASK
) == MONO_RESOLTION_SCOPE_ASSEMBLYREF
);
3568 idx
= scope
>> MONO_RESOLTION_SCOPE_BITS
;
3571 alloc_table (table
, table
->rows
);
3572 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3574 values
[MONO_EXP_TYPE_FLAGS
] = TYPE_ATTRIBUTE_FORWARDER
;
3575 values
[MONO_EXP_TYPE_TYPEDEF
] = 0;
3576 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (idx
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_ASSEMBLYREF
;
3577 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3578 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3585 #define align_pointer(base,p)\
3587 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3589 (p) += 4 - (__diff & 3);\
3593 compare_constants (const void *a
, const void *b
)
3595 const guint32
*a_values
= a
;
3596 const guint32
*b_values
= b
;
3597 return a_values
[MONO_CONSTANT_PARENT
] - b_values
[MONO_CONSTANT_PARENT
];
3601 compare_semantics (const void *a
, const void *b
)
3603 const guint32
*a_values
= a
;
3604 const guint32
*b_values
= b
;
3605 int assoc
= a_values
[MONO_METHOD_SEMA_ASSOCIATION
] - b_values
[MONO_METHOD_SEMA_ASSOCIATION
];
3608 return a_values
[MONO_METHOD_SEMA_SEMANTICS
] - b_values
[MONO_METHOD_SEMA_SEMANTICS
];
3612 compare_custom_attrs (const void *a
, const void *b
)
3614 const guint32
*a_values
= a
;
3615 const guint32
*b_values
= b
;
3617 return a_values
[MONO_CUSTOM_ATTR_PARENT
] - b_values
[MONO_CUSTOM_ATTR_PARENT
];
3621 compare_field_marshal (const void *a
, const void *b
)
3623 const guint32
*a_values
= a
;
3624 const guint32
*b_values
= b
;
3626 return a_values
[MONO_FIELD_MARSHAL_PARENT
] - b_values
[MONO_FIELD_MARSHAL_PARENT
];
3630 compare_nested (const void *a
, const void *b
)
3632 const guint32
*a_values
= a
;
3633 const guint32
*b_values
= b
;
3635 return a_values
[MONO_NESTED_CLASS_NESTED
] - b_values
[MONO_NESTED_CLASS_NESTED
];
3639 compare_genericparam (const void *a
, const void *b
)
3641 const GenericParamTableEntry
**a_entry
= (const GenericParamTableEntry
**) a
;
3642 const GenericParamTableEntry
**b_entry
= (const GenericParamTableEntry
**) b
;
3644 if ((*b_entry
)->owner
== (*a_entry
)->owner
)
3646 (*a_entry
)->gparam
->type
.type
->data
.generic_param
->num
-
3647 (*b_entry
)->gparam
->type
.type
->data
.generic_param
->num
;
3649 return (*a_entry
)->owner
- (*b_entry
)->owner
;
3653 compare_declsecurity_attrs (const void *a
, const void *b
)
3655 const guint32
*a_values
= a
;
3656 const guint32
*b_values
= b
;
3658 return a_values
[MONO_DECL_SECURITY_PARENT
] - b_values
[MONO_DECL_SECURITY_PARENT
];
3662 compare_interface_impl (const void *a
, const void *b
)
3664 const guint32
*a_values
= a
;
3665 const guint32
*b_values
= b
;
3667 int klass
= a_values
[MONO_INTERFACEIMPL_CLASS
] - b_values
[MONO_INTERFACEIMPL_CLASS
];
3671 return a_values
[MONO_INTERFACEIMPL_INTERFACE
] - b_values
[MONO_INTERFACEIMPL_INTERFACE
];
3675 pad_heap (MonoDynamicStream
*sh
)
3677 if (sh
->index
& 3) {
3678 int sz
= 4 - (sh
->index
& 3);
3679 memset (sh
->data
+ sh
->index
, 0, sz
);
3686 MonoDynamicStream
*stream
;
3690 * build_compressed_metadata() fills in the blob of data that represents the
3691 * raw metadata as it will be saved in the PE file. The five streams are output
3692 * and the metadata tables are comnpressed from the guint32 array representation,
3693 * to the compressed on-disk format.
3696 build_compressed_metadata (MonoDynamicImage
*assembly
)
3698 MonoDynamicTable
*table
;
3700 guint64 valid_mask
= 0;
3701 guint64 sorted_mask
;
3702 guint32 heapt_size
= 0;
3703 guint32 meta_size
= 256; /* allow for header and other stuff */
3704 guint32 table_offset
;
3705 guint32 ntables
= 0;
3711 struct StreamDesc stream_desc
[5];
3713 qsort (assembly
->gen_params
->pdata
, assembly
->gen_params
->len
, sizeof (gpointer
), compare_genericparam
);
3714 for (i
= 0; i
< assembly
->gen_params
->len
; i
++){
3715 GenericParamTableEntry
*entry
= g_ptr_array_index (assembly
->gen_params
, i
);
3716 write_generic_param_entry (assembly
, entry
);
3719 stream_desc
[0].name
= "#~";
3720 stream_desc
[0].stream
= &assembly
->tstream
;
3721 stream_desc
[1].name
= "#Strings";
3722 stream_desc
[1].stream
= &assembly
->sheap
;
3723 stream_desc
[2].name
= "#US";
3724 stream_desc
[2].stream
= &assembly
->us
;
3725 stream_desc
[3].name
= "#Blob";
3726 stream_desc
[3].stream
= &assembly
->blob
;
3727 stream_desc
[4].name
= "#GUID";
3728 stream_desc
[4].stream
= &assembly
->guid
;
3730 /* tables that are sorted */
3731 sorted_mask
= ((guint64
)1 << MONO_TABLE_CONSTANT
) | ((guint64
)1 << MONO_TABLE_FIELDMARSHAL
)
3732 | ((guint64
)1 << MONO_TABLE_METHODSEMANTICS
) | ((guint64
)1 << MONO_TABLE_CLASSLAYOUT
)
3733 | ((guint64
)1 << MONO_TABLE_FIELDLAYOUT
) | ((guint64
)1 << MONO_TABLE_FIELDRVA
)
3734 | ((guint64
)1 << MONO_TABLE_IMPLMAP
) | ((guint64
)1 << MONO_TABLE_NESTEDCLASS
)
3735 | ((guint64
)1 << MONO_TABLE_METHODIMPL
) | ((guint64
)1 << MONO_TABLE_CUSTOMATTRIBUTE
)
3736 | ((guint64
)1 << MONO_TABLE_DECLSECURITY
) | ((guint64
)1 << MONO_TABLE_GENERICPARAM
)
3737 | ((guint64
)1 << MONO_TABLE_INTERFACEIMPL
);
3739 /* Compute table sizes */
3740 /* the MonoImage has already been created in mono_image_basic_init() */
3741 meta
= &assembly
->image
;
3743 /* sizes should be multiple of 4 */
3744 pad_heap (&assembly
->blob
);
3745 pad_heap (&assembly
->guid
);
3746 pad_heap (&assembly
->sheap
);
3747 pad_heap (&assembly
->us
);
3749 /* Setup the info used by compute_sizes () */
3750 meta
->idx_blob_wide
= assembly
->blob
.index
>= 65536 ? 1 : 0;
3751 meta
->idx_guid_wide
= assembly
->guid
.index
>= 65536 ? 1 : 0;
3752 meta
->idx_string_wide
= assembly
->sheap
.index
>= 65536 ? 1 : 0;
3754 meta_size
+= assembly
->blob
.index
;
3755 meta_size
+= assembly
->guid
.index
;
3756 meta_size
+= assembly
->sheap
.index
;
3757 meta_size
+= assembly
->us
.index
;
3759 for (i
=0; i
< MONO_TABLE_NUM
; ++i
)
3760 meta
->tables
[i
].rows
= assembly
->tables
[i
].rows
;
3762 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3763 if (meta
->tables
[i
].rows
== 0)
3765 valid_mask
|= (guint64
)1 << i
;
3767 meta
->tables
[i
].row_size
= mono_metadata_compute_size (
3768 meta
, i
, &meta
->tables
[i
].size_bitfield
);
3769 heapt_size
+= meta
->tables
[i
].row_size
* meta
->tables
[i
].rows
;
3771 heapt_size
+= 24; /* #~ header size */
3772 heapt_size
+= ntables
* 4;
3773 /* make multiple of 4 */
3776 meta_size
+= heapt_size
;
3777 meta
->raw_metadata
= g_malloc0 (meta_size
);
3778 p
= (unsigned char*)meta
->raw_metadata
;
3779 /* the metadata signature */
3780 *p
++ = 'B'; *p
++ = 'S'; *p
++ = 'J'; *p
++ = 'B';
3781 /* version numbers and 4 bytes reserved */
3782 int16val
= (guint16
*)p
;
3783 *int16val
++ = GUINT16_TO_LE (meta
->md_version_major
);
3784 *int16val
= GUINT16_TO_LE (meta
->md_version_minor
);
3786 /* version string */
3787 int32val
= (guint32
*)p
;
3788 *int32val
= GUINT32_TO_LE ((strlen (meta
->version
) + 3) & (~3)); /* needs to be multiple of 4 */
3790 memcpy (p
, meta
->version
, strlen (meta
->version
));
3791 p
+= GUINT32_FROM_LE (*int32val
);
3792 align_pointer (meta
->raw_metadata
, p
);
3793 int16val
= (guint16
*)p
;
3794 *int16val
++ = GUINT16_TO_LE (0); /* flags must be 0 */
3795 *int16val
= GUINT16_TO_LE (5); /* number of streams */
3799 * write the stream info.
3801 table_offset
= (p
- (unsigned char*)meta
->raw_metadata
) + 5 * 8 + 40; /* room needed for stream headers */
3802 table_offset
+= 3; table_offset
&= ~3;
3804 assembly
->tstream
.index
= heapt_size
;
3805 for (i
= 0; i
< 5; ++i
) {
3806 int32val
= (guint32
*)p
;
3807 stream_desc
[i
].stream
->offset
= table_offset
;
3808 *int32val
++ = GUINT32_TO_LE (table_offset
);
3809 *int32val
= GUINT32_TO_LE (stream_desc
[i
].stream
->index
);
3810 table_offset
+= GUINT32_FROM_LE (*int32val
);
3811 table_offset
+= 3; table_offset
&= ~3;
3813 strcpy ((char*)p
, stream_desc
[i
].name
);
3814 p
+= strlen (stream_desc
[i
].name
) + 1;
3815 align_pointer (meta
->raw_metadata
, p
);
3818 * now copy the data, the table stream header and contents goes first.
3820 g_assert ((p
- (unsigned char*)meta
->raw_metadata
) < assembly
->tstream
.offset
);
3821 p
= (guchar
*)meta
->raw_metadata
+ assembly
->tstream
.offset
;
3822 int32val
= (guint32
*)p
;
3823 *int32val
= GUINT32_TO_LE (0); /* reserved */
3826 if (mono_framework_version () > 1) {
3827 *p
++ = 2; /* version */
3830 *p
++ = 1; /* version */
3834 if (meta
->idx_string_wide
)
3836 if (meta
->idx_guid_wide
)
3838 if (meta
->idx_blob_wide
)
3841 *p
++ = 1; /* reserved */
3842 int64val
= (guint64
*)p
;
3843 *int64val
++ = GUINT64_TO_LE (valid_mask
);
3844 *int64val
++ = GUINT64_TO_LE (valid_mask
& sorted_mask
); /* bitvector of sorted tables */
3846 int32val
= (guint32
*)p
;
3847 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3848 if (meta
->tables
[i
].rows
== 0)
3850 *int32val
++ = GUINT32_TO_LE (meta
->tables
[i
].rows
);
3852 p
= (unsigned char*)int32val
;
3854 /* sort the tables that still need sorting */
3855 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
3857 qsort (table
->values
+ MONO_CONSTANT_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CONSTANT_SIZE
, compare_constants
);
3858 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
3860 qsort (table
->values
+ MONO_METHOD_SEMA_SIZE
, table
->rows
, sizeof (guint32
) * MONO_METHOD_SEMA_SIZE
, compare_semantics
);
3861 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
3863 qsort (table
->values
+ MONO_CUSTOM_ATTR_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CUSTOM_ATTR_SIZE
, compare_custom_attrs
);
3864 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
3866 qsort (table
->values
+ MONO_FIELD_MARSHAL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_FIELD_MARSHAL_SIZE
, compare_field_marshal
);
3867 table
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3869 qsort (table
->values
+ MONO_NESTED_CLASS_SIZE
, table
->rows
, sizeof (guint32
) * MONO_NESTED_CLASS_SIZE
, compare_nested
);
3870 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3871 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
3873 qsort (table
->values
+ MONO_DECL_SECURITY_SIZE
, table
->rows
, sizeof (guint32
) * MONO_DECL_SECURITY_SIZE
, compare_declsecurity_attrs
);
3874 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3876 qsort (table
->values
+ MONO_INTERFACEIMPL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_INTERFACEIMPL_SIZE
, compare_interface_impl
);
3878 /* compress the tables */
3879 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3882 guint32 bitfield
= meta
->tables
[i
].size_bitfield
;
3883 if (!meta
->tables
[i
].rows
)
3885 if (assembly
->tables
[i
].columns
!= mono_metadata_table_count (bitfield
))
3886 g_error ("col count mismatch in %d: %d %d", i
, assembly
->tables
[i
].columns
, mono_metadata_table_count (bitfield
));
3887 meta
->tables
[i
].base
= (char*)p
;
3888 for (row
= 1; row
<= meta
->tables
[i
].rows
; ++row
) {
3889 values
= assembly
->tables
[i
].values
+ row
* assembly
->tables
[i
].columns
;
3890 for (col
= 0; col
< assembly
->tables
[i
].columns
; ++col
) {
3891 switch (mono_metadata_table_size (bitfield
, col
)) {
3893 *p
++ = values
[col
];
3896 *p
++ = values
[col
] & 0xff;
3897 *p
++ = (values
[col
] >> 8) & 0xff;
3900 *p
++ = values
[col
] & 0xff;
3901 *p
++ = (values
[col
] >> 8) & 0xff;
3902 *p
++ = (values
[col
] >> 16) & 0xff;
3903 *p
++ = (values
[col
] >> 24) & 0xff;
3906 g_assert_not_reached ();
3910 g_assert ((p
- (const unsigned char*)meta
->tables
[i
].base
) == (meta
->tables
[i
].rows
* meta
->tables
[i
].row_size
));
3913 g_assert (assembly
->guid
.offset
+ assembly
->guid
.index
< meta_size
);
3914 memcpy (meta
->raw_metadata
+ assembly
->sheap
.offset
, assembly
->sheap
.data
, assembly
->sheap
.index
);
3915 memcpy (meta
->raw_metadata
+ assembly
->us
.offset
, assembly
->us
.data
, assembly
->us
.index
);
3916 memcpy (meta
->raw_metadata
+ assembly
->blob
.offset
, assembly
->blob
.data
, assembly
->blob
.index
);
3917 memcpy (meta
->raw_metadata
+ assembly
->guid
.offset
, assembly
->guid
.data
, assembly
->guid
.index
);
3919 assembly
->meta_size
= assembly
->guid
.offset
+ assembly
->guid
.index
;
3923 * Some tables in metadata need to be sorted according to some criteria, but
3924 * when methods and fields are first created with reflection, they may be assigned a token
3925 * that doesn't correspond to the final token they will get assigned after the sorting.
3926 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3927 * with the reflection objects that represent them. Once all the tables are set up, the
3928 * reflection objects will contains the correct table index. fixup_method() will fixup the
3929 * tokens for the method with ILGenerator @ilgen.
3932 fixup_method (MonoReflectionILGen
*ilgen
, gpointer value
, MonoDynamicImage
*assembly
)
3934 guint32 code_idx
= GPOINTER_TO_UINT (value
);
3935 MonoReflectionILTokenInfo
*iltoken
;
3936 MonoReflectionFieldBuilder
*field
;
3937 MonoReflectionCtorBuilder
*ctor
;
3938 MonoReflectionMethodBuilder
*method
;
3939 MonoReflectionTypeBuilder
*tb
;
3940 MonoReflectionArrayMethod
*am
;
3942 unsigned char *target
;
3944 for (i
= 0; i
< ilgen
->num_token_fixups
; ++i
) {
3945 iltoken
= (MonoReflectionILTokenInfo
*)mono_array_addr_with_size (ilgen
->token_fixups
, sizeof (MonoReflectionILTokenInfo
), i
);
3946 target
= (guchar
*)assembly
->code
.data
+ code_idx
+ iltoken
->code_pos
;
3947 switch (target
[3]) {
3948 case MONO_TABLE_FIELD
:
3949 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
3950 field
= (MonoReflectionFieldBuilder
*)iltoken
->member
;
3951 idx
= field
->table_idx
;
3952 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
3953 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
3954 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->field_to_table_idx
, f
));
3956 g_assert_not_reached ();
3959 case MONO_TABLE_METHOD
:
3960 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
3961 method
= (MonoReflectionMethodBuilder
*)iltoken
->member
;
3962 idx
= method
->table_idx
;
3963 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
3964 ctor
= (MonoReflectionCtorBuilder
*)iltoken
->member
;
3965 idx
= ctor
->table_idx
;
3966 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
3967 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod")) {
3968 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
3969 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
3971 g_assert_not_reached ();
3974 case MONO_TABLE_TYPEDEF
:
3975 if (strcmp (iltoken
->member
->vtable
->klass
->name
, "TypeBuilder"))
3976 g_assert_not_reached ();
3977 tb
= (MonoReflectionTypeBuilder
*)iltoken
->member
;
3978 idx
= tb
->table_idx
;
3980 case MONO_TABLE_MEMBERREF
:
3981 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoArrayMethod")) {
3982 am
= (MonoReflectionArrayMethod
*)iltoken
->member
;
3983 idx
= am
->table_idx
;
3984 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
3985 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod") ||
3986 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod") ||
3987 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericCMethod")) {
3988 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
3989 g_assert (m
->klass
->generic_class
|| m
->klass
->generic_container
);
3991 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
3993 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
3994 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
3995 g_assert (is_field_on_inst (f
));
3997 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder") ||
3998 !strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
4000 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldOnTypeBuilderInst")) {
4002 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodOnTypeBuilderInst")) {
4004 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst")) {
4007 g_assert_not_reached ();
4010 case MONO_TABLE_METHODSPEC
:
4011 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod")) {
4012 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4013 g_assert (mono_method_signature (m
)->generic_param_count
);
4015 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
4018 g_assert_not_reached ();
4022 g_error ("got unexpected table 0x%02x in fixup", target
[3]);
4024 target
[0] = idx
& 0xff;
4025 target
[1] = (idx
>> 8) & 0xff;
4026 target
[2] = (idx
>> 16) & 0xff;
4033 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4034 * value is not known when the table is emitted.
4037 fixup_cattrs (MonoDynamicImage
*assembly
)
4039 MonoDynamicTable
*table
;
4041 guint32 type
, i
, idx
, token
;
4044 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4046 for (i
= 0; i
< table
->rows
; ++i
) {
4047 values
= table
->values
+ ((i
+ 1) * MONO_CUSTOM_ATTR_SIZE
);
4049 type
= values
[MONO_CUSTOM_ATTR_TYPE
];
4050 if ((type
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_METHODDEF
) {
4051 idx
= type
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
4052 token
= mono_metadata_make_token (MONO_TABLE_METHOD
, idx
);
4053 ctor
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4056 if (!strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
4057 MonoMethod
*m
= ((MonoReflectionMethod
*)ctor
)->method
;
4058 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4059 values
[MONO_CUSTOM_ATTR_TYPE
] = (idx
<< MONO_CUSTOM_ATTR_TYPE_BITS
) | MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
4066 assembly_add_resource_manifest (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
, guint32 implementation
)
4068 MonoDynamicTable
*table
;
4071 table
= &assembly
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4073 alloc_table (table
, table
->rows
);
4074 values
= table
->values
+ table
->next_idx
* MONO_MANIFEST_SIZE
;
4075 values
[MONO_MANIFEST_OFFSET
] = rsrc
->offset
;
4076 values
[MONO_MANIFEST_FLAGS
] = rsrc
->attrs
;
4077 values
[MONO_MANIFEST_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, rsrc
->name
);
4078 values
[MONO_MANIFEST_IMPLEMENTATION
] = implementation
;
4083 assembly_add_resource (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
)
4085 MonoDynamicTable
*table
;
4089 char *b
= blob_size
;
4091 guint32 idx
, offset
;
4093 if (rsrc
->filename
) {
4094 name
= mono_string_to_utf8 (rsrc
->filename
);
4095 sname
= g_path_get_basename (name
);
4097 table
= &assembly
->tables
[MONO_TABLE_FILE
];
4099 alloc_table (table
, table
->rows
);
4100 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
4101 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_NO_METADATA
;
4102 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, sname
);
4105 mono_sha1_get_digest_from_file (name
, hash
);
4106 mono_metadata_encode_value (20, b
, &b
);
4107 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
4108 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
4110 idx
= table
->next_idx
++;
4112 idx
= MONO_IMPLEMENTATION_FILE
| (idx
<< MONO_IMPLEMENTATION_BITS
);
4118 data
= mono_array_addr (rsrc
->data
, char, 0);
4119 len
= mono_array_length (rsrc
->data
);
4125 sizebuf
[0] = offset
; sizebuf
[1] = offset
>> 8;
4126 sizebuf
[2] = offset
>> 16; sizebuf
[3] = offset
>> 24;
4127 rsrc
->offset
= mono_image_add_stream_data (&assembly
->resources
, sizebuf
, 4);
4128 mono_image_add_stream_data (&assembly
->resources
, data
, len
);
4132 * The entry should be emitted into the MANIFESTRESOURCE table of
4133 * the main module, but that needs to reference the FILE table
4134 * which isn't emitted yet.
4141 assembly_add_resource_manifest (mb
, assembly
, rsrc
, idx
);
4145 set_version_from_string (MonoString
*version
, guint32
*values
)
4147 gchar
*ver
, *p
, *str
;
4150 values
[MONO_ASSEMBLY_MAJOR_VERSION
] = 0;
4151 values
[MONO_ASSEMBLY_MINOR_VERSION
] = 0;
4152 values
[MONO_ASSEMBLY_REV_NUMBER
] = 0;
4153 values
[MONO_ASSEMBLY_BUILD_NUMBER
] = 0;
4156 ver
= str
= mono_string_to_utf8 (version
);
4157 for (i
= 0; i
< 4; ++i
) {
4158 values
[MONO_ASSEMBLY_MAJOR_VERSION
+ i
] = strtol (ver
, &p
, 10);
4164 /* handle Revision and Build */
4174 load_public_key (MonoArray
*pkey
, MonoDynamicImage
*assembly
) {
4178 char *b
= blob_size
;
4183 len
= mono_array_length (pkey
);
4184 mono_metadata_encode_value (len
, b
, &b
);
4185 token
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
- blob_size
);
4186 mono_image_add_stream_data (&assembly
->blob
, mono_array_addr (pkey
, char, 0), len
);
4188 assembly
->public_key
= g_malloc (len
);
4189 memcpy (assembly
->public_key
, mono_array_addr (pkey
, char, 0), len
);
4190 assembly
->public_key_len
= len
;
4192 /* Special case: check for ECMA key (16 bytes) */
4193 if ((len
== MONO_ECMA_KEY_LENGTH
) && mono_is_ecma_key (mono_array_addr (pkey
, char, 0), len
)) {
4194 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4195 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
;
4196 } else if (len
>= MONO_PUBLIC_KEY_HEADER_LENGTH
+ MONO_MINIMUM_PUBLIC_KEY_LENGTH
) {
4197 /* minimum key size (in 2.0) is 384 bits */
4198 assembly
->strong_name_size
= len
- MONO_PUBLIC_KEY_HEADER_LENGTH
;
4200 /* FIXME - verifier */
4201 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len
), (int)len
);
4202 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
; /* to be safe */
4204 assembly
->strong_name
= g_malloc0 (assembly
->strong_name_size
);
4210 mono_image_emit_manifest (MonoReflectionModuleBuilder
*moduleb
)
4212 MonoDynamicTable
*table
;
4213 MonoDynamicImage
*assembly
;
4214 MonoReflectionAssemblyBuilder
*assemblyb
;
4218 guint32 module_index
;
4220 assemblyb
= moduleb
->assemblyb
;
4221 assembly
= moduleb
->dynamic_image
;
4222 domain
= mono_object_domain (assemblyb
);
4224 /* Emit ASSEMBLY table */
4225 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLY
];
4226 alloc_table (table
, 1);
4227 values
= table
->values
+ MONO_ASSEMBLY_SIZE
;
4228 values
[MONO_ASSEMBLY_HASH_ALG
] = assemblyb
->algid
? assemblyb
->algid
: ASSEMBLY_HASH_SHA1
;
4229 values
[MONO_ASSEMBLY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->name
);
4230 if (assemblyb
->culture
) {
4231 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->culture
);
4233 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert (&assembly
->sheap
, "");
4235 values
[MONO_ASSEMBLY_PUBLIC_KEY
] = load_public_key (assemblyb
->public_key
, assembly
);
4236 values
[MONO_ASSEMBLY_FLAGS
] = assemblyb
->flags
;
4237 set_version_from_string (assemblyb
->version
, values
);
4239 /* Emit FILE + EXPORTED_TYPE table */
4241 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4243 MonoReflectionModuleBuilder
*file_module
=
4244 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4245 if (file_module
!= moduleb
) {
4246 mono_image_fill_file_table (domain
, (MonoReflectionModule
*)file_module
, assembly
);
4248 if (file_module
->types
) {
4249 for (j
= 0; j
< file_module
->num_types
; ++j
) {
4250 MonoReflectionTypeBuilder
*tb
= mono_array_get (file_module
->types
, MonoReflectionTypeBuilder
*, j
);
4251 mono_image_fill_export_table (domain
, tb
, module_index
, 0, assembly
);
4256 if (assemblyb
->loaded_modules
) {
4257 for (i
= 0; i
< mono_array_length (assemblyb
->loaded_modules
); ++i
) {
4258 MonoReflectionModule
*file_module
=
4259 mono_array_get (assemblyb
->loaded_modules
, MonoReflectionModule
*, i
);
4260 mono_image_fill_file_table (domain
, file_module
, assembly
);
4262 mono_image_fill_export_table_from_module (domain
, file_module
, module_index
, assembly
);
4265 if (assemblyb
->type_forwarders
)
4266 mono_image_fill_export_table_from_type_forwarders (assemblyb
, assembly
);
4268 /* Emit MANIFESTRESOURCE table */
4270 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4272 MonoReflectionModuleBuilder
*file_module
=
4273 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4274 /* The table for the main module is emitted later */
4275 if (file_module
!= moduleb
) {
4277 if (file_module
->resources
) {
4278 int len
= mono_array_length (file_module
->resources
);
4279 for (j
= 0; j
< len
; ++j
) {
4280 MonoReflectionResource
* res
= (MonoReflectionResource
*)mono_array_addr (file_module
->resources
, MonoReflectionResource
, j
);
4281 assembly_add_resource_manifest (file_module
, assembly
, res
, MONO_IMPLEMENTATION_FILE
| (module_index
<< MONO_IMPLEMENTATION_BITS
));
4288 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4291 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4292 * for the modulebuilder @moduleb.
4293 * At the end of the process, method and field tokens are fixed up and the
4294 * on-disk compressed metadata representation is created.
4297 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4299 MonoDynamicTable
*table
;
4300 MonoDynamicImage
*assembly
;
4301 MonoReflectionAssemblyBuilder
*assemblyb
;
4307 assemblyb
= moduleb
->assemblyb
;
4308 assembly
= moduleb
->dynamic_image
;
4309 domain
= mono_object_domain (assemblyb
);
4311 if (assembly
->text_rva
)
4314 assembly
->text_rva
= START_TEXT_RVA
;
4316 if (moduleb
->is_main
) {
4317 mono_image_emit_manifest (moduleb
);
4320 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4321 table
->rows
= 1; /* .<Module> */
4323 alloc_table (table
, table
->rows
);
4325 * Set the first entry.
4327 values
= table
->values
+ table
->columns
;
4328 values
[MONO_TYPEDEF_FLAGS
] = 0;
4329 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, "<Module>") ;
4330 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, "") ;
4331 values
[MONO_TYPEDEF_EXTENDS
] = 0;
4332 values
[MONO_TYPEDEF_FIELD_LIST
] = 1;
4333 values
[MONO_TYPEDEF_METHOD_LIST
] = 1;
4336 * handle global methods
4337 * FIXME: test what to do when global methods are defined in multiple modules.
4339 if (moduleb
->global_methods
) {
4340 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
4341 table
->rows
+= mono_array_length (moduleb
->global_methods
);
4342 alloc_table (table
, table
->rows
);
4343 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
)
4344 mono_image_get_method_info (
4345 mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
4347 if (moduleb
->global_fields
) {
4348 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
4349 table
->rows
+= mono_array_length (moduleb
->global_fields
);
4350 alloc_table (table
, table
->rows
);
4351 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
)
4352 mono_image_get_field_info (
4353 mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
4356 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
4357 alloc_table (table
, 1);
4358 mono_image_fill_module_table (domain
, moduleb
, assembly
);
4360 /* Collect all types into a list sorted by their table_idx */
4361 types
= g_ptr_array_new ();
4364 for (i
= 0; i
< moduleb
->num_types
; ++i
) {
4365 MonoReflectionTypeBuilder
*type
= mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
);
4366 collect_types (types
, type
);
4369 g_ptr_array_sort (types
, (GCompareFunc
)compare_types_by_table_idx
);
4370 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4371 table
->rows
+= types
->len
;
4372 alloc_table (table
, table
->rows
);
4375 * Emit type names + namespaces at one place inside the string heap,
4376 * so load_class_names () needs to touch fewer pages.
4378 for (i
= 0; i
< types
->len
; ++i
) {
4379 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4380 string_heap_insert_mstring (&assembly
->sheap
, tb
->nspace
);
4382 for (i
= 0; i
< types
->len
; ++i
) {
4383 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4384 string_heap_insert_mstring (&assembly
->sheap
, tb
->name
);
4387 for (i
= 0; i
< types
->len
; ++i
) {
4388 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4389 mono_image_get_type_info (domain
, type
, assembly
);
4393 * table->rows is already set above and in mono_image_fill_module_table.
4395 /* add all the custom attributes at the end, once all the indexes are stable */
4396 mono_image_add_cattrs (assembly
, 1, MONO_CUSTOM_ATTR_ASSEMBLY
, assemblyb
->cattrs
);
4398 /* CAS assembly permissions */
4399 if (assemblyb
->permissions_minimum
)
4400 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_minimum
);
4401 if (assemblyb
->permissions_optional
)
4402 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_optional
);
4403 if (assemblyb
->permissions_refused
)
4404 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_refused
);
4406 module_add_cattrs (assembly
, moduleb
);
4409 mono_g_hash_table_foreach (assembly
->token_fixups
, (GHFunc
)fixup_method
, assembly
);
4411 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4412 * the final tokens and don't need another fixup pass. */
4414 if (moduleb
->global_methods
) {
4415 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
4416 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4417 moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
4418 mono_image_add_methodimpl (assembly
, mb
);
4422 for (i
= 0; i
< types
->len
; ++i
) {
4423 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4424 if (type
->methods
) {
4425 for (j
= 0; j
< type
->num_methods
; ++j
) {
4426 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4427 type
->methods
, MonoReflectionMethodBuilder
*, j
);
4429 mono_image_add_methodimpl (assembly
, mb
);
4434 g_ptr_array_free (types
, TRUE
);
4436 fixup_cattrs (assembly
);
4439 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4442 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4444 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4447 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4449 #ifndef DISABLE_REFLECTION_EMIT
4452 * mono_image_insert_string:
4453 * @module: module builder object
4456 * Insert @str into the user string stream of @module.
4459 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
4461 MonoDynamicImage
*assembly
;
4466 MONO_ARCH_SAVE_REGS
;
4468 if (!module
->dynamic_image
)
4469 mono_image_module_basic_init (module
);
4471 assembly
= module
->dynamic_image
;
4473 if (assembly
->save
) {
4474 mono_metadata_encode_value (1 | (str
->length
* 2), b
, &b
);
4475 idx
= mono_image_add_stream_data (&assembly
->us
, buf
, b
-buf
);
4476 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4478 char *swapped
= g_malloc (2 * mono_string_length (str
));
4479 const char *p
= (const char*)mono_string_chars (str
);
4481 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
4482 mono_image_add_stream_data (&assembly
->us
, swapped
, str
->length
* 2);
4486 mono_image_add_stream_data (&assembly
->us
, (const char*)mono_string_chars (str
), str
->length
* 2);
4488 mono_image_add_stream_data (&assembly
->us
, "", 1);
4490 idx
= assembly
->us
.index
++;
4493 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (MONO_TOKEN_STRING
| idx
), str
);
4495 return MONO_TOKEN_STRING
| idx
;
4499 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
4504 klass
= obj
->vtable
->klass
;
4505 if (strcmp (klass
->name
, "MonoMethod") == 0) {
4506 MonoMethod
*method
= ((MonoReflectionMethod
*)obj
)->method
;
4507 MonoMethodSignature
*sig
, *old
;
4508 guint32 sig_token
, parent
;
4511 g_assert (opt_param_types
&& (mono_method_signature (method
)->sentinelpos
>= 0));
4513 nargs
= mono_array_length (opt_param_types
);
4514 old
= mono_method_signature (method
);
4515 sig
= mono_metadata_signature_alloc ( &assembly
->image
, old
->param_count
+ nargs
);
4517 sig
->hasthis
= old
->hasthis
;
4518 sig
->explicit_this
= old
->explicit_this
;
4519 sig
->call_convention
= old
->call_convention
;
4520 sig
->generic_param_count
= old
->generic_param_count
;
4521 sig
->param_count
= old
->param_count
+ nargs
;
4522 sig
->sentinelpos
= old
->param_count
;
4523 sig
->ret
= old
->ret
;
4525 for (i
= 0; i
< old
->param_count
; i
++)
4526 sig
->params
[i
] = old
->params
[i
];
4528 for (i
= 0; i
< nargs
; i
++) {
4529 MonoReflectionType
*rt
= mono_array_get (opt_param_types
, MonoReflectionType
*, i
);
4530 sig
->params
[old
->param_count
+ i
] = rt
->type
;
4533 parent
= mono_image_typedef_or_ref (assembly
, &method
->klass
->byval_arg
);
4534 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_MEMBERREF_PARENT_TYPEREF
);
4535 parent
>>= MONO_TYPEDEFORREF_BITS
;
4537 parent
<<= MONO_MEMBERREF_PARENT_BITS
;
4538 parent
|= MONO_MEMBERREF_PARENT_TYPEREF
;
4540 sig_token
= method_encode_signature (assembly
, sig
);
4541 token
= mono_image_get_varargs_method_token (assembly
, parent
, method
->name
, sig_token
);
4542 } else if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4543 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4544 ReflectionMethodBuilder rmb
;
4545 guint32 parent
, sig
;
4548 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
4549 rmb
.opt_types
= opt_param_types
;
4551 sig
= method_builder_encode_signature (assembly
, &rmb
);
4553 parent
= mono_image_create_token (assembly
, obj
, TRUE
, TRUE
);
4554 g_assert (mono_metadata_token_table (parent
) == MONO_TABLE_METHOD
);
4556 parent
= mono_metadata_token_index (parent
) << MONO_MEMBERREF_PARENT_BITS
;
4557 parent
|= MONO_MEMBERREF_PARENT_METHODDEF
;
4559 name
= mono_string_to_utf8 (rmb
.name
);
4560 token
= mono_image_get_varargs_method_token (
4561 assembly
, parent
, name
, sig
);
4564 g_error ("requested method token for %s\n", klass
->name
);
4571 * mono_image_create_token:
4572 * @assembly: a dynamic assembly
4574 * @register_token: Whenever to register the token in the assembly->tokens hash.
4576 * Get a token to insert in the IL code stream for the given MemberInfo.
4577 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4578 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4582 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
4583 gboolean create_methodspec
, gboolean register_token
)
4588 klass
= obj
->vtable
->klass
;
4589 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4590 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4591 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4593 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
&& !mb
->generic_params
)
4594 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4596 token
= mono_image_get_methodbuilder_token (assembly
, mb
, create_methodspec
);
4597 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4598 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
4599 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
4600 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4602 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
)
4603 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4605 token
= mono_image_get_ctorbuilder_token (assembly
, mb
);
4606 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4607 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
4608 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
4609 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
4610 if (tb
->generic_params
) {
4611 token
= mono_image_get_generic_field_token (assembly
, fb
);
4613 token
= fb
->table_idx
| MONO_TOKEN_FIELD_DEF
;
4615 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
4616 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
4617 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
4618 } else if (strcmp (klass
->name
, "MonoType") == 0) {
4619 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4620 MonoClass
*mc
= mono_class_from_mono_type (tb
->type
);
4621 token
= mono_metadata_token_from_dor (
4622 mono_image_typedef_or_ref_full (assembly
, tb
->type
, mc
->generic_container
== NULL
));
4623 } else if (strcmp (klass
->name
, "GenericTypeParameterBuilder") == 0) {
4624 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4625 token
= mono_metadata_token_from_dor (
4626 mono_image_typedef_or_ref (assembly
, tb
->type
));
4627 } else if (strcmp (klass
->name
, "MonoGenericClass") == 0) {
4628 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4629 token
= mono_metadata_token_from_dor (
4630 mono_image_typedef_or_ref (assembly
, tb
->type
));
4631 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
4632 strcmp (klass
->name
, "MonoMethod") == 0 ||
4633 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
4634 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
4635 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
4636 if (m
->method
->is_inflated
) {
4637 if (create_methodspec
)
4638 token
= mono_image_get_methodspec_token (assembly
, m
->method
);
4640 token
= mono_image_get_inflated_method_token (assembly
, m
->method
);
4641 } else if ((m
->method
->klass
->image
== &assembly
->image
) &&
4642 !m
->method
->klass
->generic_class
) {
4643 static guint32 method_table_idx
= 0xffffff;
4644 if (m
->method
->klass
->wastypebuilder
) {
4645 /* we use the same token as the one that was assigned
4646 * to the Methodbuilder.
4647 * FIXME: do the equivalent for Fields.
4649 token
= m
->method
->token
;
4652 * Each token should have a unique index, but the indexes are
4653 * assigned by managed code, so we don't know about them. An
4654 * easy solution is to count backwards...
4656 method_table_idx
--;
4657 token
= MONO_TOKEN_METHOD_DEF
| method_table_idx
;
4660 token
= mono_image_get_methodref_token (assembly
, m
->method
, create_methodspec
);
4662 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4663 } else if (strcmp (klass
->name
, "MonoField") == 0) {
4664 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
4665 if ((f
->field
->parent
->image
== &assembly
->image
) && !is_field_on_inst (f
->field
)) {
4666 static guint32 field_table_idx
= 0xffffff;
4668 token
= MONO_TOKEN_FIELD_DEF
| field_table_idx
;
4670 token
= mono_image_get_fieldref_token (assembly
, f
);
4672 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4673 } else if (strcmp (klass
->name
, "MonoArrayMethod") == 0) {
4674 MonoReflectionArrayMethod
*m
= (MonoReflectionArrayMethod
*)obj
;
4675 token
= mono_image_get_array_token (assembly
, m
);
4676 } else if (strcmp (klass
->name
, "SignatureHelper") == 0) {
4677 MonoReflectionSigHelper
*s
= (MonoReflectionSigHelper
*)obj
;
4678 token
= MONO_TOKEN_SIGNATURE
| mono_image_get_sighelper_token (assembly
, s
);
4679 } else if (strcmp (klass
->name
, "EnumBuilder") == 0) {
4680 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4681 token
= mono_metadata_token_from_dor (
4682 mono_image_typedef_or_ref (assembly
, tb
->type
));
4683 } else if (strcmp (klass
->name
, "FieldOnTypeBuilderInst") == 0) {
4684 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
4685 token
= mono_image_get_field_on_inst_token (assembly
, f
);
4686 } else if (strcmp (klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
4687 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
4688 token
= mono_image_get_ctor_on_inst_token (assembly
, c
, create_methodspec
);
4689 } else if (strcmp (klass
->name
, "MethodOnTypeBuilderInst") == 0) {
4690 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
4691 token
= mono_image_get_method_on_inst_token (assembly
, m
, create_methodspec
);
4693 g_error ("requested token for %s\n", klass
->name
);
4697 mono_image_register_token (assembly
, token
, obj
);
4703 * mono_image_register_token:
4705 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4706 * the Module.ResolveXXXToken () methods to work.
4709 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
4711 MonoObject
*prev
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4713 /* There could be multiple MethodInfo objects with the same token */
4714 //g_assert (prev == obj);
4716 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), obj
);
4720 #endif /* DISABLE_REFLECTION_EMIT */
4723 guint32 import_lookup_table
;
4727 guint32 import_address_table_rva
;
4735 static gpointer
register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
);
4737 static MonoDynamicImage
*
4738 create_dynamic_mono_image (MonoDynamicAssembly
*assembly
, char *assembly_name
, char *module_name
)
4740 static const guchar entrycode
[16] = {0xff, 0x25, 0};
4741 MonoDynamicImage
*image
;
4744 const char *version
;
4746 if (!strcmp (mono_get_runtime_info ()->framework_version
, "2.1"))
4747 version
= "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4749 version
= mono_get_runtime_info ()->runtime_version
;
4752 image
= GC_MALLOC (sizeof (MonoDynamicImage
));
4754 image
= g_new0 (MonoDynamicImage
, 1);
4757 mono_profiler_module_event (&image
->image
, MONO_PROFILE_START_LOAD
);
4759 /*g_print ("created image %p\n", image);*/
4760 /* keep in sync with image.c */
4761 image
->image
.name
= assembly_name
;
4762 image
->image
.assembly_name
= image
->image
.name
; /* they may be different */
4763 image
->image
.module_name
= module_name
;
4764 image
->image
.version
= g_strdup (version
);
4765 image
->image
.md_version_major
= 1;
4766 image
->image
.md_version_minor
= 1;
4767 image
->image
.dynamic
= TRUE
;
4769 image
->image
.references
= g_new0 (MonoAssembly
*, 1);
4770 image
->image
.references
[0] = NULL
;
4772 mono_image_init (&image
->image
);
4774 image
->token_fixups
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_KEY_GC
);
4775 image
->method_to_table_idx
= g_hash_table_new (NULL
, NULL
);
4776 image
->field_to_table_idx
= g_hash_table_new (NULL
, NULL
);
4777 image
->method_aux_hash
= g_hash_table_new (NULL
, NULL
);
4778 image
->handleref
= g_hash_table_new (NULL
, NULL
);
4779 image
->tokens
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
4780 image
->generic_def_objects
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
4781 image
->methodspec
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_KEY_GC
);
4782 image
->typespec
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
4783 image
->typeref
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
4784 image
->blob_cache
= g_hash_table_new ((GHashFunc
)mono_blob_entry_hash
, (GCompareFunc
)mono_blob_entry_equal
);
4785 image
->gen_params
= g_ptr_array_new ();
4787 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4788 string_heap_init (&image
->sheap
);
4789 mono_image_add_stream_data (&image
->us
, "", 1);
4790 add_to_blob_cached (image
, (char*) "", 1, NULL
, 0);
4791 /* import tables... */
4792 mono_image_add_stream_data (&image
->code
, (char*)entrycode
, sizeof (entrycode
));
4793 image
->iat_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two IAT entries */
4794 image
->idt_offset
= mono_image_add_stream_zero (&image
->code
, 2 * sizeof (MonoIDT
)); /* two IDT entries */
4795 image
->imp_names_offset
= mono_image_add_stream_zero (&image
->code
, 2); /* flags for name entry */
4796 mono_image_add_stream_data (&image
->code
, "_CorExeMain", 12);
4797 mono_image_add_stream_data (&image
->code
, "mscoree.dll", 12);
4798 image
->ilt_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two ILT entries */
4799 stream_data_align (&image
->code
);
4801 image
->cli_header_offset
= mono_image_add_stream_zero (&image
->code
, sizeof (MonoCLIHeader
));
4803 for (i
=0; i
< MONO_TABLE_NUM
; ++i
) {
4804 image
->tables
[i
].next_idx
= 1;
4805 image
->tables
[i
].columns
= table_sizes
[i
];
4808 image
->image
.assembly
= (MonoAssembly
*)assembly
;
4809 image
->run
= assembly
->run
;
4810 image
->save
= assembly
->save
;
4811 image
->pe_kind
= 0x1; /* ILOnly */
4812 image
->machine
= 0x14c; /* I386 */
4814 mono_profiler_module_loaded (&image
->image
, MONO_PROFILE_OK
);
4820 free_blob_cache_entry (gpointer key
, gpointer val
, gpointer user_data
)
4826 mono_dynamic_image_free (MonoDynamicImage
*image
)
4828 MonoDynamicImage
*di
= image
;
4833 mono_g_hash_table_destroy (di
->methodspec
);
4835 g_hash_table_destroy (di
->typespec
);
4837 g_hash_table_destroy (di
->typeref
);
4839 g_hash_table_destroy (di
->handleref
);
4841 mono_g_hash_table_destroy (di
->tokens
);
4842 if (di
->generic_def_objects
)
4843 mono_g_hash_table_destroy (di
->generic_def_objects
);
4844 if (di
->blob_cache
) {
4845 g_hash_table_foreach (di
->blob_cache
, free_blob_cache_entry
, NULL
);
4846 g_hash_table_destroy (di
->blob_cache
);
4848 if (di
->standalonesig_cache
)
4849 g_hash_table_destroy (di
->standalonesig_cache
);
4850 for (list
= di
->array_methods
; list
; list
= list
->next
) {
4851 ArrayMethod
*am
= (ArrayMethod
*)list
->data
;
4856 g_list_free (di
->array_methods
);
4857 if (di
->gen_params
) {
4858 for (i
= 0; i
< di
->gen_params
->len
; i
++) {
4859 GenericParamTableEntry
*entry
= g_ptr_array_index (di
->gen_params
, i
);
4860 if (entry
->gparam
->type
.type
) {
4861 MonoGenericParam
*param
= entry
->gparam
->type
.type
->data
.generic_param
;
4862 g_free ((char*)param
->name
);
4867 g_ptr_array_free (di
->gen_params
, TRUE
);
4869 if (di
->token_fixups
)
4870 mono_g_hash_table_destroy (di
->token_fixups
);
4871 if (di
->method_to_table_idx
)
4872 g_hash_table_destroy (di
->method_to_table_idx
);
4873 if (di
->field_to_table_idx
)
4874 g_hash_table_destroy (di
->field_to_table_idx
);
4875 if (di
->method_aux_hash
)
4876 g_hash_table_destroy (di
->method_aux_hash
);
4877 g_free (di
->strong_name
);
4878 g_free (di
->win32_res
);
4880 g_free (di
->public_key
);
4882 /*g_print ("string heap destroy for image %p\n", di);*/
4883 mono_dynamic_stream_reset (&di
->sheap
);
4884 mono_dynamic_stream_reset (&di
->code
);
4885 mono_dynamic_stream_reset (&di
->resources
);
4886 mono_dynamic_stream_reset (&di
->us
);
4887 mono_dynamic_stream_reset (&di
->blob
);
4888 mono_dynamic_stream_reset (&di
->tstream
);
4889 mono_dynamic_stream_reset (&di
->guid
);
4890 for (i
= 0; i
< MONO_TABLE_NUM
; ++i
) {
4891 g_free (di
->tables
[i
].values
);
4895 #ifndef DISABLE_REFLECTION_EMIT
4898 * mono_image_basic_init:
4899 * @assembly: an assembly builder object
4901 * Create the MonoImage that represents the assembly builder and setup some
4902 * of the helper hash table and the basic metadata streams.
4905 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
4907 MonoDynamicAssembly
*assembly
;
4908 MonoDynamicImage
*image
;
4909 MonoDomain
*domain
= mono_object_domain (assemblyb
);
4911 MONO_ARCH_SAVE_REGS
;
4913 if (assemblyb
->dynamic_assembly
)
4917 assembly
= assemblyb
->dynamic_assembly
= GC_MALLOC (sizeof (MonoDynamicAssembly
));
4919 assembly
= assemblyb
->dynamic_assembly
= g_new0 (MonoDynamicAssembly
, 1);
4922 mono_profiler_assembly_event (&assembly
->assembly
, MONO_PROFILE_START_LOAD
);
4924 assembly
->assembly
.ref_count
= 1;
4925 assembly
->assembly
.dynamic
= TRUE
;
4926 assembly
->assembly
.corlib_internal
= assemblyb
->corlib_internal
;
4927 assemblyb
->assembly
.assembly
= (MonoAssembly
*)assembly
;
4928 assembly
->assembly
.basedir
= mono_string_to_utf8 (assemblyb
->dir
);
4929 if (assemblyb
->culture
)
4930 assembly
->assembly
.aname
.culture
= mono_string_to_utf8 (assemblyb
->culture
);
4932 assembly
->assembly
.aname
.culture
= g_strdup ("");
4934 if (assemblyb
->version
) {
4935 char *vstr
= mono_string_to_utf8 (assemblyb
->version
);
4936 char **version
= g_strsplit (vstr
, ".", 4);
4937 char **parts
= version
;
4938 assembly
->assembly
.aname
.major
= atoi (*parts
++);
4939 assembly
->assembly
.aname
.minor
= atoi (*parts
++);
4940 assembly
->assembly
.aname
.build
= *parts
!= NULL
? atoi (*parts
++) : 0;
4941 assembly
->assembly
.aname
.revision
= *parts
!= NULL
? atoi (*parts
) : 0;
4943 g_strfreev (version
);
4946 assembly
->assembly
.aname
.major
= 0;
4947 assembly
->assembly
.aname
.minor
= 0;
4948 assembly
->assembly
.aname
.build
= 0;
4949 assembly
->assembly
.aname
.revision
= 0;
4952 assembly
->run
= assemblyb
->access
!= 2;
4953 assembly
->save
= assemblyb
->access
!= 1;
4955 image
= create_dynamic_mono_image (assembly
, mono_string_to_utf8 (assemblyb
->name
), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4956 image
->initial_image
= TRUE
;
4957 assembly
->assembly
.aname
.name
= image
->image
.name
;
4958 assembly
->assembly
.image
= &image
->image
;
4960 mono_domain_assemblies_lock (domain
);
4961 domain
->domain_assemblies
= g_slist_prepend (domain
->domain_assemblies
, assembly
);
4962 mono_domain_assemblies_unlock (domain
);
4964 register_assembly (mono_object_domain (assemblyb
), &assemblyb
->assembly
, &assembly
->assembly
);
4966 mono_profiler_assembly_loaded (&assembly
->assembly
, MONO_PROFILE_OK
);
4968 mono_assembly_invoke_load_hook ((MonoAssembly
*)assembly
);
4971 #endif /* DISABLE_REFLECTION_EMIT */
4974 calc_section_size (MonoDynamicImage
*assembly
)
4978 /* alignment constraints */
4979 mono_image_add_stream_zero (&assembly
->code
, 4 - (assembly
->code
.index
% 4));
4980 g_assert ((assembly
->code
.index
% 4) == 0);
4981 assembly
->meta_size
+= 3;
4982 assembly
->meta_size
&= ~3;
4983 mono_image_add_stream_zero (&assembly
->resources
, 4 - (assembly
->resources
.index
% 4));
4984 g_assert ((assembly
->resources
.index
% 4) == 0);
4986 assembly
->sections
[MONO_SECTION_TEXT
].size
= assembly
->meta_size
+ assembly
->code
.index
+ assembly
->resources
.index
+ assembly
->strong_name_size
;
4987 assembly
->sections
[MONO_SECTION_TEXT
].attrs
= SECT_FLAGS_HAS_CODE
| SECT_FLAGS_MEM_EXECUTE
| SECT_FLAGS_MEM_READ
;
4990 if (assembly
->win32_res
) {
4991 guint32 res_size
= (assembly
->win32_res_size
+ 3) & ~3;
4993 assembly
->sections
[MONO_SECTION_RSRC
].size
= res_size
;
4994 assembly
->sections
[MONO_SECTION_RSRC
].attrs
= SECT_FLAGS_HAS_INITIALIZED_DATA
| SECT_FLAGS_MEM_READ
;
4998 assembly
->sections
[MONO_SECTION_RELOC
].size
= 12;
4999 assembly
->sections
[MONO_SECTION_RELOC
].attrs
= SECT_FLAGS_MEM_READ
| SECT_FLAGS_MEM_DISCARDABLE
| SECT_FLAGS_HAS_INITIALIZED_DATA
;
5009 MonoReflectionWin32Resource
*win32_res
; /* Only for leaf nodes */
5013 resource_tree_compare_by_id (gconstpointer a
, gconstpointer b
)
5015 ResTreeNode
*t1
= (ResTreeNode
*)a
;
5016 ResTreeNode
*t2
= (ResTreeNode
*)b
;
5018 return t1
->id
- t2
->id
;
5022 * resource_tree_create:
5024 * Organize the resources into a resource tree.
5026 static ResTreeNode
*
5027 resource_tree_create (MonoArray
*win32_resources
)
5029 ResTreeNode
*tree
, *res_node
, *type_node
, *lang_node
;
5033 tree
= g_new0 (ResTreeNode
, 1);
5035 for (i
= 0; i
< mono_array_length (win32_resources
); ++i
) {
5036 MonoReflectionWin32Resource
*win32_res
=
5037 (MonoReflectionWin32Resource
*)mono_array_addr (win32_resources
, MonoReflectionWin32Resource
, i
);
5041 /* FIXME: BUG: this stores managed references in unmanaged memory */
5042 lang_node
= g_new0 (ResTreeNode
, 1);
5043 lang_node
->id
= win32_res
->lang_id
;
5044 lang_node
->win32_res
= win32_res
;
5046 /* Create type node if neccesary */
5048 for (l
= tree
->children
; l
; l
= l
->next
)
5049 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_type
) {
5050 type_node
= (ResTreeNode
*)l
->data
;
5055 type_node
= g_new0 (ResTreeNode
, 1);
5056 type_node
->id
= win32_res
->res_type
;
5059 * The resource types have to be sorted otherwise
5060 * Windows Explorer can't display the version information.
5062 tree
->children
= g_slist_insert_sorted (tree
->children
,
5063 type_node
, resource_tree_compare_by_id
);
5066 /* Create res node if neccesary */
5068 for (l
= type_node
->children
; l
; l
= l
->next
)
5069 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_id
) {
5070 res_node
= (ResTreeNode
*)l
->data
;
5075 res_node
= g_new0 (ResTreeNode
, 1);
5076 res_node
->id
= win32_res
->res_id
;
5077 type_node
->children
= g_slist_append (type_node
->children
, res_node
);
5080 res_node
->children
= g_slist_append (res_node
->children
, lang_node
);
5087 * resource_tree_encode:
5089 * Encode the resource tree into the format used in the PE file.
5092 resource_tree_encode (ResTreeNode
*node
, char *begin
, char *p
, char **endbuf
)
5095 MonoPEResourceDir dir
;
5096 MonoPEResourceDirEntry dir_entry
;
5097 MonoPEResourceDataEntry data_entry
;
5099 guint32 res_id_entries
;
5102 * For the format of the resource directory, see the article
5103 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5107 memset (&dir
, 0, sizeof (dir
));
5108 memset (&dir_entry
, 0, sizeof (dir_entry
));
5109 memset (&data_entry
, 0, sizeof (data_entry
));
5111 g_assert (sizeof (dir
) == 16);
5112 g_assert (sizeof (dir_entry
) == 8);
5113 g_assert (sizeof (data_entry
) == 16);
5115 node
->offset
= p
- begin
;
5117 /* IMAGE_RESOURCE_DIRECTORY */
5118 res_id_entries
= g_slist_length (node
->children
);
5119 dir
.res_id_entries
= GUINT16_TO_LE (res_id_entries
);
5121 memcpy (p
, &dir
, sizeof (dir
));
5124 /* Reserve space for entries */
5126 p
+= sizeof (dir_entry
) * res_id_entries
;
5128 /* Write children */
5129 for (l
= node
->children
; l
; l
= l
->next
) {
5130 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5132 if (child
->win32_res
) {
5135 child
->offset
= p
- begin
;
5137 /* IMAGE_RESOURCE_DATA_ENTRY */
5138 data_entry
.rde_data_offset
= GUINT32_TO_LE (p
- begin
+ sizeof (data_entry
));
5139 size
= mono_array_length (child
->win32_res
->res_data
);
5140 data_entry
.rde_size
= GUINT32_TO_LE (size
);
5142 memcpy (p
, &data_entry
, sizeof (data_entry
));
5143 p
+= sizeof (data_entry
);
5145 memcpy (p
, mono_array_addr (child
->win32_res
->res_data
, char, 0), size
);
5148 resource_tree_encode (child
, begin
, p
, &p
);
5152 /* IMAGE_RESOURCE_ENTRY */
5153 for (l
= node
->children
; l
; l
= l
->next
) {
5154 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5156 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry
, FALSE
, child
->id
);
5157 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry
, !child
->win32_res
, child
->offset
);
5159 memcpy (entries
, &dir_entry
, sizeof (dir_entry
));
5160 entries
+= sizeof (dir_entry
);
5167 resource_tree_free (ResTreeNode
* node
)
5170 for (list
= node
->children
; list
; list
= list
->next
)
5171 resource_tree_free ((ResTreeNode
*)list
->data
);
5172 g_slist_free(node
->children
);
5177 assembly_add_win32_resources (MonoDynamicImage
*assembly
, MonoReflectionAssemblyBuilder
*assemblyb
)
5182 MonoReflectionWin32Resource
*win32_res
;
5185 if (!assemblyb
->win32_resources
)
5189 * Resources are stored in a three level tree inside the PE file.
5190 * - level one contains a node for each type of resource
5191 * - level two contains a node for each resource
5192 * - level three contains a node for each instance of a resource for a
5193 * specific language.
5196 tree
= resource_tree_create (assemblyb
->win32_resources
);
5198 /* Estimate the size of the encoded tree */
5200 for (i
= 0; i
< mono_array_length (assemblyb
->win32_resources
); ++i
) {
5201 win32_res
= (MonoReflectionWin32Resource
*)mono_array_addr (assemblyb
->win32_resources
, MonoReflectionWin32Resource
, i
);
5202 size
+= mono_array_length (win32_res
->res_data
);
5204 /* Directory structure */
5205 size
+= mono_array_length (assemblyb
->win32_resources
) * 256;
5206 p
= buf
= g_malloc (size
);
5208 resource_tree_encode (tree
, p
, p
, &p
);
5210 g_assert (p
- buf
<= size
);
5212 assembly
->win32_res
= g_malloc (p
- buf
);
5213 assembly
->win32_res_size
= p
- buf
;
5214 memcpy (assembly
->win32_res
, buf
, p
- buf
);
5217 resource_tree_free (tree
);
5221 fixup_resource_directory (char *res_section
, char *p
, guint32 rva
)
5223 MonoPEResourceDir
*dir
= (MonoPEResourceDir
*)p
;
5226 p
+= sizeof (MonoPEResourceDir
);
5227 for (i
= 0; i
< GUINT16_FROM_LE (dir
->res_named_entries
) + GUINT16_FROM_LE (dir
->res_id_entries
); ++i
) {
5228 MonoPEResourceDirEntry
*dir_entry
= (MonoPEResourceDirEntry
*)p
;
5229 char *child
= res_section
+ MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry
);
5230 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry
)) {
5231 fixup_resource_directory (res_section
, child
, rva
);
5233 MonoPEResourceDataEntry
*data_entry
= (MonoPEResourceDataEntry
*)child
;
5234 data_entry
->rde_data_offset
= GUINT32_TO_LE (GUINT32_FROM_LE (data_entry
->rde_data_offset
) + rva
);
5237 p
+= sizeof (MonoPEResourceDirEntry
);
5242 checked_write_file (HANDLE f
, gconstpointer buffer
, guint32 numbytes
)
5245 if (!WriteFile (f
, buffer
, numbytes
, &dummy
, NULL
))
5246 g_error ("WriteFile returned %d\n", GetLastError ());
5249 #ifndef DISABLE_REFLECTION_EMIT_SAVE
5252 * mono_image_create_pefile:
5253 * @mb: a module builder object
5255 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5256 * assembly->pefile where it can be easily retrieved later in chunks.
5259 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5261 MonoMSDOSHeader
*msdos
;
5262 MonoDotNetHeader
*header
;
5263 MonoSectionTable
*section
;
5264 MonoCLIHeader
*cli_header
;
5265 guint32 size
, image_size
, virtual_base
, text_offset
;
5266 guint32 header_start
, section_start
, file_offset
, virtual_offset
;
5267 MonoDynamicImage
*assembly
;
5268 MonoReflectionAssemblyBuilder
*assemblyb
;
5269 MonoDynamicStream pefile_stream
= {0};
5270 MonoDynamicStream
*pefile
= &pefile_stream
;
5272 guint32
*rva
, value
;
5274 static const unsigned char msheader
[] = {
5275 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5276 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5277 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5279 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5280 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5281 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5282 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5285 assemblyb
= mb
->assemblyb
;
5287 mono_image_basic_init (assemblyb
);
5288 assembly
= mb
->dynamic_image
;
5290 assembly
->pe_kind
= assemblyb
->pe_kind
;
5291 assembly
->machine
= assemblyb
->machine
;
5292 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->pe_kind
= assemblyb
->pe_kind
;
5293 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->machine
= assemblyb
->machine
;
5295 mono_image_build_metadata (mb
);
5297 if (mb
->is_main
&& assemblyb
->resources
) {
5298 int len
= mono_array_length (assemblyb
->resources
);
5299 for (i
= 0; i
< len
; ++i
)
5300 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (assemblyb
->resources
, MonoReflectionResource
, i
));
5303 if (mb
->resources
) {
5304 int len
= mono_array_length (mb
->resources
);
5305 for (i
= 0; i
< len
; ++i
)
5306 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (mb
->resources
, MonoReflectionResource
, i
));
5309 build_compressed_metadata (assembly
);
5312 assembly_add_win32_resources (assembly
, assemblyb
);
5314 nsections
= calc_section_size (assembly
);
5316 /* The DOS header and stub */
5317 g_assert (sizeof (MonoMSDOSHeader
) == sizeof (msheader
));
5318 mono_image_add_stream_data (pefile
, (char*)msheader
, sizeof (msheader
));
5320 /* the dotnet header */
5321 header_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoDotNetHeader
));
5323 /* the section tables */
5324 section_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoSectionTable
) * nsections
);
5326 file_offset
= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5327 virtual_offset
= VIRT_ALIGN
;
5330 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5331 if (!assembly
->sections
[i
].size
)
5334 file_offset
+= FILE_ALIGN
- 1;
5335 file_offset
&= ~(FILE_ALIGN
- 1);
5336 virtual_offset
+= VIRT_ALIGN
- 1;
5337 virtual_offset
&= ~(VIRT_ALIGN
- 1);
5339 assembly
->sections
[i
].offset
= file_offset
;
5340 assembly
->sections
[i
].rva
= virtual_offset
;
5342 file_offset
+= assembly
->sections
[i
].size
;
5343 virtual_offset
+= assembly
->sections
[i
].size
;
5344 image_size
+= (assembly
->sections
[i
].size
+ VIRT_ALIGN
- 1) & ~(VIRT_ALIGN
- 1);
5347 file_offset
+= FILE_ALIGN
- 1;
5348 file_offset
&= ~(FILE_ALIGN
- 1);
5350 image_size
+= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5352 /* back-patch info */
5353 msdos
= (MonoMSDOSHeader
*)pefile
->data
;
5354 msdos
->pe_offset
= GUINT32_FROM_LE (sizeof (MonoMSDOSHeader
));
5356 header
= (MonoDotNetHeader
*)(pefile
->data
+ header_start
);
5357 header
->pesig
[0] = 'P';
5358 header
->pesig
[1] = 'E';
5360 header
->coff
.coff_machine
= GUINT16_FROM_LE (assemblyb
->machine
);
5361 header
->coff
.coff_sections
= GUINT16_FROM_LE (nsections
);
5362 header
->coff
.coff_time
= GUINT32_FROM_LE (time (NULL
));
5363 header
->coff
.coff_opt_header_size
= GUINT16_FROM_LE (sizeof (MonoDotNetHeader
) - sizeof (MonoCOFFHeader
) - 4);
5364 if (assemblyb
->pekind
== 1) {
5366 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x210e);
5369 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x010e);
5372 virtual_base
= 0x400000; /* FIXME: 0x10000000 if a DLL */
5374 header
->pe
.pe_magic
= GUINT16_FROM_LE (0x10B);
5375 header
->pe
.pe_major
= 6;
5376 header
->pe
.pe_minor
= 0;
5377 size
= assembly
->sections
[MONO_SECTION_TEXT
].size
;
5378 size
+= FILE_ALIGN
- 1;
5379 size
&= ~(FILE_ALIGN
- 1);
5380 header
->pe
.pe_code_size
= GUINT32_FROM_LE(size
);
5381 size
= assembly
->sections
[MONO_SECTION_RSRC
].size
;
5382 size
+= FILE_ALIGN
- 1;
5383 size
&= ~(FILE_ALIGN
- 1);
5384 header
->pe
.pe_data_size
= GUINT32_FROM_LE(size
);
5385 g_assert (START_TEXT_RVA
== assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5386 header
->pe
.pe_rva_code_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5387 header
->pe
.pe_rva_data_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5388 /* pe_rva_entry_point always at the beginning of the text section */
5389 header
->pe
.pe_rva_entry_point
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5391 header
->nt
.pe_image_base
= GUINT32_FROM_LE (virtual_base
);
5392 header
->nt
.pe_section_align
= GUINT32_FROM_LE (VIRT_ALIGN
);
5393 header
->nt
.pe_file_alignment
= GUINT32_FROM_LE (FILE_ALIGN
);
5394 header
->nt
.pe_os_major
= GUINT16_FROM_LE (4);
5395 header
->nt
.pe_os_minor
= GUINT16_FROM_LE (0);
5396 header
->nt
.pe_subsys_major
= GUINT16_FROM_LE (4);
5397 size
= section_start
;
5398 size
+= FILE_ALIGN
- 1;
5399 size
&= ~(FILE_ALIGN
- 1);
5400 header
->nt
.pe_header_size
= GUINT32_FROM_LE (size
);
5402 size
+= VIRT_ALIGN
- 1;
5403 size
&= ~(VIRT_ALIGN
- 1);
5404 header
->nt
.pe_image_size
= GUINT32_FROM_LE (size
);
5407 // Translate the PEFileKind value to the value expected by the Windows loader
5413 // PEFileKinds.Dll == 1
5414 // PEFileKinds.ConsoleApplication == 2
5415 // PEFileKinds.WindowApplication == 3
5418 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5419 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5421 if (assemblyb
->pekind
== 3)
5426 header
->nt
.pe_subsys_required
= GUINT16_FROM_LE (kind
);
5428 header
->nt
.pe_stack_reserve
= GUINT32_FROM_LE (0x00100000);
5429 header
->nt
.pe_stack_commit
= GUINT32_FROM_LE (0x00001000);
5430 header
->nt
.pe_heap_reserve
= GUINT32_FROM_LE (0x00100000);
5431 header
->nt
.pe_heap_commit
= GUINT32_FROM_LE (0x00001000);
5432 header
->nt
.pe_loader_flags
= GUINT32_FROM_LE (0);
5433 header
->nt
.pe_data_dir_count
= GUINT32_FROM_LE (16);
5435 /* fill data directory entries */
5437 header
->datadir
.pe_resource_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].size
);
5438 header
->datadir
.pe_resource_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5440 header
->datadir
.pe_reloc_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].size
);
5441 header
->datadir
.pe_reloc_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].rva
);
5443 header
->datadir
.pe_cli_header
.size
= GUINT32_FROM_LE (72);
5444 header
->datadir
.pe_cli_header
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->cli_header_offset
);
5445 header
->datadir
.pe_iat
.size
= GUINT32_FROM_LE (8);
5446 header
->datadir
.pe_iat
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5447 /* patch entrypoint name */
5448 if (assemblyb
->pekind
== 1)
5449 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorDllMain", 12);
5451 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorExeMain", 12);
5452 /* patch imported function RVA name */
5453 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->iat_offset
);
5454 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
);
5456 /* the import table */
5457 header
->datadir
.pe_import_table
.size
= GUINT32_FROM_LE (79); /* FIXME: magic number? */
5458 header
->datadir
.pe_import_table
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->idt_offset
);
5459 /* patch imported dll RVA name and other entries in the dir */
5460 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, name_rva
));
5461 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
+ 14); /* 14 is hint+strlen+1 of func name */
5462 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_address_table_rva
));
5463 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5464 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_lookup_table
));
5465 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->ilt_offset
);
5467 p
= (guchar
*)(assembly
->code
.data
+ assembly
->ilt_offset
);
5468 value
= (assembly
->text_rva
+ assembly
->imp_names_offset
);
5469 *p
++ = (value
) & 0xff;
5470 *p
++ = (value
>> 8) & (0xff);
5471 *p
++ = (value
>> 16) & (0xff);
5472 *p
++ = (value
>> 24) & (0xff);
5474 /* the CLI header info */
5475 cli_header
= (MonoCLIHeader
*)(assembly
->code
.data
+ assembly
->cli_header_offset
);
5476 cli_header
->ch_size
= GUINT32_FROM_LE (72);
5477 cli_header
->ch_runtime_major
= GUINT16_FROM_LE (2);
5478 if (mono_framework_version () > 1)
5479 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (5);
5481 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (0);
5482 cli_header
->ch_flags
= GUINT32_FROM_LE (assemblyb
->pe_kind
);
5483 if (assemblyb
->entry_point
) {
5484 guint32 table_idx
= 0;
5485 if (!strcmp (assemblyb
->entry_point
->object
.vtable
->klass
->name
, "MethodBuilder")) {
5486 MonoReflectionMethodBuilder
*methodb
= (MonoReflectionMethodBuilder
*)assemblyb
->entry_point
;
5487 table_idx
= methodb
->table_idx
;
5489 table_idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, assemblyb
->entry_point
->method
));
5491 cli_header
->ch_entry_point
= GUINT32_FROM_LE (table_idx
| MONO_TOKEN_METHOD_DEF
);
5493 cli_header
->ch_entry_point
= GUINT32_FROM_LE (0);
5495 /* The embedded managed resources */
5496 text_offset
= assembly
->text_rva
+ assembly
->code
.index
;
5497 cli_header
->ch_resources
.rva
= GUINT32_FROM_LE (text_offset
);
5498 cli_header
->ch_resources
.size
= GUINT32_FROM_LE (assembly
->resources
.index
);
5499 text_offset
+= assembly
->resources
.index
;
5500 cli_header
->ch_metadata
.rva
= GUINT32_FROM_LE (text_offset
);
5501 cli_header
->ch_metadata
.size
= GUINT32_FROM_LE (assembly
->meta_size
);
5502 text_offset
+= assembly
->meta_size
;
5503 if (assembly
->strong_name_size
) {
5504 cli_header
->ch_strong_name
.rva
= GUINT32_FROM_LE (text_offset
);
5505 cli_header
->ch_strong_name
.size
= GUINT32_FROM_LE (assembly
->strong_name_size
);
5506 text_offset
+= assembly
->strong_name_size
;
5509 /* write the section tables and section content */
5510 section
= (MonoSectionTable
*)(pefile
->data
+ section_start
);
5511 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5512 static const char section_names
[][7] = {
5513 ".text", ".rsrc", ".reloc"
5515 if (!assembly
->sections
[i
].size
)
5517 strcpy (section
->st_name
, section_names
[i
]);
5518 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5519 section
->st_virtual_address
= GUINT32_FROM_LE (assembly
->sections
[i
].rva
);
5520 section
->st_virtual_size
= GUINT32_FROM_LE (assembly
->sections
[i
].size
);
5521 section
->st_raw_data_size
= GUINT32_FROM_LE (GUINT32_TO_LE (section
->st_virtual_size
) + (FILE_ALIGN
- 1));
5522 section
->st_raw_data_size
&= GUINT32_FROM_LE (~(FILE_ALIGN
- 1));
5523 section
->st_raw_data_ptr
= GUINT32_FROM_LE (assembly
->sections
[i
].offset
);
5524 section
->st_flags
= GUINT32_FROM_LE (assembly
->sections
[i
].attrs
);
5528 checked_write_file (file
, pefile
->data
, pefile
->index
);
5530 mono_dynamic_stream_reset (pefile
);
5532 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5533 if (!assembly
->sections
[i
].size
)
5536 if (SetFilePointer (file
, assembly
->sections
[i
].offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5537 g_error ("SetFilePointer returned %d\n", GetLastError ());
5540 case MONO_SECTION_TEXT
:
5541 /* patch entry point */
5542 p
= (guchar
*)(assembly
->code
.data
+ 2);
5543 value
= (virtual_base
+ assembly
->text_rva
+ assembly
->iat_offset
);
5544 *p
++ = (value
) & 0xff;
5545 *p
++ = (value
>> 8) & 0xff;
5546 *p
++ = (value
>> 16) & 0xff;
5547 *p
++ = (value
>> 24) & 0xff;
5549 checked_write_file (file
, assembly
->code
.data
, assembly
->code
.index
);
5550 checked_write_file (file
, assembly
->resources
.data
, assembly
->resources
.index
);
5551 checked_write_file (file
, assembly
->image
.raw_metadata
, assembly
->meta_size
);
5552 checked_write_file (file
, assembly
->strong_name
, assembly
->strong_name_size
);
5555 g_free (assembly
->image
.raw_metadata
);
5557 case MONO_SECTION_RELOC
: {
5561 guint16 type_and_offset
;
5565 g_assert (sizeof (reloc
) == 12);
5567 reloc
.page_rva
= GUINT32_FROM_LE (assembly
->text_rva
);
5568 reloc
.block_size
= GUINT32_FROM_LE (12);
5571 * the entrypoint is always at the start of the text section
5572 * 3 is IMAGE_REL_BASED_HIGHLOW
5573 * 2 is patch_size_rva - text_rva
5575 reloc
.type_and_offset
= GUINT16_FROM_LE ((3 << 12) + (2));
5578 checked_write_file (file
, &reloc
, sizeof (reloc
));
5582 case MONO_SECTION_RSRC
:
5583 if (assembly
->win32_res
) {
5585 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5586 fixup_resource_directory (assembly
->win32_res
, assembly
->win32_res
, assembly
->sections
[i
].rva
);
5587 checked_write_file (file
, assembly
->win32_res
, assembly
->win32_res_size
);
5591 g_assert_not_reached ();
5595 /* check that the file is properly padded */
5596 if (SetFilePointer (file
, file_offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5597 g_error ("SetFilePointer returned %d\n", GetLastError ());
5598 if (! SetEndOfFile (file
))
5599 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5601 mono_dynamic_stream_reset (&assembly
->code
);
5602 mono_dynamic_stream_reset (&assembly
->us
);
5603 mono_dynamic_stream_reset (&assembly
->blob
);
5604 mono_dynamic_stream_reset (&assembly
->guid
);
5605 mono_dynamic_stream_reset (&assembly
->sheap
);
5607 g_hash_table_foreach (assembly
->blob_cache
, (GHFunc
)g_free
, NULL
);
5608 g_hash_table_destroy (assembly
->blob_cache
);
5609 assembly
->blob_cache
= NULL
;
5612 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5615 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5617 g_assert_not_reached ();
5620 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5622 #ifndef DISABLE_REFLECTION_EMIT
5624 MonoReflectionModule
*
5625 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
5629 MonoImageOpenStatus status
;
5630 MonoDynamicAssembly
*assembly
;
5631 guint32 module_count
;
5632 MonoImage
**new_modules
;
5633 gboolean
*new_modules_loaded
;
5635 name
= mono_string_to_utf8 (fileName
);
5637 image
= mono_image_open (name
, &status
);
5640 if (status
== MONO_IMAGE_ERROR_ERRNO
)
5641 exc
= mono_get_exception_file_not_found (fileName
);
5643 exc
= mono_get_exception_bad_image_format (name
);
5645 mono_raise_exception (exc
);
5650 assembly
= ab
->dynamic_assembly
;
5651 image
->assembly
= (MonoAssembly
*)assembly
;
5653 module_count
= image
->assembly
->image
->module_count
;
5654 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5655 new_modules_loaded
= g_new0 (gboolean
, module_count
+ 1);
5657 if (image
->assembly
->image
->modules
)
5658 memcpy (new_modules
, image
->assembly
->image
->modules
, module_count
* sizeof (MonoImage
*));
5659 if (image
->assembly
->image
->modules_loaded
)
5660 memcpy (new_modules_loaded
, image
->assembly
->image
->modules_loaded
, module_count
* sizeof (gboolean
));
5661 new_modules
[module_count
] = image
;
5662 new_modules_loaded
[module_count
] = TRUE
;
5663 mono_image_addref (image
);
5665 g_free (image
->assembly
->image
->modules
);
5666 image
->assembly
->image
->modules
= new_modules
;
5667 image
->assembly
->image
->modules_loaded
= new_modules_loaded
;
5668 image
->assembly
->image
->module_count
++;
5670 mono_assembly_load_references (image
, &status
);
5672 mono_image_close (image
);
5673 mono_raise_exception (mono_get_exception_file_not_found (fileName
));
5676 return mono_module_get_object (mono_domain_get (), image
);
5679 #endif /* DISABLE_REFLECTION_EMIT */
5682 * We need to return always the same object for MethodInfo, FieldInfo etc..
5683 * but we need to consider the reflected type.
5684 * type uses a different hash, since it uses custom hash/equal functions.
5689 MonoClass
*refclass
;
5693 reflected_equal (gconstpointer a
, gconstpointer b
) {
5694 const ReflectedEntry
*ea
= a
;
5695 const ReflectedEntry
*eb
= b
;
5697 return (ea
->item
== eb
->item
) && (ea
->refclass
== eb
->refclass
);
5701 reflected_hash (gconstpointer a
) {
5702 const ReflectedEntry
*ea
= a
;
5703 return mono_aligned_addr_hash (ea
->item
);
5706 #define CHECK_OBJECT(t,p,k) \
5712 mono_domain_lock (domain); \
5713 if (!domain->refobject_hash) \
5714 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5715 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5716 mono_domain_unlock (domain); \
5719 mono_domain_unlock (domain); \
5722 #ifdef HAVE_BOEHM_GC
5723 #define ALLOC_REFENTRY mono_gc_alloc_fixed (sizeof (ReflectedEntry), NULL)
5725 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5728 #define CACHE_OBJECT(t,p,o,k) \
5731 ReflectedEntry pe; \
5733 pe.refclass = (k); \
5734 mono_domain_lock (domain); \
5735 if (!domain->refobject_hash) \
5736 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5737 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5739 ReflectedEntry *e = ALLOC_REFENTRY; \
5741 e->refclass = (k); \
5742 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5745 mono_domain_unlock (domain); \
5750 register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
)
5752 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
5756 register_module (MonoDomain
*domain
, MonoReflectionModuleBuilder
*res
, MonoDynamicImage
*module
)
5758 CACHE_OBJECT (MonoReflectionModuleBuilder
*, module
, res
, NULL
);
5761 #ifndef DISABLE_REFLECTION_EMIT
5764 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
5766 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
5767 MonoReflectionAssemblyBuilder
*ab
= moduleb
->assemblyb
;
5770 MonoImage
**new_modules
;
5773 * FIXME: we already created an image in mono_image_basic_init (), but
5774 * we don't know which module it belongs to, since that is only
5775 * determined at assembly save time.
5777 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5778 image
= create_dynamic_mono_image (ab
->dynamic_assembly
, mono_string_to_utf8 (ab
->name
), mono_string_to_utf8 (moduleb
->module
.fqname
));
5780 moduleb
->module
.image
= &image
->image
;
5781 moduleb
->dynamic_image
= image
;
5782 register_module (mono_object_domain (moduleb
), moduleb
, image
);
5784 /* register the module with the assembly */
5785 ass
= ab
->dynamic_assembly
->assembly
.image
;
5786 module_count
= ass
->module_count
;
5787 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5790 memcpy (new_modules
, ass
->modules
, module_count
* sizeof (MonoImage
*));
5791 new_modules
[module_count
] = &image
->image
;
5792 mono_image_addref (&image
->image
);
5794 g_free (ass
->modules
);
5795 ass
->modules
= new_modules
;
5796 ass
->module_count
++;
5803 * mono_assembly_get_object:
5804 * @domain: an app domain
5805 * @assembly: an assembly
5807 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5809 MonoReflectionAssembly
*
5810 mono_assembly_get_object (MonoDomain
*domain
, MonoAssembly
*assembly
)
5812 static MonoClass
*System_Reflection_Assembly
;
5813 MonoReflectionAssembly
*res
;
5815 CHECK_OBJECT (MonoReflectionAssembly
*, assembly
, NULL
);
5816 if (!System_Reflection_Assembly
)
5817 System_Reflection_Assembly
= mono_class_from_name (
5818 mono_defaults
.corlib
, "System.Reflection", "Assembly");
5819 res
= (MonoReflectionAssembly
*)mono_object_new (domain
, System_Reflection_Assembly
);
5820 res
->assembly
= assembly
;
5822 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
5827 MonoReflectionModule
*
5828 mono_module_get_object (MonoDomain
*domain
, MonoImage
*image
)
5830 static MonoClass
*System_Reflection_Module
;
5831 MonoReflectionModule
*res
;
5834 CHECK_OBJECT (MonoReflectionModule
*, image
, NULL
);
5835 if (!System_Reflection_Module
)
5836 System_Reflection_Module
= mono_class_from_name (
5837 mono_defaults
.corlib
, "System.Reflection", "Module");
5838 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
5841 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
5843 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, image
->name
));
5844 basename
= g_path_get_basename (image
->name
);
5845 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, basename
));
5846 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, image
->module_name
));
5850 if (image
->assembly
->image
== image
) {
5851 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULE
, 1);
5855 if (image
->assembly
->image
->modules
) {
5856 for (i
= 0; i
< image
->assembly
->image
->module_count
; i
++) {
5857 if (image
->assembly
->image
->modules
[i
] == image
)
5858 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULEREF
, i
+ 1);
5860 g_assert (res
->token
);
5864 CACHE_OBJECT (MonoReflectionModule
*, image
, res
, NULL
);
5867 MonoReflectionModule
*
5868 mono_module_file_get_object (MonoDomain
*domain
, MonoImage
*image
, int table_index
)
5870 static MonoClass
*System_Reflection_Module
;
5871 MonoReflectionModule
*res
;
5872 MonoTableInfo
*table
;
5873 guint32 cols
[MONO_FILE_SIZE
];
5875 guint32 i
, name_idx
;
5878 if (!System_Reflection_Module
)
5879 System_Reflection_Module
= mono_class_from_name (
5880 mono_defaults
.corlib
, "System.Reflection", "Module");
5881 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
5883 table
= &image
->tables
[MONO_TABLE_FILE
];
5884 g_assert (table_index
< table
->rows
);
5885 mono_metadata_decode_row (table
, table_index
, cols
, MONO_FILE_SIZE
);
5888 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
5889 name
= mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]);
5891 /* Check whenever the row has a corresponding row in the moduleref table */
5892 table
= &image
->tables
[MONO_TABLE_MODULEREF
];
5893 for (i
= 0; i
< table
->rows
; ++i
) {
5894 name_idx
= mono_metadata_decode_row_col (table
, i
, MONO_MODULEREF_NAME
);
5895 val
= mono_metadata_string_heap (image
, name_idx
);
5896 if (strcmp (val
, name
) == 0)
5897 res
->image
= image
->modules
[i
];
5900 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, name
));
5901 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, name
));
5902 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, name
));
5903 res
->is_resource
= cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
;
5904 res
->token
= mono_metadata_make_token (MONO_TABLE_FILE
, table_index
+ 1);
5910 mymono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
5912 if ((t1
->type
!= t2
->type
) ||
5913 (t1
->byref
!= t2
->byref
))
5917 case MONO_TYPE_VOID
:
5918 case MONO_TYPE_BOOLEAN
:
5919 case MONO_TYPE_CHAR
:
5930 case MONO_TYPE_STRING
:
5933 case MONO_TYPE_OBJECT
:
5934 case MONO_TYPE_TYPEDBYREF
:
5936 case MONO_TYPE_VALUETYPE
:
5937 case MONO_TYPE_CLASS
:
5938 case MONO_TYPE_SZARRAY
:
5939 return t1
->data
.klass
== t2
->data
.klass
;
5941 return mymono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
);
5942 case MONO_TYPE_ARRAY
:
5943 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
5945 return t1
->data
.array
->eklass
== t2
->data
.array
->eklass
;
5946 case MONO_TYPE_GENERICINST
: {
5948 MonoGenericInst
*i1
= t1
->data
.generic_class
->context
.class_inst
;
5949 MonoGenericInst
*i2
= t2
->data
.generic_class
->context
.class_inst
;
5950 if (i1
->type_argc
!= i2
->type_argc
)
5952 if (!mono_metadata_type_equal (&t1
->data
.generic_class
->container_class
->byval_arg
,
5953 &t2
->data
.generic_class
->container_class
->byval_arg
))
5955 /* FIXME: we should probably just compare the instance pointers directly. */
5956 for (i
= 0; i
< i1
->type_argc
; ++i
) {
5957 if (!mono_metadata_type_equal (i1
->type_argv
[i
], i2
->type_argv
[i
]))
5963 case MONO_TYPE_MVAR
:
5964 return t1
->data
.generic_param
== t2
->data
.generic_param
;
5966 g_error ("implement type compare for %0x!", t1
->type
);
5974 mymono_metadata_type_hash (MonoType
*t1
)
5980 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
5982 case MONO_TYPE_VALUETYPE
:
5983 case MONO_TYPE_CLASS
:
5984 case MONO_TYPE_SZARRAY
:
5985 /* check if the distribution is good enough */
5986 return ((hash
<< 5) - hash
) ^ g_str_hash (t1
->data
.klass
->name
);
5988 return ((hash
<< 5) - hash
) ^ mymono_metadata_type_hash (t1
->data
.type
);
5989 case MONO_TYPE_GENERICINST
: {
5991 MonoGenericInst
*inst
= t1
->data
.generic_class
->context
.class_inst
;
5992 hash
+= g_str_hash (t1
->data
.generic_class
->container_class
->name
);
5994 for (i
= 0; i
< inst
->type_argc
; ++i
) {
5995 hash
+= mymono_metadata_type_hash (inst
->type_argv
[i
]);
6004 static MonoReflectionGenericClass
*
6005 mono_generic_class_get_object (MonoDomain
*domain
, MonoType
*geninst
)
6007 static MonoClass
*System_Reflection_MonoGenericClass
;
6008 MonoReflectionGenericClass
*res
;
6009 MonoClass
*klass
, *gklass
;
6011 if (!System_Reflection_MonoGenericClass
) {
6012 System_Reflection_MonoGenericClass
= mono_class_from_name (
6013 mono_defaults
.corlib
, "System.Reflection", "MonoGenericClass");
6014 g_assert (System_Reflection_MonoGenericClass
);
6017 klass
= mono_class_from_mono_type (geninst
);
6018 gklass
= klass
->generic_class
->container_class
;
6020 mono_class_init (klass
);
6023 res
= (MonoReflectionGenericClass
*) mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, System_Reflection_MonoGenericClass
), mono_class_instance_size (System_Reflection_MonoGenericClass
));
6025 res
= (MonoReflectionGenericClass
*) mono_object_new (domain
, System_Reflection_MonoGenericClass
);
6028 res
->type
.type
= geninst
;
6029 g_assert (gklass
->reflection_info
);
6030 g_assert (!strcmp (((MonoObject
*)gklass
->reflection_info
)->vtable
->klass
->name
, "TypeBuilder"));
6031 MONO_OBJECT_SETREF (res
, generic_type
, gklass
->reflection_info
);
6037 verify_safe_for_managed_space (MonoType
*type
)
6039 switch (type
->type
) {
6041 case MONO_TYPE_ARRAY
:
6042 return verify_safe_for_managed_space (&type
->data
.array
->eklass
->byval_arg
);
6044 return verify_safe_for_managed_space (type
->data
.type
);
6045 case MONO_TYPE_SZARRAY
:
6046 return verify_safe_for_managed_space (&type
->data
.klass
->byval_arg
);
6047 case MONO_TYPE_GENERICINST
: {
6048 MonoGenericInst
*inst
= type
->data
.generic_class
->inst
;
6052 for (i
= 0; i
< inst
->type_argc
; ++i
)
6053 if (!verify_safe_for_managed_space (inst
->type_argv
[i
]))
6059 case MONO_TYPE_MVAR
:
6066 * mono_type_get_object:
6067 * @domain: an app domain
6070 * Return an System.MonoType object representing the type @type.
6073 mono_type_get_object (MonoDomain
*domain
, MonoType
*type
)
6075 MonoReflectionType
*res
;
6076 MonoClass
*klass
= mono_class_from_mono_type (type
);
6078 /*we must avoid using @type as it might have come
6079 * from a mono_metadata_type_dup and the caller
6080 * expects that is can be freed.
6081 * Using the right type from
6083 type
= klass
->byval_arg
.byref
== type
->byref
? &klass
->byval_arg
: &klass
->this_arg
;
6085 /* void is very common */
6086 if (type
->type
== MONO_TYPE_VOID
&& domain
->typeof_void
)
6087 return (MonoReflectionType
*)domain
->typeof_void
;
6090 * If the vtable of the given class was already created, we can use
6091 * the MonoType from there and avoid all locking and hash table lookups.
6093 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6094 * that the resulting object is diferent.
6096 if (type
== &klass
->byval_arg
&& !klass
->image
->dynamic
) {
6097 MonoVTable
*vtable
= mono_class_try_get_vtable (domain
, klass
);
6098 if (vtable
&& vtable
->type
)
6099 return vtable
->type
;
6102 mono_domain_lock (domain
);
6103 if (!domain
->type_hash
)
6104 domain
->type_hash
= mono_g_hash_table_new_type ((GHashFunc
)mymono_metadata_type_hash
,
6105 (GCompareFunc
)mymono_metadata_type_equal
, MONO_HASH_VALUE_GC
);
6106 if ((res
= mono_g_hash_table_lookup (domain
->type_hash
, type
))) {
6107 mono_domain_unlock (domain
);
6110 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6111 if ((type
->type
== MONO_TYPE_GENERICINST
) && type
->data
.generic_class
->is_dynamic
&& !type
->data
.generic_class
->container_class
->wastypebuilder
) {
6112 res
= (MonoReflectionType
*)mono_generic_class_get_object (domain
, type
);
6113 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6114 mono_domain_unlock (domain
);
6118 if (!verify_safe_for_managed_space (type
)) {
6119 mono_domain_unlock (domain
);
6120 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6123 if (klass
->reflection_info
&& !klass
->wastypebuilder
) {
6124 /* g_assert_not_reached (); */
6125 /* should this be considered an error condition? */
6127 mono_domain_unlock (domain
);
6128 return klass
->reflection_info
;
6131 // FIXME: Get rid of this, do it in the icalls for Type
6132 mono_class_init (klass
);
6134 res
= (MonoReflectionType
*)mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, mono_defaults
.monotype_class
), mono_class_instance_size (mono_defaults
.monotype_class
));
6136 res
= (MonoReflectionType
*)mono_object_new (domain
, mono_defaults
.monotype_class
);
6139 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6141 if (type
->type
== MONO_TYPE_VOID
)
6142 MONO_OBJECT_SETREF (domain
, typeof_void
, res
);
6144 mono_domain_unlock (domain
);
6149 * mono_method_get_object:
6150 * @domain: an app domain
6152 * @refclass: the reflected type (can be NULL)
6154 * Return an System.Reflection.MonoMethod object representing the method @method.
6156 MonoReflectionMethod
*
6157 mono_method_get_object (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
6160 * We use the same C representation for methods and constructors, but the type
6161 * name in C# is different.
6163 static MonoClass
*System_Reflection_MonoMethod
= NULL
;
6164 static MonoClass
*System_Reflection_MonoCMethod
= NULL
;
6165 static MonoClass
*System_Reflection_MonoGenericMethod
= NULL
;
6166 static MonoClass
*System_Reflection_MonoGenericCMethod
= NULL
;
6168 MonoReflectionMethod
*ret
;
6171 * Don't let static RGCTX invoke wrappers get into
6172 * MonoReflectionMethods.
6174 if (method
->wrapper_type
== MONO_WRAPPER_STATIC_RGCTX_INVOKE
)
6175 method
= mono_marshal_method_from_wrapper (method
);
6177 if (method
->is_inflated
) {
6178 MonoReflectionGenericMethod
*gret
;
6180 refclass
= method
->klass
;
6181 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6182 if ((*method
->name
== '.') && (!strcmp (method
->name
, ".ctor") || !strcmp (method
->name
, ".cctor"))) {
6183 if (!System_Reflection_MonoGenericCMethod
)
6184 System_Reflection_MonoGenericCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericCMethod");
6185 klass
= System_Reflection_MonoGenericCMethod
;
6187 if (!System_Reflection_MonoGenericMethod
)
6188 System_Reflection_MonoGenericMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericMethod");
6189 klass
= System_Reflection_MonoGenericMethod
;
6191 gret
= (MonoReflectionGenericMethod
*)mono_object_new (domain
, klass
);
6192 gret
->method
.method
= method
;
6193 MONO_OBJECT_SETREF (gret
, method
.name
, mono_string_new (domain
, method
->name
));
6194 MONO_OBJECT_SETREF (gret
, method
.reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6195 CACHE_OBJECT (MonoReflectionMethod
*, method
, (MonoReflectionMethod
*)gret
, refclass
);
6199 refclass
= method
->klass
;
6201 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6202 if (*method
->name
== '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0)) {
6203 if (!System_Reflection_MonoCMethod
)
6204 System_Reflection_MonoCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoCMethod");
6205 klass
= System_Reflection_MonoCMethod
;
6208 if (!System_Reflection_MonoMethod
)
6209 System_Reflection_MonoMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoMethod");
6210 klass
= System_Reflection_MonoMethod
;
6212 ret
= (MonoReflectionMethod
*)mono_object_new (domain
, klass
);
6213 ret
->method
= method
;
6214 MONO_OBJECT_SETREF (ret
, reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6215 CACHE_OBJECT (MonoReflectionMethod
*, method
, ret
, refclass
);
6219 * mono_field_get_object:
6220 * @domain: an app domain
6224 * Return an System.Reflection.MonoField object representing the field @field
6227 MonoReflectionField
*
6228 mono_field_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
)
6230 MonoReflectionField
*res
;
6231 static MonoClass
*monofield_klass
;
6233 CHECK_OBJECT (MonoReflectionField
*, field
, klass
);
6234 if (!monofield_klass
)
6235 monofield_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoField");
6236 res
= (MonoReflectionField
*)mono_object_new (domain
, monofield_klass
);
6239 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, mono_field_get_name (field
)));
6240 if (is_field_on_inst (field
))
6241 res
->attrs
= get_field_on_inst_generic_type (field
)->attrs
;
6243 res
->attrs
= field
->type
->attrs
;
6244 MONO_OBJECT_SETREF (res
, type
, mono_type_get_object (domain
, field
->type
));
6245 CACHE_OBJECT (MonoReflectionField
*, field
, res
, klass
);
6249 * mono_property_get_object:
6250 * @domain: an app domain
6252 * @property: a property
6254 * Return an System.Reflection.MonoProperty object representing the property @property
6257 MonoReflectionProperty
*
6258 mono_property_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
)
6260 MonoReflectionProperty
*res
;
6261 static MonoClass
*monoproperty_klass
;
6263 CHECK_OBJECT (MonoReflectionProperty
*, property
, klass
);
6264 if (!monoproperty_klass
)
6265 monoproperty_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoProperty");
6266 res
= (MonoReflectionProperty
*)mono_object_new (domain
, monoproperty_klass
);
6268 res
->property
= property
;
6269 CACHE_OBJECT (MonoReflectionProperty
*, property
, res
, klass
);
6273 * mono_event_get_object:
6274 * @domain: an app domain
6278 * Return an System.Reflection.MonoEvent object representing the event @event
6281 MonoReflectionEvent
*
6282 mono_event_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
)
6284 MonoReflectionEvent
*res
;
6285 static MonoClass
*monoevent_klass
;
6287 CHECK_OBJECT (MonoReflectionEvent
*, event
, klass
);
6288 if (!monoevent_klass
)
6289 monoevent_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoEvent");
6290 res
= (MonoReflectionEvent
*)mono_object_new (domain
, monoevent_klass
);
6293 CACHE_OBJECT (MonoReflectionEvent
*, event
, res
, klass
);
6297 * mono_get_reflection_missing_object:
6298 * @domain: Domain where the object lives
6300 * Returns the System.Reflection.Missing.Value singleton object
6301 * (of type System.Reflection.Missing).
6303 * Used as the value for ParameterInfo.DefaultValue when Optional
6307 mono_get_reflection_missing_object (MonoDomain
*domain
)
6310 static MonoClassField
*missing_value_field
= NULL
;
6312 if (!missing_value_field
) {
6313 MonoClass
*missing_klass
;
6314 missing_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Missing");
6315 mono_class_init (missing_klass
);
6316 missing_value_field
= mono_class_get_field_from_name (missing_klass
, "Value");
6317 g_assert (missing_value_field
);
6319 obj
= mono_field_get_value_object (domain
, missing_value_field
, NULL
);
6325 get_dbnull (MonoDomain
*domain
, MonoObject
**dbnull
)
6328 *dbnull
= mono_get_dbnull_object (domain
);
6333 get_reflection_missing (MonoDomain
*domain
, MonoObject
**reflection_missing
)
6335 if (!*reflection_missing
)
6336 *reflection_missing
= mono_get_reflection_missing_object (domain
);
6337 return *reflection_missing
;
6341 * mono_param_get_objects:
6342 * @domain: an app domain
6345 * Return an System.Reflection.ParameterInfo array object representing the parameters
6346 * in the method @method.
6349 mono_param_get_objects (MonoDomain
*domain
, MonoMethod
*method
)
6351 static MonoClass
*System_Reflection_ParameterInfo
;
6352 static MonoClass
*System_Reflection_ParameterInfo_array
;
6353 MonoArray
*res
= NULL
;
6354 MonoReflectionMethod
*member
= NULL
;
6355 MonoReflectionParameter
*param
= NULL
;
6356 char **names
, **blobs
= NULL
;
6357 guint32
*types
= NULL
;
6358 MonoType
*type
= NULL
;
6359 MonoObject
*dbnull
= NULL
;
6360 MonoObject
*missing
= NULL
;
6361 MonoMarshalSpec
**mspecs
;
6362 MonoMethodSignature
*sig
;
6363 MonoVTable
*pinfo_vtable
;
6366 if (!System_Reflection_ParameterInfo_array
) {
6369 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ParameterInfo");
6370 mono_memory_barrier ();
6371 System_Reflection_ParameterInfo
= klass
;
6373 klass
= mono_array_class_get (klass
, 1);
6374 mono_memory_barrier ();
6375 System_Reflection_ParameterInfo_array
= klass
;
6378 if (!mono_method_signature (method
)->param_count
)
6379 return mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), 0);
6381 /* Note: the cache is based on the address of the signature into the method
6382 * since we already cache MethodInfos with the method as keys.
6384 CHECK_OBJECT (MonoArray
*, &(method
->signature
), NULL
);
6386 sig
= mono_method_signature (method
);
6387 member
= mono_method_get_object (domain
, method
, NULL
);
6388 names
= g_new (char *, sig
->param_count
);
6389 mono_method_get_param_names (method
, (const char **) names
);
6391 mspecs
= g_new (MonoMarshalSpec
*, sig
->param_count
+ 1);
6392 mono_method_get_marshal_info (method
, mspecs
);
6394 res
= mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), sig
->param_count
);
6395 pinfo_vtable
= mono_class_vtable (domain
, System_Reflection_ParameterInfo
);
6396 for (i
= 0; i
< sig
->param_count
; ++i
) {
6397 param
= (MonoReflectionParameter
*)mono_object_new_specific (pinfo_vtable
);
6398 MONO_OBJECT_SETREF (param
, ClassImpl
, mono_type_get_object (domain
, sig
->params
[i
]));
6399 MONO_OBJECT_SETREF (param
, MemberImpl
, (MonoObject
*)member
);
6400 MONO_OBJECT_SETREF (param
, NameImpl
, mono_string_new (domain
, names
[i
]));
6401 param
->PositionImpl
= i
;
6402 param
->AttrsImpl
= sig
->params
[i
]->attrs
;
6404 if (!(param
->AttrsImpl
& PARAM_ATTRIBUTE_HAS_DEFAULT
)) {
6405 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6406 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6408 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6412 blobs
= g_new0 (char *, sig
->param_count
);
6413 types
= g_new0 (guint32
, sig
->param_count
);
6414 get_default_param_value_blobs (method
, blobs
, types
);
6417 /* Build MonoType for the type from the Constant Table */
6419 type
= g_new0 (MonoType
, 1);
6420 type
->type
= types
[i
];
6421 type
->data
.klass
= NULL
;
6422 if (types
[i
] == MONO_TYPE_CLASS
)
6423 type
->data
.klass
= mono_defaults
.object_class
;
6424 else if ((sig
->params
[i
]->type
== MONO_TYPE_VALUETYPE
) && sig
->params
[i
]->data
.klass
->enumtype
) {
6425 /* For enums, types [i] contains the base type */
6427 type
->type
= MONO_TYPE_VALUETYPE
;
6428 type
->data
.klass
= mono_class_from_mono_type (sig
->params
[i
]);
6430 type
->data
.klass
= mono_class_from_mono_type (type
);
6432 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, mono_get_object_from_blob (domain
, type
, blobs
[i
]));
6434 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6435 if (types
[i
] != MONO_TYPE_CLASS
&& !param
->DefaultValueImpl
) {
6436 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6437 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6439 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6445 MONO_OBJECT_SETREF (param
, MarshalAsImpl
, (MonoObject
*)mono_reflection_marshal_from_marshal_spec (domain
, method
->klass
, mspecs
[i
+ 1]));
6447 mono_array_setref (res
, i
, param
);
6454 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
6456 mono_metadata_free_marshal_spec (mspecs
[i
]);
6459 CACHE_OBJECT (MonoArray
*, &(method
->signature
), res
, NULL
);
6463 * mono_method_body_get_object:
6464 * @domain: an app domain
6467 * Return an System.Reflection.MethodBody object representing the method @method.
6469 MonoReflectionMethodBody
*
6470 mono_method_body_get_object (MonoDomain
*domain
, MonoMethod
*method
)
6472 static MonoClass
*System_Reflection_MethodBody
= NULL
;
6473 static MonoClass
*System_Reflection_LocalVariableInfo
= NULL
;
6474 static MonoClass
*System_Reflection_ExceptionHandlingClause
= NULL
;
6475 MonoReflectionMethodBody
*ret
;
6476 MonoMethodNormal
*mn
;
6477 MonoMethodHeader
*header
;
6478 guint32 method_rva
, local_var_sig_token
;
6480 unsigned char format
, flags
;
6483 if (!System_Reflection_MethodBody
)
6484 System_Reflection_MethodBody
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MethodBody");
6485 if (!System_Reflection_LocalVariableInfo
)
6486 System_Reflection_LocalVariableInfo
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "LocalVariableInfo");
6487 if (!System_Reflection_ExceptionHandlingClause
)
6488 System_Reflection_ExceptionHandlingClause
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ExceptionHandlingClause");
6490 CHECK_OBJECT (MonoReflectionMethodBody
*, method
, NULL
);
6492 if ((method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
6493 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
6494 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
6495 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
))
6497 mn
= (MonoMethodNormal
*)method
;
6498 header
= mono_method_get_header (method
);
6500 /* Obtain local vars signature token */
6501 method_rva
= mono_metadata_decode_row_col (&method
->klass
->image
->tables
[MONO_TABLE_METHOD
], mono_metadata_token_index (method
->token
) - 1, MONO_METHOD_RVA
);
6502 ptr
= mono_image_rva_map (method
->klass
->image
, method_rva
);
6503 flags
= *(const unsigned char *) ptr
;
6504 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
6506 case METHOD_HEADER_TINY_FORMAT
:
6507 case METHOD_HEADER_TINY_FORMAT1
:
6508 local_var_sig_token
= 0;
6510 case METHOD_HEADER_FAT_FORMAT
:
6514 local_var_sig_token
= read32 (ptr
);
6517 g_assert_not_reached ();
6520 ret
= (MonoReflectionMethodBody
*)mono_object_new (domain
, System_Reflection_MethodBody
);
6522 ret
->init_locals
= header
->init_locals
;
6523 ret
->max_stack
= header
->max_stack
;
6524 ret
->local_var_sig_token
= local_var_sig_token
;
6525 MONO_OBJECT_SETREF (ret
, il
, mono_array_new (domain
, mono_defaults
.byte_class
, header
->code_size
));
6526 memcpy (mono_array_addr (ret
->il
, guint8
, 0), header
->code
, header
->code_size
);
6529 MONO_OBJECT_SETREF (ret
, locals
, mono_array_new (domain
, System_Reflection_LocalVariableInfo
, header
->num_locals
));
6530 for (i
= 0; i
< header
->num_locals
; ++i
) {
6531 MonoReflectionLocalVariableInfo
*info
= (MonoReflectionLocalVariableInfo
*)mono_object_new (domain
, System_Reflection_LocalVariableInfo
);
6532 MONO_OBJECT_SETREF (info
, local_type
, mono_type_get_object (domain
, header
->locals
[i
]));
6533 info
->is_pinned
= header
->locals
[i
]->pinned
;
6534 info
->local_index
= i
;
6535 mono_array_setref (ret
->locals
, i
, info
);
6539 MONO_OBJECT_SETREF (ret
, clauses
, mono_array_new (domain
, System_Reflection_ExceptionHandlingClause
, header
->num_clauses
));
6540 for (i
= 0; i
< header
->num_clauses
; ++i
) {
6541 MonoReflectionExceptionHandlingClause
*info
= (MonoReflectionExceptionHandlingClause
*)mono_object_new (domain
, System_Reflection_ExceptionHandlingClause
);
6542 MonoExceptionClause
*clause
= &header
->clauses
[i
];
6544 info
->flags
= clause
->flags
;
6545 info
->try_offset
= clause
->try_offset
;
6546 info
->try_length
= clause
->try_len
;
6547 info
->handler_offset
= clause
->handler_offset
;
6548 info
->handler_length
= clause
->handler_len
;
6549 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)
6550 info
->filter_offset
= clause
->data
.filter_offset
;
6551 else if (clause
->data
.catch_class
)
6552 MONO_OBJECT_SETREF (info
, catch_type
, mono_type_get_object (mono_domain_get (), &clause
->data
.catch_class
->byval_arg
));
6554 mono_array_setref (ret
->clauses
, i
, info
);
6557 CACHE_OBJECT (MonoReflectionMethodBody
*, method
, ret
, NULL
);
6562 * mono_get_dbnull_object:
6563 * @domain: Domain where the object lives
6565 * Returns the System.DBNull.Value singleton object
6567 * Used as the value for ParameterInfo.DefaultValue
6570 mono_get_dbnull_object (MonoDomain
*domain
)
6573 static MonoClassField
*dbnull_value_field
= NULL
;
6575 if (!dbnull_value_field
) {
6576 MonoClass
*dbnull_klass
;
6577 dbnull_klass
= mono_class_from_name (mono_defaults
.corlib
, "System", "DBNull");
6578 mono_class_init (dbnull_klass
);
6579 dbnull_value_field
= mono_class_get_field_from_name (dbnull_klass
, "Value");
6580 g_assert (dbnull_value_field
);
6582 obj
= mono_field_get_value_object (domain
, dbnull_value_field
, NULL
);
6588 get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
)
6590 guint32 param_index
, i
, lastp
, crow
= 0;
6591 guint32 param_cols
[MONO_PARAM_SIZE
], const_cols
[MONO_CONSTANT_SIZE
];
6594 MonoClass
*klass
= method
->klass
;
6595 MonoImage
*image
= klass
->image
;
6596 MonoMethodSignature
*methodsig
= mono_method_signature (method
);
6598 MonoTableInfo
*constt
;
6599 MonoTableInfo
*methodt
;
6600 MonoTableInfo
*paramt
;
6602 if (!methodsig
->param_count
)
6605 mono_class_init (klass
);
6607 if (klass
->image
->dynamic
) {
6608 MonoReflectionMethodAux
*aux
;
6609 if (method
->is_inflated
)
6610 method
= ((MonoMethodInflated
*)method
)->declaring
;
6611 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
6612 if (aux
&& aux
->param_defaults
) {
6613 memcpy (blobs
, &(aux
->param_defaults
[1]), methodsig
->param_count
* sizeof (char*));
6614 memcpy (types
, &(aux
->param_default_types
[1]), methodsig
->param_count
* sizeof (guint32
));
6619 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
6620 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
6621 constt
= &image
->tables
[MONO_TABLE_CONSTANT
];
6623 idx
= mono_method_get_index (method
) - 1;
6624 g_assert (idx
!= -1);
6626 param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
6627 if (idx
+ 1 < methodt
->rows
)
6628 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
6630 lastp
= paramt
->rows
+ 1;
6632 for (i
= param_index
; i
< lastp
; ++i
) {
6635 mono_metadata_decode_row (paramt
, i
- 1, param_cols
, MONO_PARAM_SIZE
);
6636 paramseq
= param_cols
[MONO_PARAM_SEQUENCE
];
6638 if (!param_cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_DEFAULT
)
6641 crow
= mono_metadata_get_constant_index (image
, MONO_TOKEN_PARAM_DEF
| i
, crow
+ 1);
6646 mono_metadata_decode_row (constt
, crow
- 1, const_cols
, MONO_CONSTANT_SIZE
);
6647 blobs
[paramseq
- 1] = (gpointer
) mono_metadata_blob_heap (image
, const_cols
[MONO_CONSTANT_VALUE
]);
6648 types
[paramseq
- 1] = const_cols
[MONO_CONSTANT_TYPE
];
6655 mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
)
6660 MonoType
*basetype
= type
;
6665 klass
= mono_class_from_mono_type (type
);
6666 if (klass
->valuetype
) {
6667 object
= mono_object_new (domain
, klass
);
6668 retval
= ((gchar
*) object
+ sizeof (MonoObject
));
6669 if (klass
->enumtype
)
6670 basetype
= klass
->enum_basetype
;
6675 if (!mono_get_constant_value_from_blob (domain
, basetype
->type
, blob
, retval
))
6682 assembly_name_to_aname (MonoAssemblyName
*assembly
, char *p
) {
6686 memset (assembly
, 0, sizeof (MonoAssemblyName
));
6688 assembly
->culture
= "";
6689 memset (assembly
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
6691 while (*p
&& (isalnum (*p
) || *p
== '.' || *p
== '-' || *p
== '_' || *p
== '$' || *p
== '@'))
6694 while (g_ascii_isspace (*p
) || *p
== ',') {
6703 if (*p
== 'V' && g_ascii_strncasecmp (p
, "Version=", 8) == 0) {
6705 assembly
->major
= strtoul (p
, &s
, 10);
6706 if (s
== p
|| *s
!= '.')
6709 assembly
->minor
= strtoul (p
, &s
, 10);
6710 if (s
== p
|| *s
!= '.')
6713 assembly
->build
= strtoul (p
, &s
, 10);
6714 if (s
== p
|| *s
!= '.')
6717 assembly
->revision
= strtoul (p
, &s
, 10);
6721 } else if (*p
== 'C' && g_ascii_strncasecmp (p
, "Culture=", 8) == 0) {
6723 if (g_ascii_strncasecmp (p
, "neutral", 7) == 0) {
6724 assembly
->culture
= "";
6727 assembly
->culture
= p
;
6728 while (*p
&& *p
!= ',') {
6732 } else if (*p
== 'P' && g_ascii_strncasecmp (p
, "PublicKeyToken=", 15) == 0) {
6734 if (strncmp (p
, "null", 4) == 0) {
6739 while (*p
&& *p
!= ',') {
6742 len
= (p
- start
+ 1);
6743 if (len
> MONO_PUBLIC_KEY_TOKEN_LENGTH
)
6744 len
= MONO_PUBLIC_KEY_TOKEN_LENGTH
;
6745 g_strlcpy ((char*)assembly
->public_key_token
, start
, len
);
6748 while (*p
&& *p
!= ',')
6752 while (g_ascii_isspace (*p
) || *p
== ',') {
6766 * mono_reflection_parse_type:
6769 * Parse a type name as accepted by the GetType () method and output the info
6770 * extracted in the info structure.
6771 * the name param will be mangled, so, make a copy before passing it to this function.
6772 * The fields in info will be valid until the memory pointed to by name is valid.
6774 * See also mono_type_get_name () below.
6776 * Returns: 0 on parse error.
6779 _mono_reflection_parse_type (char *name
, char **endptr
, gboolean is_recursed
,
6780 MonoTypeNameParse
*info
)
6782 char *start
, *p
, *w
, *temp
, *last_point
, *startn
;
6783 int in_modifiers
= 0;
6784 int isbyref
= 0, rank
, arity
= 0, i
;
6786 start
= p
= w
= name
;
6788 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6789 memset (&info
->assembly
, 0, sizeof (MonoAssemblyName
));
6790 info
->name
= info
->name_space
= NULL
;
6791 info
->nested
= NULL
;
6792 info
->modifiers
= NULL
;
6793 info
->type_arguments
= NULL
;
6795 /* last_point separates the namespace from the name */
6798 while (*p
== ' ') p
++, start
++, w
++, name
++;
6803 *p
= 0; /* NULL terminate the name */
6805 info
->nested
= g_list_append (info
->nested
, startn
);
6806 /* we have parsed the nesting namespace + name */
6810 info
->name_space
= start
;
6812 info
->name
= last_point
+ 1;
6814 info
->name_space
= (char *)"";
6833 i
= strtol (p
, &temp
, 10);
6850 info
->name_space
= start
;
6852 info
->name
= last_point
+ 1;
6854 info
->name_space
= (char *)"";
6861 if (isbyref
) /* only one level allowed by the spec */
6864 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (0));
6868 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-1));
6874 info
->type_arguments
= g_ptr_array_new ();
6875 for (i
= 0; i
< arity
; i
++) {
6876 MonoTypeNameParse
*subinfo
= g_new0 (MonoTypeNameParse
, 1);
6877 gboolean fqname
= FALSE
;
6879 g_ptr_array_add (info
->type_arguments
, subinfo
);
6886 if (!_mono_reflection_parse_type (p
, &p
, TRUE
, subinfo
))
6897 while (*p
&& (*p
!= ']'))
6905 if (g_ascii_isspace (*aname
)) {
6912 !assembly_name_to_aname (&subinfo
->assembly
, aname
))
6916 if (i
+ 1 < arity
) {
6936 else if (*p
== '*') /* '*' means unknown lower bound */
6937 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-2));
6944 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (rank
));
6955 if (g_ascii_isspace (*p
)) {
6962 return 0; /* missing assembly name */
6963 if (!assembly_name_to_aname (&info
->assembly
, p
))
6969 if (info
->assembly
.name
)
6972 // *w = 0; /* terminate class name */
6974 if (!info
->name
|| !*info
->name
)
6978 /* add other consistency checks */
6983 mono_reflection_parse_type (char *name
, MonoTypeNameParse
*info
)
6985 return _mono_reflection_parse_type (name
, NULL
, FALSE
, info
);
6989 _mono_reflection_get_type_from_info (MonoTypeNameParse
*info
, MonoImage
*image
, gboolean ignorecase
)
6991 gboolean type_resolve
= FALSE
;
6993 MonoImage
*rootimage
= image
;
6995 if (info
->assembly
.name
) {
6996 MonoAssembly
*assembly
= mono_assembly_loaded (&info
->assembly
);
6997 if (!assembly
&& image
&& image
->assembly
&& mono_assembly_names_equal (&info
->assembly
, &image
->assembly
->aname
))
6999 * This could happen in the AOT compiler case when the search hook is not
7002 assembly
= image
->assembly
;
7004 /* then we must load the assembly ourselve - see #60439 */
7005 assembly
= mono_assembly_load (&info
->assembly
, NULL
, NULL
);
7009 image
= assembly
->image
;
7010 } else if (!image
) {
7011 image
= mono_defaults
.corlib
;
7014 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7015 if (type
== NULL
&& !info
->assembly
.name
&& image
!= mono_defaults
.corlib
) {
7016 image
= mono_defaults
.corlib
;
7017 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7024 mono_reflection_get_type_internal (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7029 gboolean bounded
= FALSE
;
7032 image
= mono_defaults
.corlib
;
7035 klass
= mono_class_from_name_case (image
, info
->name_space
, info
->name
);
7037 klass
= mono_class_from_name (image
, info
->name_space
, info
->name
);
7040 for (mod
= info
->nested
; mod
; mod
= mod
->next
) {
7041 gpointer iter
= NULL
;
7045 mono_class_init (parent
);
7047 while ((klass
= mono_class_get_nested_types (parent
, &iter
))) {
7049 if (g_strcasecmp (klass
->name
, mod
->data
) == 0)
7052 if (strcmp (klass
->name
, mod
->data
) == 0)
7061 mono_class_init (klass
);
7063 if (info
->type_arguments
) {
7064 MonoType
**type_args
= g_new0 (MonoType
*, info
->type_arguments
->len
);
7065 MonoReflectionType
*the_type
;
7069 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7070 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7072 type_args
[i
] = _mono_reflection_get_type_from_info (subinfo
, rootimage
, ignorecase
);
7073 if (!type_args
[i
]) {
7079 the_type
= mono_type_get_object (mono_domain_get (), &klass
->byval_arg
);
7081 instance
= mono_reflection_bind_generic_parameters (
7082 the_type
, info
->type_arguments
->len
, type_args
);
7088 klass
= mono_class_from_mono_type (instance
);
7091 for (mod
= info
->modifiers
; mod
; mod
= mod
->next
) {
7092 modval
= GPOINTER_TO_UINT (mod
->data
);
7093 if (!modval
) { /* byref: must be last modifier */
7094 return &klass
->this_arg
;
7095 } else if (modval
== -1) {
7096 klass
= mono_ptr_class_get (&klass
->byval_arg
);
7097 } else if (modval
== -2) {
7099 } else { /* array rank */
7100 klass
= mono_bounded_array_class_get (klass
, modval
, bounded
);
7102 mono_class_init (klass
);
7105 return &klass
->byval_arg
;
7109 * mono_reflection_get_type:
7110 * @image: a metadata context
7111 * @info: type description structure
7112 * @ignorecase: flag for case-insensitive string compares
7113 * @type_resolve: whenever type resolve was already tried
7115 * Build a MonoType from the type description in @info.
7120 mono_reflection_get_type (MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
) {
7121 return mono_reflection_get_type_with_rootimage(image
, image
, info
, ignorecase
, type_resolve
);
7125 mono_reflection_get_type_internal_dynamic (MonoImage
*rootimage
, MonoAssembly
*assembly
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7127 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)mono_assembly_get_object (mono_domain_get (), assembly
);
7131 g_assert (assembly
->dynamic
);
7133 /* Enumerate all modules */
7136 if (abuilder
->modules
) {
7137 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
7138 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
7139 type
= mono_reflection_get_type_internal (rootimage
, &mb
->dynamic_image
->image
, info
, ignorecase
);
7145 if (!type
&& abuilder
->loaded_modules
) {
7146 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
7147 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
7148 type
= mono_reflection_get_type_internal (rootimage
, mod
->image
, info
, ignorecase
);
7158 mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
)
7161 MonoReflectionAssembly
*assembly
;
7165 if (image
&& image
->dynamic
)
7166 type
= mono_reflection_get_type_internal_dynamic (rootimage
, image
->assembly
, info
, ignorecase
);
7168 type
= mono_reflection_get_type_internal (rootimage
, image
, info
, ignorecase
);
7171 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7178 *type_resolve
= TRUE
;
7181 /* Reconstruct the type name */
7182 fullName
= g_string_new ("");
7183 if (info
->name_space
&& (info
->name_space
[0] != '\0'))
7184 g_string_printf (fullName
, "%s.%s", info
->name_space
, info
->name
);
7186 g_string_printf (fullName
, info
->name
);
7187 for (mod
= info
->nested
; mod
; mod
= mod
->next
)
7188 g_string_append_printf (fullName
, "+%s", (char*)mod
->data
);
7190 assembly
= mono_domain_try_type_resolve ( mono_domain_get (), fullName
->str
, NULL
);
7192 if (assembly
->assembly
->dynamic
)
7193 type
= mono_reflection_get_type_internal_dynamic (rootimage
, assembly
->assembly
, info
, ignorecase
);
7195 type
= mono_reflection_get_type_internal (rootimage
, assembly
->assembly
->image
,
7198 g_string_free (fullName
, TRUE
);
7203 mono_reflection_free_type_info (MonoTypeNameParse
*info
)
7205 g_list_free (info
->modifiers
);
7206 g_list_free (info
->nested
);
7208 if (info
->type_arguments
) {
7211 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7212 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7214 mono_reflection_free_type_info (subinfo
);
7215 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7219 g_ptr_array_free (info
->type_arguments
, TRUE
);
7224 * mono_reflection_type_from_name:
7226 * @image: a metadata context (can be NULL).
7228 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7229 * it defaults to get the type from @image or, if @image is NULL or loading
7230 * from it fails, uses corlib.
7234 mono_reflection_type_from_name (char *name
, MonoImage
*image
)
7236 MonoType
*type
= NULL
;
7237 MonoTypeNameParse info
;
7240 /* Make a copy since parse_type modifies its argument */
7241 tmp
= g_strdup (name
);
7243 /*g_print ("requested type %s\n", str);*/
7244 if (mono_reflection_parse_type (tmp
, &info
)) {
7245 type
= _mono_reflection_get_type_from_info (&info
, image
, FALSE
);
7249 mono_reflection_free_type_info (&info
);
7254 * mono_reflection_get_token:
7256 * Return the metadata token of OBJ which should be an object
7257 * representing a metadata element.
7260 mono_reflection_get_token (MonoObject
*obj
)
7265 klass
= obj
->vtable
->klass
;
7267 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
7268 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
7270 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7271 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
7272 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
7274 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7275 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
7276 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
7278 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7279 token
= mono_image_create_token (((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
, obj
, FALSE
, TRUE
);
7280 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
7281 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
7282 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
7283 } else if (strcmp (klass
->name
, "MonoType") == 0) {
7284 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
7285 token
= mono_class_from_mono_type (tb
->type
)->type_token
;
7286 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
7287 strcmp (klass
->name
, "MonoMethod") == 0 ||
7288 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
7289 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
7290 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
7291 if (m
->method
->is_inflated
) {
7292 MonoMethodInflated
*inflated
= (MonoMethodInflated
*) m
->method
;
7293 return inflated
->declaring
->token
;
7295 token
= m
->method
->token
;
7297 } else if (strcmp (klass
->name
, "MonoField") == 0) {
7298 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
7300 if (is_field_on_inst (f
->field
)) {
7301 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)f
->field
->parent
->generic_class
;
7302 int field_index
= f
->field
- dgclass
->fields
;
7305 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
7306 obj
= dgclass
->field_objects
[field_index
];
7307 return mono_reflection_get_token (obj
);
7309 token
= mono_class_get_field_token (f
->field
);
7310 } else if (strcmp (klass
->name
, "MonoProperty") == 0) {
7311 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)obj
;
7313 token
= mono_class_get_property_token (p
->property
);
7314 } else if (strcmp (klass
->name
, "MonoEvent") == 0) {
7315 MonoReflectionEvent
*p
= (MonoReflectionEvent
*)obj
;
7317 token
= mono_class_get_event_token (p
->event
);
7318 } else if (strcmp (klass
->name
, "ParameterInfo") == 0) {
7319 MonoReflectionParameter
*p
= (MonoReflectionParameter
*)obj
;
7321 token
= mono_method_get_param_token (((MonoReflectionMethod
*)p
->MemberImpl
)->method
, p
->PositionImpl
);
7322 } else if (strcmp (klass
->name
, "Module") == 0) {
7323 MonoReflectionModule
*m
= (MonoReflectionModule
*)obj
;
7326 } else if (strcmp (klass
->name
, "Assembly") == 0) {
7327 token
= mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1);
7329 gchar
*msg
= g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass
->name_space
, klass
->name
);
7330 MonoException
*ex
= mono_get_exception_not_implemented (msg
);
7332 mono_raise_exception (ex
);
7339 load_cattr_value (MonoImage
*image
, MonoType
*t
, const char *p
, const char **end
)
7341 int slen
, type
= t
->type
;
7342 MonoClass
*tklass
= t
->data
.klass
;
7348 case MONO_TYPE_BOOLEAN
: {
7349 MonoBoolean
*bval
= g_malloc (sizeof (MonoBoolean
));
7354 case MONO_TYPE_CHAR
:
7356 case MONO_TYPE_I2
: {
7357 guint16
*val
= g_malloc (sizeof (guint16
));
7362 #if SIZEOF_VOID_P == 4
7368 case MONO_TYPE_I4
: {
7369 guint32
*val
= g_malloc (sizeof (guint32
));
7374 #if SIZEOF_VOID_P == 8
7375 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
7379 case MONO_TYPE_I8
: {
7380 guint64
*val
= g_malloc (sizeof (guint64
));
7385 case MONO_TYPE_R8
: {
7386 double *val
= g_malloc (sizeof (double));
7391 case MONO_TYPE_VALUETYPE
:
7392 if (t
->data
.klass
->enumtype
) {
7393 type
= t
->data
.klass
->enum_basetype
->type
;
7396 g_error ("generic valutype %s not handled in custom attr value decoding", t
->data
.klass
->name
);
7399 case MONO_TYPE_STRING
:
7400 if (*p
== (char)0xFF) {
7404 slen
= mono_metadata_decode_value (p
, &p
);
7406 return mono_string_new_len (mono_domain_get (), p
, slen
);
7407 case MONO_TYPE_CLASS
: {
7410 if (*p
== (char)0xFF) {
7415 slen
= mono_metadata_decode_value (p
, &p
);
7416 n
= g_memdup (p
, slen
+ 1);
7418 t
= mono_reflection_type_from_name (n
, image
);
7420 g_warning ("Cannot load type '%s'", n
);
7424 return mono_type_get_object (mono_domain_get (), t
);
7428 case MONO_TYPE_OBJECT
: {
7431 MonoClass
*subc
= NULL
;
7436 } else if (subt
== 0x0E) {
7437 type
= MONO_TYPE_STRING
;
7439 } else if (subt
== 0x1D) {
7440 MonoType simple_type
= {{0}};
7445 /* See Partition II, Appendix B3 */
7446 etype
= MONO_TYPE_OBJECT
;
7447 type
= MONO_TYPE_SZARRAY
;
7448 simple_type
.type
= etype
;
7449 tklass
= mono_class_from_mono_type (&simple_type
);
7451 } else if (subt
== 0x55) {
7454 slen
= mono_metadata_decode_value (p
, &p
);
7455 n
= g_memdup (p
, slen
+ 1);
7457 t
= mono_reflection_type_from_name (n
, image
);
7459 g_error ("Cannot load type '%s'", n
);
7462 subc
= mono_class_from_mono_type (t
);
7463 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
7464 MonoType simple_type
= {{0}};
7465 simple_type
.type
= subt
;
7466 subc
= mono_class_from_mono_type (&simple_type
);
7468 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
7470 val
= load_cattr_value (image
, &subc
->byval_arg
, p
, end
);
7471 obj
= mono_object_new (mono_domain_get (), subc
);
7472 memcpy ((char*)obj
+ sizeof (MonoObject
), val
, mono_class_value_size (subc
, NULL
));
7476 case MONO_TYPE_SZARRAY
: {
7478 guint32 i
, alen
, basetype
;
7481 if (alen
== 0xffffffff) {
7485 arr
= mono_array_new (mono_domain_get(), tklass
, alen
);
7486 basetype
= tklass
->byval_arg
.type
;
7487 if (basetype
== MONO_TYPE_VALUETYPE
&& tklass
->enumtype
)
7488 basetype
= tklass
->enum_basetype
->type
;
7493 case MONO_TYPE_BOOLEAN
:
7494 for (i
= 0; i
< alen
; i
++) {
7495 MonoBoolean val
= *p
++;
7496 mono_array_set (arr
, MonoBoolean
, i
, val
);
7499 case MONO_TYPE_CHAR
:
7502 for (i
= 0; i
< alen
; i
++) {
7503 guint16 val
= read16 (p
);
7504 mono_array_set (arr
, guint16
, i
, val
);
7511 for (i
= 0; i
< alen
; i
++) {
7512 guint32 val
= read32 (p
);
7513 mono_array_set (arr
, guint32
, i
, val
);
7518 for (i
= 0; i
< alen
; i
++) {
7521 mono_array_set (arr
, double, i
, val
);
7527 for (i
= 0; i
< alen
; i
++) {
7528 guint64 val
= read64 (p
);
7529 mono_array_set (arr
, guint64
, i
, val
);
7533 case MONO_TYPE_CLASS
:
7534 case MONO_TYPE_OBJECT
:
7535 case MONO_TYPE_STRING
:
7536 for (i
= 0; i
< alen
; i
++) {
7537 MonoObject
*item
= load_cattr_value (image
, &tklass
->byval_arg
, p
, &p
);
7538 mono_array_setref (arr
, i
, item
);
7542 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
7548 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
7554 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
)
7556 static MonoClass
*klass
;
7557 static MonoMethod
*ctor
;
7559 void *params
[2], *unboxed
;
7562 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeTypedArgument");
7564 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7566 params
[0] = mono_type_get_object (mono_domain_get (), t
);
7568 retval
= mono_object_new (mono_domain_get (), klass
);
7569 unboxed
= mono_object_unbox (retval
);
7570 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7576 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
)
7578 static MonoClass
*klass
;
7579 static MonoMethod
*ctor
;
7581 void *unboxed
, *params
[2];
7584 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeNamedArgument");
7586 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7589 params
[1] = typedarg
;
7590 retval
= mono_object_new (mono_domain_get (), klass
);
7591 unboxed
= mono_object_unbox (retval
);
7592 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7598 type_is_reference (MonoType
*type
)
7600 switch (type
->type
) {
7601 case MONO_TYPE_BOOLEAN
:
7602 case MONO_TYPE_CHAR
:
7615 case MONO_TYPE_VALUETYPE
:
7623 free_param_data (MonoMethodSignature
*sig
, void **params
) {
7625 for (i
= 0; i
< sig
->param_count
; ++i
) {
7626 if (!type_is_reference (sig
->params
[i
]))
7627 g_free (params
[i
]);
7632 * Find the field index in the metadata FieldDef table.
7635 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
7638 for (i
= 0; i
< klass
->field
.count
; ++i
) {
7639 if (field
== &klass
->fields
[i
])
7640 return klass
->field
.first
+ 1 + i
;
7646 * Find the property index in the metadata Property table.
7649 find_property_index (MonoClass
*klass
, MonoProperty
*property
) {
7652 for (i
= 0; i
< klass
->property
.count
; ++i
) {
7653 if (property
== &klass
->properties
[i
])
7654 return klass
->property
.first
+ 1 + i
;
7660 * Find the event index in the metadata Event table.
7663 find_event_index (MonoClass
*klass
, MonoEvent
*event
) {
7666 for (i
= 0; i
< klass
->event
.count
; ++i
) {
7667 if (event
== &klass
->events
[i
])
7668 return klass
->event
.first
+ 1 + i
;
7674 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
7676 const char *p
= (const char*)data
;
7678 guint32 i
, j
, num_named
;
7682 mono_class_init (method
->klass
);
7685 attr
= mono_object_new (mono_domain_get (), method
->klass
);
7686 mono_runtime_invoke (method
, attr
, NULL
, NULL
);
7690 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
7693 /*g_print ("got attr %s\n", method->klass->name);*/
7695 /* Allocate using alloca so it gets GC tracking */
7696 params
= alloca (mono_method_signature (method
)->param_count
* sizeof (void*));
7700 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
7701 params
[i
] = load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
7705 attr
= mono_object_new (mono_domain_get (), method
->klass
);
7706 mono_runtime_invoke (method
, attr
, params
, NULL
);
7707 free_param_data (method
->signature
, params
);
7708 num_named
= read16 (named
);
7710 for (j
= 0; j
< num_named
; j
++) {
7712 char *name
, named_type
, data_type
;
7713 named_type
= *named
++;
7714 data_type
= *named
++; /* type of data */
7715 if (data_type
== MONO_TYPE_SZARRAY
)
7716 data_type
= *named
++;
7717 if (data_type
== MONO_TYPE_ENUM
) {
7720 type_len
= mono_metadata_decode_blob_size (named
, &named
);
7721 type_name
= g_malloc (type_len
+ 1);
7722 memcpy (type_name
, named
, type_len
);
7723 type_name
[type_len
] = 0;
7725 /* FIXME: lookup the type and check type consistency */
7728 name_len
= mono_metadata_decode_blob_size (named
, &named
);
7729 name
= g_malloc (name_len
+ 1);
7730 memcpy (name
, named
, name_len
);
7731 name
[name_len
] = 0;
7733 if (named_type
== 0x53) {
7734 MonoClassField
*field
= mono_class_get_field_from_name (mono_object_class (attr
), name
);
7735 void *val
= load_cattr_value (image
, field
->type
, named
, &named
);
7736 mono_field_set_value (attr
, field
, val
);
7737 if (!type_is_reference (field
->type
))
7739 } else if (named_type
== 0x54) {
7742 MonoType
*prop_type
;
7744 prop
= mono_class_get_property_from_name (mono_object_class (attr
), name
);
7745 /* can we have more that 1 arg in a custom attr named property? */
7746 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
7747 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
7748 pparams
[0] = load_cattr_value (image
, prop_type
, named
, &named
);
7749 mono_property_set_value (prop
, attr
, pparams
, NULL
);
7750 if (!type_is_reference (prop_type
))
7751 g_free (pparams
[0]);
7760 create_custom_attr_data (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
7762 MonoArray
*typedargs
, *namedargs
;
7763 MonoClass
*attrklass
;
7764 static MonoMethod
*ctor
;
7767 const char *p
= (const char*)data
;
7769 guint32 i
, j
, num_named
;
7772 mono_class_init (method
->klass
);
7775 ctor
= mono_class_get_method_from_name (mono_defaults
.customattribute_data_class
, ".ctor", 3);
7777 domain
= mono_domain_get ();
7779 /* This is for Attributes with no parameters */
7780 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
7781 params
[0] = mono_method_get_object (domain
, method
, NULL
);
7782 params
[1] = params
[2] = NULL
;
7783 mono_runtime_invoke (method
, attr
, params
, NULL
);
7787 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
7790 typedargs
= mono_array_new (domain
, mono_get_object_class (), mono_method_signature (method
)->param_count
);
7794 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
7795 MonoObject
*obj
, *typedarg
;
7798 val
= load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
7799 obj
= type_is_reference (mono_method_signature (method
)->params
[i
]) ?
7800 val
: mono_value_box (domain
, mono_class_from_mono_type (mono_method_signature (method
)->params
[i
]), val
);
7801 typedarg
= create_cattr_typed_arg (mono_method_signature (method
)->params
[i
], obj
);
7802 mono_array_setref (typedargs
, i
, typedarg
);
7804 if (!type_is_reference (mono_method_signature (method
)->params
[i
]))
7809 num_named
= read16 (named
);
7810 namedargs
= mono_array_new (domain
, mono_get_object_class (), num_named
);
7812 attrklass
= method
->klass
;
7813 for (j
= 0; j
< num_named
; j
++) {
7815 char *name
, named_type
, data_type
;
7816 named_type
= *named
++;
7817 data_type
= *named
++; /* type of data */
7818 if (data_type
== MONO_TYPE_SZARRAY
)
7819 data_type
= *named
++;
7820 if (data_type
== MONO_TYPE_ENUM
) {
7823 type_len
= mono_metadata_decode_blob_size (named
, &named
);
7824 type_name
= g_malloc (type_len
+ 1);
7825 memcpy (type_name
, named
, type_len
);
7826 type_name
[type_len
] = 0;
7828 /* FIXME: lookup the type and check type consistency */
7831 name_len
= mono_metadata_decode_blob_size (named
, &named
);
7832 name
= g_malloc (name_len
+ 1);
7833 memcpy (name
, named
, name_len
);
7834 name
[name_len
] = 0;
7836 if (named_type
== 0x53) {
7837 MonoObject
*obj
, *typedarg
, *namedarg
;
7838 MonoClassField
*field
= mono_class_get_field_from_name (attrklass
, name
);
7839 void *minfo
, *val
= load_cattr_value (image
, field
->type
, named
, &named
);
7841 minfo
= mono_field_get_object (domain
, NULL
, field
);
7842 obj
= type_is_reference (field
->type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (field
->type
), val
);
7843 typedarg
= create_cattr_typed_arg (field
->type
, obj
);
7844 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
7845 mono_array_setref (namedargs
, j
, namedarg
);
7846 if (!type_is_reference (field
->type
))
7848 } else if (named_type
== 0x54) {
7849 MonoObject
*obj
, *typedarg
, *namedarg
;
7850 MonoType
*prop_type
;
7852 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
7854 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
7855 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
7856 minfo
= mono_property_get_object (domain
, NULL
, prop
);
7857 val
= load_cattr_value (image
, prop_type
, named
, &named
);
7858 obj
= type_is_reference (prop_type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (prop_type
), val
);
7859 typedarg
= create_cattr_typed_arg (prop_type
, obj
);
7860 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
7861 mono_array_setref (namedargs
, j
, namedarg
);
7862 if (!type_is_reference (prop_type
))
7867 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
7868 params
[0] = mono_method_get_object (domain
, method
, NULL
);
7869 params
[1] = typedargs
;
7870 params
[2] = namedargs
;
7871 mono_runtime_invoke (ctor
, attr
, params
, NULL
);
7876 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
7882 result
= mono_array_new (mono_domain_get (), mono_defaults
.attribute_class
, cinfo
->num_attrs
);
7883 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7884 if (!cinfo
->attrs
[i
].ctor
)
7885 /* The cattr type is not finished yet */
7886 /* We should include the type name but cinfo doesn't contain it */
7887 mono_raise_exception (mono_get_exception_type_load (NULL
, NULL
));
7888 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
7889 mono_array_setref (result
, i
, attr
);
7895 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
)
7902 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7903 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
))
7907 result
= mono_array_new (mono_domain_get (), mono_defaults
.attribute_class
, n
);
7909 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7910 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
)) {
7911 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
7912 mono_array_setref (result
, n
, attr
);
7920 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
)
7926 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, cinfo
->num_attrs
);
7927 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7928 attr
= create_custom_attr_data (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
7929 mono_array_setref (result
, i
, attr
);
7935 * mono_custom_attrs_from_index:
7937 * Returns: NULL if no attributes are found or if a loading error occurs.
7940 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
7942 guint32 mtoken
, i
, len
;
7943 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
7945 MonoCustomAttrInfo
*ainfo
;
7946 GList
*tmp
, *list
= NULL
;
7949 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
7951 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
7955 while (i
< ca
->rows
) {
7956 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
7958 list
= g_list_prepend (list
, GUINT_TO_POINTER (i
));
7961 len
= g_list_length (list
);
7964 ainfo
= g_malloc0 (sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (len
- MONO_ZERO_LEN_ARRAY
));
7965 ainfo
->num_attrs
= len
;
7966 ainfo
->image
= image
;
7967 for (i
= 0, tmp
= list
; i
< len
; ++i
, tmp
= tmp
->next
) {
7968 mono_metadata_decode_row (ca
, GPOINTER_TO_UINT (tmp
->data
), cols
, MONO_CUSTOM_ATTR_SIZE
);
7969 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
7970 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
7971 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
7972 mtoken
|= MONO_TOKEN_METHOD_DEF
;
7974 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
7975 mtoken
|= MONO_TOKEN_MEMBER_REF
;
7978 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
7981 ainfo
->attrs
[i
].ctor
= mono_get_method (image
, mtoken
, NULL
);
7982 if (!ainfo
->attrs
[i
].ctor
) {
7983 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image
->name
, mtoken
);
7988 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
7989 ainfo
->attrs
[i
].data_size
= mono_metadata_decode_value (data
, &data
);
7990 ainfo
->attrs
[i
].data
= (guchar
*)data
;
7998 mono_custom_attrs_from_method (MonoMethod
*method
)
8003 * An instantiated method has the same cattrs as the generic method definition.
8005 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8006 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8008 if (method
->is_inflated
)
8009 method
= ((MonoMethodInflated
*) method
)->declaring
;
8011 if (method
->dynamic
|| method
->klass
->image
->dynamic
)
8012 return lookup_custom_attr (method
->klass
->image
, method
);
8014 idx
= mono_method_get_index (method
);
8015 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8016 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
8017 return mono_custom_attrs_from_index (method
->klass
->image
, idx
);
8021 mono_custom_attrs_from_class (MonoClass
*klass
)
8025 if (klass
->generic_class
)
8026 klass
= klass
->generic_class
->container_class
;
8028 if (klass
->image
->dynamic
)
8029 return lookup_custom_attr (klass
->image
, klass
);
8031 if (klass
->byval_arg
.type
== MONO_TYPE_VAR
|| klass
->byval_arg
.type
== MONO_TYPE_MVAR
) {
8032 idx
= mono_metadata_token_index (klass
->sizes
.generic_param_token
);
8033 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8034 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
8036 idx
= mono_metadata_token_index (klass
->type_token
);
8037 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8038 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
8040 return mono_custom_attrs_from_index (klass
->image
, idx
);
8044 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
8048 if (assembly
->image
->dynamic
)
8049 return lookup_custom_attr (assembly
->image
, assembly
);
8050 idx
= 1; /* there is only one assembly */
8051 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8052 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
8053 return mono_custom_attrs_from_index (assembly
->image
, idx
);
8056 static MonoCustomAttrInfo
*
8057 mono_custom_attrs_from_module (MonoImage
*image
)
8062 return lookup_custom_attr (image
, image
);
8063 idx
= 1; /* there is only one module */
8064 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8065 idx
|= MONO_CUSTOM_ATTR_MODULE
;
8066 return mono_custom_attrs_from_index (image
, idx
);
8070 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
8074 if (klass
->image
->dynamic
) {
8075 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
8076 return lookup_custom_attr (klass
->image
, property
);
8078 idx
= find_property_index (klass
, property
);
8079 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8080 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
8081 return mono_custom_attrs_from_index (klass
->image
, idx
);
8085 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
8089 if (klass
->image
->dynamic
) {
8090 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
8091 return lookup_custom_attr (klass
->image
, event
);
8093 idx
= find_event_index (klass
, event
);
8094 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8095 idx
|= MONO_CUSTOM_ATTR_EVENT
;
8096 return mono_custom_attrs_from_index (klass
->image
, idx
);
8100 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
8103 if (klass
->image
->dynamic
) {
8104 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
8105 return lookup_custom_attr (klass
->image
, field
);
8107 idx
= find_field_index (klass
, field
);
8108 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8109 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
8110 return mono_custom_attrs_from_index (klass
->image
, idx
);
8114 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
8117 guint32 i
, idx
, method_index
;
8118 guint32 param_list
, param_last
, param_pos
, found
;
8120 MonoReflectionMethodAux
*aux
;
8123 * An instantiated method has the same cattrs as the generic method definition.
8125 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8126 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8128 if (method
->is_inflated
)
8129 method
= ((MonoMethodInflated
*) method
)->declaring
;
8131 if (method
->klass
->image
->dynamic
) {
8132 MonoCustomAttrInfo
*res
, *ainfo
;
8135 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
8136 if (!aux
|| !aux
->param_cattr
)
8139 /* Need to copy since it will be freed later */
8140 ainfo
= aux
->param_cattr
[param
];
8141 size
= sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (ainfo
->num_attrs
- MONO_ZERO_LEN_ARRAY
);
8142 res
= g_malloc0 (size
);
8143 memcpy (res
, ainfo
, size
);
8147 image
= method
->klass
->image
;
8148 method_index
= mono_method_get_index (method
);
8149 ca
= &image
->tables
[MONO_TABLE_METHOD
];
8151 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
8152 if (method_index
== ca
->rows
) {
8153 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8154 param_last
= ca
->rows
+ 1;
8156 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
8157 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8160 for (i
= param_list
; i
< param_last
; ++i
) {
8161 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
8162 if (param_pos
== param
) {
8170 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8171 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
8172 return mono_custom_attrs_from_index (image
, idx
);
8176 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8180 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8181 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8182 if (mono_class_has_parent (klass
, attr_klass
))
8189 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8196 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8197 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8198 if (mono_class_has_parent (klass
, attr_klass
)) {
8203 if (attr_index
== -1)
8206 attrs
= mono_custom_attrs_construct (ainfo
);
8208 return mono_array_get (attrs
, MonoObject
*, attr_index
);
8214 * mono_reflection_get_custom_attrs_info:
8215 * @obj: a reflection object handle
8217 * Return the custom attribute info for attributes defined for the
8218 * reflection handle @obj. The objects.
8221 mono_reflection_get_custom_attrs_info (MonoObject
*obj
)
8224 MonoCustomAttrInfo
*cinfo
= NULL
;
8226 klass
= obj
->vtable
->klass
;
8227 if (klass
== mono_defaults
.monotype_class
) {
8228 MonoReflectionType
*rtype
= (MonoReflectionType
*)obj
;
8229 klass
= mono_class_from_mono_type (rtype
->type
);
8230 cinfo
= mono_custom_attrs_from_class (klass
);
8231 } else if (strcmp ("Assembly", klass
->name
) == 0) {
8232 MonoReflectionAssembly
*rassembly
= (MonoReflectionAssembly
*)obj
;
8233 cinfo
= mono_custom_attrs_from_assembly (rassembly
->assembly
);
8234 } else if (strcmp ("Module", klass
->name
) == 0) {
8235 MonoReflectionModule
*module
= (MonoReflectionModule
*)obj
;
8236 cinfo
= mono_custom_attrs_from_module (module
->image
);
8237 } else if (strcmp ("MonoProperty", klass
->name
) == 0) {
8238 MonoReflectionProperty
*rprop
= (MonoReflectionProperty
*)obj
;
8239 cinfo
= mono_custom_attrs_from_property (rprop
->property
->parent
, rprop
->property
);
8240 } else if (strcmp ("MonoEvent", klass
->name
) == 0) {
8241 MonoReflectionEvent
*revent
= (MonoReflectionEvent
*)obj
;
8242 cinfo
= mono_custom_attrs_from_event (revent
->event
->parent
, revent
->event
);
8243 } else if (strcmp ("MonoField", klass
->name
) == 0) {
8244 MonoReflectionField
*rfield
= (MonoReflectionField
*)obj
;
8245 cinfo
= mono_custom_attrs_from_field (rfield
->field
->parent
, rfield
->field
);
8246 } else if ((strcmp ("MonoMethod", klass
->name
) == 0) || (strcmp ("MonoCMethod", klass
->name
) == 0)) {
8247 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8248 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8249 } else if ((strcmp ("MonoGenericMethod", klass
->name
) == 0) || (strcmp ("MonoGenericCMethod", klass
->name
) == 0)) {
8250 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8251 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8252 } else if (strcmp ("ParameterInfo", klass
->name
) == 0) {
8253 MonoReflectionParameter
*param
= (MonoReflectionParameter
*)obj
;
8254 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
8255 cinfo
= mono_custom_attrs_from_param (rmethod
->method
, param
->PositionImpl
+ 1);
8256 } else if (strcmp ("AssemblyBuilder", klass
->name
) == 0) {
8257 MonoReflectionAssemblyBuilder
*assemblyb
= (MonoReflectionAssemblyBuilder
*)obj
;
8258 cinfo
= mono_custom_attrs_from_builders (NULL
, assemblyb
->assembly
.assembly
->image
, assemblyb
->cattrs
);
8259 } else if (strcmp ("TypeBuilder", klass
->name
) == 0) {
8260 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
8261 cinfo
= mono_custom_attrs_from_builders (NULL
, &tb
->module
->dynamic_image
->image
, tb
->cattrs
);
8262 } else if (strcmp ("ModuleBuilder", klass
->name
) == 0) {
8263 MonoReflectionModuleBuilder
*mb
= (MonoReflectionModuleBuilder
*)obj
;
8264 cinfo
= mono_custom_attrs_from_builders (NULL
, &mb
->dynamic_image
->image
, mb
->cattrs
);
8265 } else if (strcmp ("ConstructorBuilder", klass
->name
) == 0) {
8266 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
8267 cinfo
= mono_custom_attrs_from_builders (NULL
, cb
->mhandle
->klass
->image
, cb
->cattrs
);
8268 } else if (strcmp ("MethodBuilder", klass
->name
) == 0) {
8269 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
8270 cinfo
= mono_custom_attrs_from_builders (NULL
, mb
->mhandle
->klass
->image
, mb
->cattrs
);
8271 } else if (strcmp ("FieldBuilder", klass
->name
) == 0) {
8272 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
8273 cinfo
= mono_custom_attrs_from_builders (NULL
, &((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
->image
, fb
->cattrs
);
8274 } else if (strcmp ("MonoGenericClass", klass
->name
) == 0) {
8275 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)obj
;
8276 cinfo
= mono_reflection_get_custom_attrs_info ((MonoObject
*)gclass
->generic_type
);
8277 } else { /* handle other types here... */
8278 g_error ("get custom attrs not yet supported for %s", klass
->name
);
8285 * mono_reflection_get_custom_attrs_by_type:
8286 * @obj: a reflection object handle
8288 * Return an array with all the custom attributes defined of the
8289 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8290 * of that type are returned. The objects are fully build. Return NULL if a loading error
8294 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj
, MonoClass
*attr_klass
)
8297 MonoCustomAttrInfo
*cinfo
;
8299 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8302 result
= mono_custom_attrs_construct_by_type (cinfo
, attr_klass
);
8304 result
= mono_custom_attrs_construct (cinfo
);
8306 mono_custom_attrs_free (cinfo
);
8308 if (mono_loader_get_last_error ())
8310 result
= mono_array_new (mono_domain_get (), mono_defaults
.attribute_class
, 0);
8317 * mono_reflection_get_custom_attrs:
8318 * @obj: a reflection object handle
8320 * Return an array with all the custom attributes defined of the
8321 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8325 mono_reflection_get_custom_attrs (MonoObject
*obj
)
8327 return mono_reflection_get_custom_attrs_by_type (obj
, NULL
);
8331 * mono_reflection_get_custom_attrs_data:
8332 * @obj: a reflection obj handle
8334 * Returns an array of System.Reflection.CustomAttributeData,
8335 * which include information about attributes reflected on
8336 * types loaded using the Reflection Only methods
8339 mono_reflection_get_custom_attrs_data (MonoObject
*obj
)
8342 MonoCustomAttrInfo
*cinfo
;
8344 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8346 result
= mono_custom_attrs_data_construct (cinfo
);
8348 mono_custom_attrs_free (cinfo
);
8350 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, 0);
8355 static MonoReflectionType
*
8356 mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
)
8358 MonoMethod
*method_get_underlying_system_type
;
8360 method_get_underlying_system_type
= mono_object_get_virtual_method ((MonoObject
*) t
,
8361 mono_class_get_method_from_name (mono_object_class (t
),
8362 "get_UnderlyingSystemType",
8364 return (MonoReflectionType
*) mono_runtime_invoke (method_get_underlying_system_type
, t
, NULL
, NULL
);
8368 mono_reflection_type_get_handle (MonoReflectionType
* t
)
8373 t
= mono_reflection_type_get_underlying_system_type (t
);
8381 * LOCKING: Assumes the loader lock is held.
8383 static MonoMethodSignature
*
8384 parameters_to_signature (MonoMemPool
*mp
, MonoArray
*parameters
) {
8385 MonoMethodSignature
*sig
;
8388 count
= parameters
? mono_array_length (parameters
): 0;
8390 sig
= mp_g_malloc0 (mp
, sizeof (MonoMethodSignature
) + sizeof (MonoType
*) * count
);
8391 sig
->param_count
= count
;
8392 sig
->sentinelpos
= -1; /* FIXME */
8393 for (i
= 0; i
< count
; ++i
) {
8394 MonoReflectionType
*pt
= mono_array_get (parameters
, MonoReflectionType
*, i
);
8395 sig
->params
[i
] = mono_reflection_type_get_handle (pt
);
8401 * LOCKING: Assumes the loader lock is held.
8403 static MonoMethodSignature
*
8404 ctor_builder_to_signature (MonoMemPool
*mp
, MonoReflectionCtorBuilder
*ctor
) {
8405 MonoMethodSignature
*sig
;
8407 sig
= parameters_to_signature (mp
, ctor
->parameters
);
8408 sig
->hasthis
= ctor
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8409 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
8414 * LOCKING: Assumes the loader lock is held.
8416 static MonoMethodSignature
*
8417 method_builder_to_signature (MonoMemPool
*mp
, MonoReflectionMethodBuilder
*method
) {
8418 MonoMethodSignature
*sig
;
8420 sig
= parameters_to_signature (mp
, method
->parameters
);
8421 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8422 sig
->ret
= method
->rtype
? method
->rtype
->type
: &mono_defaults
.void_class
->byval_arg
;
8423 sig
->generic_param_count
= method
->generic_params
? mono_array_length (method
->generic_params
) : 0;
8427 static MonoMethodSignature
*
8428 dynamic_method_to_signature (MonoReflectionDynamicMethod
*method
) {
8429 MonoMethodSignature
*sig
;
8431 sig
= parameters_to_signature (NULL
, method
->parameters
);
8432 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8433 sig
->ret
= method
->rtype
? method
->rtype
->type
: &mono_defaults
.void_class
->byval_arg
;
8434 sig
->generic_param_count
= 0;
8439 get_prop_name_and_type (MonoObject
*prop
, char **name
, MonoType
**type
)
8441 MonoClass
*klass
= mono_object_class (prop
);
8442 if (strcmp (klass
->name
, "PropertyBuilder") == 0) {
8443 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*)prop
;
8444 *name
= mono_string_to_utf8 (pb
->name
);
8445 *type
= pb
->type
->type
;
8447 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)prop
;
8448 *name
= g_strdup (p
->property
->name
);
8449 if (p
->property
->get
)
8450 *type
= mono_method_signature (p
->property
->get
)->ret
;
8452 *type
= mono_method_signature (p
->property
->set
)->params
[mono_method_signature (p
->property
->set
)->param_count
- 1];
8457 get_field_name_and_type (MonoObject
*field
, char **name
, MonoType
**type
)
8459 MonoClass
*klass
= mono_object_class (field
);
8460 if (strcmp (klass
->name
, "FieldBuilder") == 0) {
8461 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)field
;
8462 *name
= mono_string_to_utf8 (fb
->name
);
8463 *type
= fb
->type
->type
;
8465 MonoReflectionField
*f
= (MonoReflectionField
*)field
;
8466 *name
= g_strdup (mono_field_get_name (f
->field
));
8467 *type
= f
->field
->type
;
8472 * Encode a value in a custom attribute stream of bytes.
8473 * The value to encode is either supplied as an object in argument val
8474 * (valuetypes are boxed), or as a pointer to the data in the
8476 * @type represents the type of the value
8477 * @buffer is the start of the buffer
8478 * @p the current position in the buffer
8479 * @buflen contains the size of the buffer and is used to return the new buffer size
8480 * if this needs to be realloced.
8481 * @retbuffer and @retp return the start and the position of the buffer
8484 encode_cattr_value (MonoAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, MonoObject
*arg
, char *argval
)
8486 MonoTypeEnum simple_type
;
8488 if ((p
-buffer
) + 10 >= *buflen
) {
8491 newbuf
= g_realloc (buffer
, *buflen
);
8492 p
= newbuf
+ (p
-buffer
);
8496 argval
= ((char*)arg
+ sizeof (MonoObject
));
8497 simple_type
= type
->type
;
8499 switch (simple_type
) {
8500 case MONO_TYPE_BOOLEAN
:
8505 case MONO_TYPE_CHAR
:
8508 swap_with_size (p
, argval
, 2, 1);
8514 swap_with_size (p
, argval
, 4, 1);
8518 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8528 swap_with_size (p
, argval
, 8, 1);
8534 swap_with_size (p
, argval
, 8, 1);
8537 case MONO_TYPE_VALUETYPE
:
8538 if (type
->data
.klass
->enumtype
) {
8539 simple_type
= type
->data
.klass
->enum_basetype
->type
;
8542 g_warning ("generic valutype %s not handled in custom attr value decoding", type
->data
.klass
->name
);
8545 case MONO_TYPE_STRING
: {
8552 str
= mono_string_to_utf8 ((MonoString
*)arg
);
8553 slen
= strlen (str
);
8554 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8558 newbuf
= g_realloc (buffer
, *buflen
);
8559 p
= newbuf
+ (p
-buffer
);
8562 mono_metadata_encode_value (slen
, p
, &p
);
8563 memcpy (p
, str
, slen
);
8568 case MONO_TYPE_CLASS
: {
8576 k
= mono_object_class (arg
);
8577 if (!mono_object_isinst (arg
, mono_defaults
.monotype_class
) &&
8578 (strcmp (k
->name
, "TypeBuilder") || strcmp (k
->name_space
, "System.Reflection.Emit"))) {
8579 MonoReflectionType
* rt
= mono_reflection_type_get_underlying_system_type ((MonoReflectionType
*) arg
);
8582 if (rt
&& (rtc
= mono_object_class (rt
)) &&
8583 (mono_object_isinst ((MonoObject
*) rt
, mono_defaults
.monotype_class
) ||
8584 !strcmp (rtc
->name
, "TypeBuilder") || !strcmp (rtc
->name_space
, "System.Reflection.Emit"))) {
8585 arg
= (MonoObject
*) rt
;
8588 g_error ("Only System.Type allowed, not %s.%s", k
->name_space
, k
->name
);
8591 str
= type_get_qualified_name (((MonoReflectionType
*)arg
)->type
, NULL
);
8592 slen
= strlen (str
);
8593 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8597 newbuf
= g_realloc (buffer
, *buflen
);
8598 p
= newbuf
+ (p
-buffer
);
8601 mono_metadata_encode_value (slen
, p
, &p
);
8602 memcpy (p
, str
, slen
);
8607 case MONO_TYPE_SZARRAY
: {
8609 MonoClass
*eclass
, *arg_eclass
;
8612 *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff;
8615 len
= mono_array_length ((MonoArray
*)arg
);
8617 *p
++ = (len
>> 8) & 0xff;
8618 *p
++ = (len
>> 16) & 0xff;
8619 *p
++ = (len
>> 24) & 0xff;
8621 *retbuffer
= buffer
;
8622 eclass
= type
->data
.klass
;
8623 arg_eclass
= mono_object_class (arg
)->element_class
;
8626 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8627 eclass
= mono_defaults
.object_class
;
8629 if (eclass
== mono_defaults
.object_class
&& arg_eclass
->valuetype
) {
8630 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
8631 int elsize
= mono_class_array_element_size (arg_eclass
);
8632 for (i
= 0; i
< len
; ++i
) {
8633 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &arg_eclass
->byval_arg
, NULL
, elptr
);
8636 } else if (eclass
->valuetype
&& arg_eclass
->valuetype
) {
8637 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
8638 int elsize
= mono_class_array_element_size (eclass
);
8639 for (i
= 0; i
< len
; ++i
) {
8640 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, NULL
, elptr
);
8644 for (i
= 0; i
< len
; ++i
) {
8645 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, mono_array_get ((MonoArray
*)arg
, MonoObject
*, i
), NULL
);
8650 case MONO_TYPE_OBJECT
: {
8656 * The parameter type is 'object' but the type of the actual
8657 * argument is not. So we have to add type information to the blob
8658 * too. This is completely undocumented in the spec.
8662 *p
++ = MONO_TYPE_STRING
; // It's same hack as MS uses
8667 klass
= mono_object_class (arg
);
8669 if (mono_object_isinst (arg
, mono_defaults
.systemtype_class
)) {
8672 } else if (klass
->enumtype
) {
8674 } else if (klass
== mono_defaults
.string_class
) {
8675 simple_type
= MONO_TYPE_STRING
;
8678 } else if (klass
->rank
== 1) {
8680 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_OBJECT
)
8681 /* See Partition II, Appendix B3 */
8684 *p
++ = klass
->element_class
->byval_arg
.type
;
8685 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &klass
->byval_arg
, arg
, NULL
);
8687 } else if (klass
->byval_arg
.type
>= MONO_TYPE_BOOLEAN
&& klass
->byval_arg
.type
<= MONO_TYPE_R8
) {
8688 *p
++ = simple_type
= klass
->byval_arg
.type
;
8691 g_error ("unhandled type in custom attr");
8693 str
= type_get_qualified_name (mono_class_get_type(klass
), NULL
);
8694 slen
= strlen (str
);
8695 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8699 newbuf
= g_realloc (buffer
, *buflen
);
8700 p
= newbuf
+ (p
-buffer
);
8703 mono_metadata_encode_value (slen
, p
, &p
);
8704 memcpy (p
, str
, slen
);
8707 simple_type
= klass
->enum_basetype
->type
;
8711 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type
);
8714 *retbuffer
= buffer
;
8718 encode_field_or_prop_type (MonoType
*type
, char *p
, char **retp
)
8720 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
8721 char *str
= type_get_qualified_name (type
, NULL
);
8722 int slen
= strlen (str
);
8726 * This seems to be optional...
8729 mono_metadata_encode_value (slen
, p
, &p
);
8730 memcpy (p
, str
, slen
);
8733 } else if (type
->type
== MONO_TYPE_OBJECT
) {
8735 } else if (type
->type
== MONO_TYPE_CLASS
) {
8736 /* it should be a type: encode_cattr_value () has the check */
8739 mono_metadata_encode_value (type
->type
, p
, &p
);
8740 if (type
->type
== MONO_TYPE_SZARRAY
)
8741 /* See the examples in Partition VI, Annex B */
8742 encode_field_or_prop_type (&type
->data
.klass
->byval_arg
, p
, &p
);
8749 encode_named_val (MonoReflectionAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, char *name
, MonoObject
*value
)
8752 /* Preallocate a large enough buffer */
8753 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
8754 char *str
= type_get_qualified_name (type
, NULL
);
8757 } else if (type
->type
== MONO_TYPE_SZARRAY
&& type
->data
.klass
->enumtype
) {
8758 char *str
= type_get_qualified_name (&type
->data
.klass
->byval_arg
, NULL
);
8764 len
+= strlen (name
);
8766 if ((p
-buffer
) + 20 + len
>= *buflen
) {
8770 newbuf
= g_realloc (buffer
, *buflen
);
8771 p
= newbuf
+ (p
-buffer
);
8775 encode_field_or_prop_type (type
, p
, &p
);
8777 len
= strlen (name
);
8778 mono_metadata_encode_value (len
, p
, &p
);
8779 memcpy (p
, name
, len
);
8781 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, buflen
, type
, value
, NULL
);
8783 *retbuffer
= buffer
;
8786 #ifndef DISABLE_REFLECTION_EMIT
8789 * mono_reflection_get_custom_attrs_blob:
8790 * @ctor: custom attribute constructor
8791 * @ctorArgs: arguments o the constructor
8797 * Creates the blob of data that needs to be saved in the metadata and that represents
8798 * the custom attributed described by @ctor, @ctorArgs etc.
8799 * Returns: a Byte array representing the blob of data.
8802 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
8805 MonoMethodSignature
*sig
;
8810 MONO_ARCH_SAVE_REGS
;
8812 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
8813 /* sig is freed later so allocate it in the heap */
8814 sig
= ctor_builder_to_signature (NULL
, (MonoReflectionCtorBuilder
*)ctor
);
8816 sig
= mono_method_signature (((MonoReflectionMethod
*)ctor
)->method
);
8819 g_assert (mono_array_length (ctorArgs
) == sig
->param_count
);
8821 p
= buffer
= g_malloc (buflen
);
8822 /* write the prolog */
8825 for (i
= 0; i
< sig
->param_count
; ++i
) {
8826 arg
= mono_array_get (ctorArgs
, MonoObject
*, i
);
8827 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, &buflen
, sig
->params
[i
], arg
, NULL
);
8831 i
+= mono_array_length (properties
);
8833 i
+= mono_array_length (fields
);
8835 *p
++ = (i
>> 8) & 0xff;
8838 for (i
= 0; i
< mono_array_length (properties
); ++i
) {
8842 prop
= mono_array_get (properties
, gpointer
, i
);
8843 get_prop_name_and_type (prop
, &pname
, &ptype
);
8844 *p
++ = 0x54; /* PROPERTY signature */
8845 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ptype
, pname
, (MonoObject
*)mono_array_get (propValues
, gpointer
, i
));
8852 for (i
= 0; i
< mono_array_length (fields
); ++i
) {
8856 field
= mono_array_get (fields
, gpointer
, i
);
8857 get_field_name_and_type (field
, &fname
, &ftype
);
8858 *p
++ = 0x53; /* FIELD signature */
8859 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ftype
, fname
, (MonoObject
*)mono_array_get (fieldValues
, gpointer
, i
));
8864 g_assert (p
- buffer
<= buflen
);
8865 buflen
= p
- buffer
;
8866 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
8867 p
= mono_array_addr (result
, char, 0);
8868 memcpy (p
, buffer
, buflen
);
8870 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod"))
8876 * mono_reflection_setup_internal_class:
8877 * @tb: a TypeBuilder object
8879 * Creates a MonoClass that represents the TypeBuilder.
8880 * This is a trick that lets us simplify a lot of reflection code
8881 * (and will allow us to support Build and Run assemblies easier).
8884 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
8886 MonoClass
*klass
, *parent
;
8888 MONO_ARCH_SAVE_REGS
;
8890 mono_loader_lock ();
8893 /* check so we can compile corlib correctly */
8894 if (strcmp (mono_object_class (tb
->parent
)->name
, "TypeBuilder") == 0) {
8895 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8896 parent
= tb
->parent
->type
->data
.klass
;
8898 parent
= my_mono_class_from_mono_type (tb
->parent
->type
);
8904 /* the type has already being created: it means we just have to change the parent */
8905 if (tb
->type
.type
) {
8906 klass
= mono_class_from_mono_type (tb
->type
.type
);
8907 klass
->parent
= NULL
;
8908 /* fool mono_class_setup_parent */
8909 klass
->supertypes
= NULL
;
8910 mono_class_setup_parent (klass
, parent
);
8911 mono_class_setup_mono_type (klass
);
8912 mono_loader_unlock ();
8916 klass
= mono_image_alloc0 (&tb
->module
->dynamic_image
->image
, sizeof (MonoClass
));
8918 klass
->image
= &tb
->module
->dynamic_image
->image
;
8920 klass
->inited
= 1; /* we lie to the runtime */
8921 klass
->name
= mono_string_to_utf8_mp (klass
->image
->mempool
, tb
->name
);
8922 klass
->name_space
= mono_string_to_utf8_mp (klass
->image
->mempool
, tb
->nspace
);
8923 klass
->type_token
= MONO_TOKEN_TYPE_DEF
| tb
->table_idx
;
8924 klass
->flags
= tb
->attrs
;
8926 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
8928 klass
->element_class
= klass
;
8930 MOVING_GC_REGISTER (&klass
->reflection_info
);
8931 klass
->reflection_info
= tb
;
8933 /* Put into cache so mono_class_get () will find it */
8934 mono_image_add_to_name_cache (klass
->image
, klass
->name_space
, klass
->name
, tb
->table_idx
);
8936 mono_g_hash_table_insert (tb
->module
->dynamic_image
->tokens
,
8937 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF
| tb
->table_idx
), tb
);
8939 if (parent
!= NULL
) {
8940 mono_class_setup_parent (klass
, parent
);
8941 } else if (strcmp (klass
->name
, "Object") == 0 && strcmp (klass
->name_space
, "System") == 0) {
8942 const char *old_n
= klass
->name
;
8943 /* trick to get relative numbering right when compiling corlib */
8944 klass
->name
= "BuildingObject";
8945 mono_class_setup_parent (klass
, mono_defaults
.object_class
);
8946 klass
->name
= old_n
;
8949 if ((!strcmp (klass
->name
, "ValueType") && !strcmp (klass
->name_space
, "System")) ||
8950 (!strcmp (klass
->name
, "Object") && !strcmp (klass
->name_space
, "System")) ||
8951 (!strcmp (klass
->name
, "Enum") && !strcmp (klass
->name_space
, "System"))) {
8952 klass
->instance_size
= sizeof (MonoObject
);
8953 klass
->size_inited
= 1;
8954 mono_class_setup_vtable_general (klass
, NULL
, 0);
8957 mono_class_setup_mono_type (klass
);
8959 mono_class_setup_supertypes (klass
);
8962 * FIXME: handle interfaces.
8965 tb
->type
.type
= &klass
->byval_arg
;
8967 if (tb
->nesting_type
) {
8968 g_assert (tb
->nesting_type
->type
);
8969 klass
->nested_in
= mono_class_from_mono_type (tb
->nesting_type
->type
);
8972 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
8974 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
8976 mono_loader_unlock ();
8980 * mono_reflection_setup_generic_class:
8981 * @tb: a TypeBuilder object
8983 * Setup the generic class before adding the first generic parameter.
8986 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
8991 * mono_reflection_create_generic_class:
8992 * @tb: a TypeBuilder object
8994 * Creates the generic class after all generic parameters have been added.
8997 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
9002 MONO_ARCH_SAVE_REGS
;
9004 klass
= my_mono_class_from_mono_type (tb
->type
.type
);
9006 count
= tb
->generic_params
? mono_array_length (tb
->generic_params
) : 0;
9008 if (klass
->generic_container
|| (count
== 0))
9011 g_assert (tb
->generic_container
&& (tb
->generic_container
->owner
.klass
== klass
));
9013 klass
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
9015 klass
->generic_container
->owner
.klass
= klass
;
9016 klass
->generic_container
->type_argc
= count
;
9017 klass
->generic_container
->type_params
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericParam
) * count
);
9019 for (i
= 0; i
< count
; i
++) {
9020 MonoReflectionGenericParam
*gparam
= mono_array_get (tb
->generic_params
, gpointer
, i
);
9021 klass
->generic_container
->type_params
[i
] = *gparam
->type
.type
->data
.generic_param
;
9022 /*Make sure we are a diferent type instance */
9023 klass
->generic_container
->type_params
[i
].owner
= klass
->generic_container
;
9024 klass
->generic_container
->type_params
[i
].pklass
= NULL
;
9026 g_assert (klass
->generic_container
->type_params
[i
].owner
);
9029 klass
->generic_container
->context
.class_inst
= mono_get_shared_generic_inst (klass
->generic_container
);
9033 * mono_reflection_create_internal_class:
9034 * @tb: a TypeBuilder object
9036 * Actually create the MonoClass that is associated with the TypeBuilder.
9039 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
9043 MONO_ARCH_SAVE_REGS
;
9045 klass
= my_mono_class_from_mono_type (tb
->type
.type
);
9047 mono_loader_lock ();
9048 if (klass
->enumtype
&& klass
->enum_basetype
== NULL
) {
9049 MonoReflectionFieldBuilder
*fb
;
9052 g_assert (tb
->fields
!= NULL
);
9053 g_assert (mono_array_length (tb
->fields
) >= 1);
9055 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, 0);
9057 if (!mono_type_is_valid_enum_basetype (fb
->type
->type
)) {
9058 mono_loader_unlock ();
9062 klass
->enum_basetype
= fb
->type
->type
;
9063 klass
->element_class
= my_mono_class_from_mono_type (klass
->enum_basetype
);
9064 if (!klass
->element_class
)
9065 klass
->element_class
= mono_class_from_mono_type (klass
->enum_basetype
);
9068 * get the element_class from the current corlib.
9070 ec
= default_class_from_mono_type (klass
->enum_basetype
);
9071 klass
->instance_size
= ec
->instance_size
;
9072 klass
->size_inited
= 1;
9074 * this is almost safe to do with enums and it's needed to be able
9075 * to create objects of the enum type (for use in SetConstant).
9077 /* FIXME: Does this mean enums can't have method overrides ? */
9078 mono_class_setup_vtable_general (klass
, NULL
, 0);
9080 mono_loader_unlock ();
9083 #endif /* DISABLE_REFLECTION_EMIT */
9085 static MonoMarshalSpec
*
9086 mono_marshal_spec_from_builder (MonoMemPool
*mp
, MonoAssembly
*assembly
,
9087 MonoReflectionMarshal
*minfo
)
9089 MonoMarshalSpec
*res
;
9091 res
= mp_g_new0 (mp
, MonoMarshalSpec
, 1);
9092 res
->native
= minfo
->type
;
9094 switch (minfo
->type
) {
9095 case MONO_NATIVE_LPARRAY
:
9096 res
->data
.array_data
.elem_type
= minfo
->eltype
;
9097 if (minfo
->has_size
) {
9098 res
->data
.array_data
.param_num
= minfo
->param_num
;
9099 res
->data
.array_data
.num_elem
= minfo
->count
;
9100 res
->data
.array_data
.elem_mult
= minfo
->param_num
== -1 ? 0 : 1;
9103 res
->data
.array_data
.param_num
= -1;
9104 res
->data
.array_data
.num_elem
= -1;
9105 res
->data
.array_data
.elem_mult
= -1;
9109 case MONO_NATIVE_BYVALTSTR
:
9110 case MONO_NATIVE_BYVALARRAY
:
9111 res
->data
.array_data
.num_elem
= minfo
->count
;
9114 case MONO_NATIVE_CUSTOM
:
9115 if (minfo
->marshaltyperef
)
9116 res
->data
.custom_data
.custom_name
=
9117 type_get_fully_qualified_name (minfo
->marshaltyperef
->type
);
9119 res
->data
.custom_data
.cookie
= mono_string_to_utf8 (minfo
->mcookie
);
9129 MonoReflectionMarshal
*
9130 mono_reflection_marshal_from_marshal_spec (MonoDomain
*domain
, MonoClass
*klass
,
9131 MonoMarshalSpec
*spec
)
9133 static MonoClass
*System_Reflection_Emit_UnmanagedMarshalClass
;
9134 MonoReflectionMarshal
*minfo
;
9137 if (!System_Reflection_Emit_UnmanagedMarshalClass
) {
9138 System_Reflection_Emit_UnmanagedMarshalClass
= mono_class_from_name (
9139 mono_defaults
.corlib
, "System.Reflection.Emit", "UnmanagedMarshal");
9140 g_assert (System_Reflection_Emit_UnmanagedMarshalClass
);
9143 minfo
= (MonoReflectionMarshal
*)mono_object_new (domain
, System_Reflection_Emit_UnmanagedMarshalClass
);
9144 minfo
->type
= spec
->native
;
9146 switch (minfo
->type
) {
9147 case MONO_NATIVE_LPARRAY
:
9148 minfo
->eltype
= spec
->data
.array_data
.elem_type
;
9149 minfo
->count
= spec
->data
.array_data
.num_elem
;
9150 minfo
->param_num
= spec
->data
.array_data
.param_num
;
9153 case MONO_NATIVE_BYVALTSTR
:
9154 case MONO_NATIVE_BYVALARRAY
:
9155 minfo
->count
= spec
->data
.array_data
.num_elem
;
9158 case MONO_NATIVE_CUSTOM
:
9159 if (spec
->data
.custom_data
.custom_name
) {
9160 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, klass
->image
);
9162 MONO_OBJECT_SETREF (minfo
, marshaltyperef
, mono_type_get_object (domain
, mtype
));
9164 MONO_OBJECT_SETREF (minfo
, marshaltype
, mono_string_new (domain
, spec
->data
.custom_data
.custom_name
));
9166 if (spec
->data
.custom_data
.cookie
)
9167 MONO_OBJECT_SETREF (minfo
, mcookie
, mono_string_new (domain
, spec
->data
.custom_data
.cookie
));
9178 reflection_methodbuilder_to_mono_method (MonoClass
*klass
,
9179 ReflectionMethodBuilder
*rmb
,
9180 MonoMethodSignature
*sig
)
9183 MonoMethodNormal
*pm
;
9184 MonoMarshalSpec
**specs
;
9185 MonoReflectionMethodAux
*method_aux
;
9191 * Methods created using a MethodBuilder should have their memory allocated
9192 * inside the image mempool, while dynamic methods should have their memory
9195 dynamic
= rmb
->refs
!= NULL
;
9196 mp
= dynamic
? NULL
: klass
->image
->mempool
;
9199 g_assert (!klass
->generic_class
);
9201 mono_loader_lock ();
9203 if ((rmb
->attrs
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
9204 (rmb
->iattrs
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
))
9205 m
= (MonoMethod
*)mp_g_new0 (mp
, MonoMethodPInvoke
, 1);
9207 m
= (MonoMethod
*)mp_g_new0 (mp
, MonoMethodWrapper
, 1);
9209 m
= (MonoMethod
*)mp_g_new0 (mp
, MonoMethodNormal
, 1);
9211 pm
= (MonoMethodNormal
*)m
;
9213 m
->dynamic
= dynamic
;
9215 m
->flags
= rmb
->attrs
;
9216 m
->iflags
= rmb
->iattrs
;
9217 m
->name
= mp_string_to_utf8 (mp
, rmb
->name
);
9220 m
->skip_visibility
= rmb
->skip_visibility
;
9222 m
->token
= MONO_TOKEN_METHOD_DEF
| (*rmb
->table_idx
);
9224 if (m
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) {
9225 if (klass
== mono_defaults
.string_class
&& !strcmp (m
->name
, ".ctor"))
9228 m
->signature
->pinvoke
= 1;
9229 } else if (m
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
9230 m
->signature
->pinvoke
= 1;
9232 method_aux
= mp_g_new0 (mp
, MonoReflectionMethodAux
, 1);
9234 method_aux
->dllentry
= rmb
->dllentry
? mono_string_to_utf8_mp (mp
, rmb
->dllentry
) : mono_mempool_strdup (mp
, m
->name
);
9235 method_aux
->dll
= mono_string_to_utf8_mp (mp
, rmb
->dll
);
9237 ((MonoMethodPInvoke
*)m
)->piflags
= (rmb
->native_cc
<< 8) | (rmb
->charset
? (rmb
->charset
- 1) * 2 : 0) | rmb
->extra_flags
;
9239 if (klass
->image
->dynamic
)
9240 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
9242 mono_loader_unlock ();
9245 } else if (!(m
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) &&
9246 !(m
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
9247 MonoMethodHeader
*header
;
9249 gint32 max_stack
, i
;
9250 gint32 num_locals
= 0;
9251 gint32 num_clauses
= 0;
9255 code
= mono_array_addr (rmb
->ilgen
->code
, guint8
, 0);
9256 code_size
= rmb
->ilgen
->code_len
;
9257 max_stack
= rmb
->ilgen
->max_stack
;
9258 num_locals
= rmb
->ilgen
->locals
? mono_array_length (rmb
->ilgen
->locals
) : 0;
9259 if (rmb
->ilgen
->ex_handlers
)
9260 num_clauses
= method_count_clauses (rmb
->ilgen
);
9263 code
= mono_array_addr (rmb
->code
, guint8
, 0);
9264 code_size
= mono_array_length (rmb
->code
);
9265 /* we probably need to run a verifier on the code... */
9275 header
= mp_g_malloc0 (mp
, sizeof (MonoMethodHeader
) +
9276 (num_locals
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoType
*));
9277 header
->code_size
= code_size
;
9278 header
->code
= mp_g_malloc (mp
, code_size
);
9279 memcpy ((char*)header
->code
, code
, code_size
);
9280 header
->max_stack
= max_stack
;
9281 header
->init_locals
= rmb
->init_locals
;
9282 header
->num_locals
= num_locals
;
9284 for (i
= 0; i
< num_locals
; ++i
) {
9285 MonoReflectionLocalBuilder
*lb
=
9286 mono_array_get (rmb
->ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
9288 header
->locals
[i
] = mp_g_new0 (mp
, MonoType
, 1);
9289 memcpy (header
->locals
[i
], lb
->type
->type
, sizeof (MonoType
));
9292 header
->num_clauses
= num_clauses
;
9294 header
->clauses
= method_encode_clauses (mp
, (MonoDynamicImage
*)klass
->image
,
9295 rmb
->ilgen
, num_clauses
);
9298 pm
->header
= header
;
9301 if (rmb
->generic_params
) {
9302 int count
= mono_array_length (rmb
->generic_params
);
9303 MonoGenericContainer
*container
;
9305 container
= rmb
->generic_container
;
9307 m
->is_generic
= TRUE
;
9308 mono_method_set_generic_container (m
, container
);
9310 container
->type_argc
= count
;
9311 container
->type_params
= mp_g_new0 (mp
, MonoGenericParam
, count
);
9312 container
->owner
.method
= m
;
9314 for (i
= 0; i
< count
; i
++) {
9315 MonoReflectionGenericParam
*gp
=
9316 mono_array_get (rmb
->generic_params
, MonoReflectionGenericParam
*, i
);
9318 container
->type_params
[i
] = *gp
->type
.type
->data
.generic_param
;
9321 if (klass
->generic_container
) {
9322 container
->parent
= klass
->generic_container
;
9323 container
->context
.class_inst
= klass
->generic_container
->context
.class_inst
;
9325 container
->context
.method_inst
= mono_get_shared_generic_inst (container
);
9329 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)m
;
9333 m
->wrapper_type
= MONO_WRAPPER_DYNAMIC_METHOD
;
9335 mw
->method_data
= data
= mp_g_new (mp
, gpointer
, rmb
->nrefs
+ 1);
9336 data
[0] = GUINT_TO_POINTER (rmb
->nrefs
);
9337 for (i
= 0; i
< rmb
->nrefs
; ++i
)
9338 data
[i
+ 1] = rmb
->refs
[i
];
9343 /* Parameter info */
9346 method_aux
= mp_g_new0 (mp
, MonoReflectionMethodAux
, 1);
9347 method_aux
->param_names
= mp_g_new0 (mp
, char *, mono_method_signature (m
)->param_count
+ 1);
9348 for (i
= 0; i
<= m
->signature
->param_count
; ++i
) {
9349 MonoReflectionParamBuilder
*pb
;
9350 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
9351 if ((i
> 0) && (pb
->attrs
)) {
9352 /* Make a copy since it might point to a shared type structure */
9353 m
->signature
->params
[i
- 1] = mono_metadata_type_dup (mp
, m
->signature
->params
[i
- 1]);
9354 m
->signature
->params
[i
- 1]->attrs
= pb
->attrs
;
9357 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
9358 MonoDynamicImage
*assembly
;
9359 guint32 idx
, def_type
, len
;
9363 if (!method_aux
->param_defaults
) {
9364 method_aux
->param_defaults
= mp_g_new0 (mp
, guint8
*, m
->signature
->param_count
+ 1);
9365 method_aux
->param_default_types
= mp_g_new0 (mp
, guint32
, m
->signature
->param_count
+ 1);
9367 assembly
= (MonoDynamicImage
*)klass
->image
;
9368 idx
= encode_constant (assembly
, pb
->def_value
, &def_type
);
9369 /* Copy the data from the blob since it might get realloc-ed */
9370 p
= assembly
->blob
.data
+ idx
;
9371 len
= mono_metadata_decode_blob_size (p
, &p2
);
9373 method_aux
->param_defaults
[i
] = mp_g_malloc (mp
, len
);
9374 method_aux
->param_default_types
[i
] = def_type
;
9375 memcpy ((gpointer
)method_aux
->param_defaults
[i
], p
, len
);
9379 method_aux
->param_names
[i
] = mp_string_to_utf8 (mp
, pb
->name
);
9381 if (!method_aux
->param_cattr
)
9382 method_aux
->param_cattr
= mp_g_new0 (mp
, MonoCustomAttrInfo
*, m
->signature
->param_count
+ 1);
9383 method_aux
->param_cattr
[i
] = mono_custom_attrs_from_builders (mp
, klass
->image
, pb
->cattrs
);
9389 /* Parameter marshalling */
9392 for (i
= 0; i
< mono_array_length (rmb
->pinfo
); ++i
) {
9393 MonoReflectionParamBuilder
*pb
;
9394 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
9395 if (pb
->marshal_info
) {
9397 specs
= mp_g_new0 (mp
, MonoMarshalSpec
*, sig
->param_count
+ 1);
9398 specs
[pb
->position
] =
9399 mono_marshal_spec_from_builder (mp
, klass
->image
->assembly
, pb
->marshal_info
);
9403 if (specs
!= NULL
) {
9405 method_aux
= mp_g_new0 (mp
, MonoReflectionMethodAux
, 1);
9406 method_aux
->param_marshall
= specs
;
9409 if (klass
->image
->dynamic
&& method_aux
)
9410 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
9412 mono_loader_unlock ();
9418 ctorbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionCtorBuilder
* mb
)
9420 ReflectionMethodBuilder rmb
;
9421 MonoMethodSignature
*sig
;
9423 mono_loader_lock ();
9424 sig
= ctor_builder_to_signature (klass
->image
->mempool
, mb
);
9425 mono_loader_unlock ();
9427 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
9429 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
9430 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
9432 /* If we are in a generic class, we might be called multiple times from inflate_method */
9433 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
9434 /* ilgen is no longer needed */
9442 methodbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionMethodBuilder
* mb
)
9444 ReflectionMethodBuilder rmb
;
9445 MonoMethodSignature
*sig
;
9447 mono_loader_lock ();
9448 sig
= method_builder_to_signature (klass
->image
->mempool
, mb
);
9449 mono_loader_unlock ();
9451 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
9453 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
9454 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
9456 /* If we are in a generic class, we might be called multiple times from inflate_method */
9457 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
9458 /* ilgen is no longer needed */
9464 static MonoClassField
*
9465 fieldbuilder_to_mono_class_field (MonoClass
*klass
, MonoReflectionFieldBuilder
* fb
)
9467 MonoClassField
*field
;
9470 field
= g_new0 (MonoClassField
, 1);
9472 field
->name
= mono_string_to_utf8 (fb
->name
);
9473 if (fb
->attrs
|| fb
->modreq
|| fb
->modopt
) {
9474 field
->type
= mono_metadata_type_dup (NULL
, fb
->type
->type
);
9475 field
->type
->attrs
= fb
->attrs
;
9477 g_assert (klass
->image
->dynamic
);
9478 custom
= add_custom_modifiers ((MonoDynamicImage
*)klass
->image
, field
->type
, fb
->modreq
, fb
->modopt
);
9479 g_free (field
->type
);
9480 field
->type
= custom
;
9482 field
->type
= fb
->type
->type
;
9484 if (fb
->offset
!= -1)
9485 field
->offset
= fb
->offset
;
9486 field
->parent
= klass
;
9487 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
9489 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9495 mono_reflection_bind_generic_parameters (MonoReflectionType
*type
, int type_argc
, MonoType
**types
)
9498 MonoReflectionTypeBuilder
*tb
= NULL
;
9499 gboolean is_dynamic
= FALSE
;
9503 mono_loader_lock ();
9505 domain
= mono_object_domain (type
);
9507 if (!strcmp (((MonoObject
*) type
)->vtable
->klass
->name
, "TypeBuilder")) {
9508 tb
= (MonoReflectionTypeBuilder
*) type
;
9511 } else if (!strcmp (((MonoObject
*) type
)->vtable
->klass
->name
, "MonoGenericClass")) {
9512 MonoReflectionGenericClass
*rgi
= (MonoReflectionGenericClass
*) type
;
9514 tb
= rgi
->generic_type
;
9518 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9519 if (tb
&& tb
->generic_container
)
9520 mono_reflection_create_generic_class (tb
);
9522 klass
= mono_class_from_mono_type (type
->type
);
9523 if (!klass
->generic_container
) {
9524 mono_loader_unlock ();
9528 if (klass
->wastypebuilder
) {
9529 tb
= (MonoReflectionTypeBuilder
*) klass
->reflection_info
;
9534 mono_loader_unlock ();
9536 geninst
= mono_class_bind_generic_parameters (klass
, type_argc
, types
, is_dynamic
);
9538 return &geninst
->byval_arg
;
9542 mono_class_bind_generic_parameters (MonoClass
*klass
, int type_argc
, MonoType
**types
, gboolean is_dynamic
)
9544 MonoGenericClass
*gclass
;
9545 MonoGenericInst
*inst
;
9547 g_assert (klass
->generic_container
);
9549 inst
= mono_metadata_get_generic_inst (type_argc
, types
);
9550 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, is_dynamic
);
9552 return mono_generic_class_get_class (gclass
);
9555 MonoReflectionMethod
*
9556 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod
*rmethod
, MonoArray
*types
)
9559 MonoMethod
*method
, *inflated
;
9560 MonoMethodInflated
*imethod
;
9561 MonoReflectionMethodBuilder
*mb
= NULL
;
9562 MonoGenericContext tmp_context
;
9563 MonoGenericInst
*ginst
;
9564 MonoType
**type_argv
;
9567 MONO_ARCH_SAVE_REGS
;
9569 if (!strcmp (rmethod
->object
.vtable
->klass
->name
, "MethodBuilder")) {
9570 #ifndef DISABLE_REFLECTION_EMIT
9571 MonoReflectionTypeBuilder
*tb
;
9574 mb
= (MonoReflectionMethodBuilder
*) rmethod
;
9575 tb
= (MonoReflectionTypeBuilder
*) mb
->type
;
9576 klass
= mono_class_from_mono_type (tb
->type
.type
);
9578 method
= methodbuilder_to_mono_method (klass
, mb
);
9580 g_assert_not_reached ();
9584 method
= rmethod
->method
;
9587 klass
= method
->klass
;
9589 if (method
->is_inflated
)
9590 method
= ((MonoMethodInflated
*) method
)->declaring
;
9592 count
= mono_method_signature (method
)->generic_param_count
;
9593 if (count
!= mono_array_length (types
))
9596 type_argv
= g_new0 (MonoType
*, count
);
9597 for (i
= 0; i
< count
; i
++) {
9598 MonoReflectionType
*garg
= mono_array_get (types
, gpointer
, i
);
9599 type_argv
[i
] = garg
->type
;
9601 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
9604 tmp_context
.class_inst
= klass
->generic_class
? klass
->generic_class
->context
.class_inst
: NULL
;
9605 tmp_context
.method_inst
= ginst
;
9607 inflated
= mono_class_inflate_generic_method (method
, &tmp_context
);
9608 imethod
= (MonoMethodInflated
*) inflated
;
9610 if (method
->klass
->image
->dynamic
) {
9611 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
9613 * This table maps metadata structures representing inflated methods/fields
9614 * to the reflection objects representing their generic definitions.
9616 mono_loader_lock ();
9617 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, rmethod
);
9618 mono_loader_unlock ();
9621 return mono_method_get_object (mono_object_domain (rmethod
), inflated
, NULL
);
9624 #ifndef DISABLE_REFLECTION_EMIT
9627 inflate_mono_method (MonoClass
*klass
, MonoMethod
*method
, MonoObject
*obj
)
9629 MonoMethodInflated
*imethod
;
9630 MonoGenericContext
*context
;
9634 * With generic code sharing the klass might not be inflated.
9635 * This can happen because classes inflated with their own
9636 * type arguments are "normalized" to the uninflated class.
9638 if (!klass
->generic_class
)
9641 context
= mono_class_get_context (klass
);
9643 if (klass
->method
.count
) {
9644 /* Find the already created inflated method */
9645 for (i
= 0; i
< klass
->method
.count
; ++i
) {
9646 g_assert (klass
->methods
[i
]->is_inflated
);
9647 if (((MonoMethodInflated
*)klass
->methods
[i
])->declaring
== method
)
9650 g_assert (i
< klass
->method
.count
);
9651 imethod
= (MonoMethodInflated
*)klass
->methods
[i
];
9653 imethod
= (MonoMethodInflated
*) mono_class_inflate_generic_method_full (method
, klass
, context
);
9656 if (method
->is_generic
&& method
->klass
->image
->dynamic
) {
9657 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
9659 mono_loader_lock ();
9660 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, obj
);
9661 mono_loader_unlock ();
9663 return (MonoMethod
*) imethod
;
9667 inflate_method (MonoReflectionGenericClass
*type
, MonoObject
*obj
)
9672 gklass
= mono_class_from_mono_type (type
->generic_type
->type
.type
);
9674 if (!strcmp (obj
->vtable
->klass
->name
, "MethodBuilder"))
9675 if (((MonoReflectionMethodBuilder
*)obj
)->mhandle
)
9676 method
= ((MonoReflectionMethodBuilder
*)obj
)->mhandle
;
9678 method
= methodbuilder_to_mono_method (gklass
, (MonoReflectionMethodBuilder
*) obj
);
9679 else if (!strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder"))
9680 method
= ctorbuilder_to_mono_method (gklass
, (MonoReflectionCtorBuilder
*) obj
);
9681 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoMethod") || !strcmp (obj
->vtable
->klass
->name
, "MonoCMethod"))
9682 method
= ((MonoReflectionMethod
*) obj
)->method
;
9684 method
= NULL
; /* prevent compiler warning */
9685 g_assert_not_reached ();
9688 return inflate_mono_method (mono_class_from_mono_type (type
->type
.type
), method
, obj
);
9691 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9693 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
9694 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
9697 MonoGenericClass
*gclass
;
9698 MonoDynamicGenericClass
*dgclass
;
9699 MonoClass
*klass
, *gklass
;
9702 MONO_ARCH_SAVE_REGS
;
9704 klass
= mono_class_from_mono_type (type
->type
.type
);
9705 g_assert (type
->type
.type
->type
== MONO_TYPE_GENERICINST
);
9706 gclass
= type
->type
.type
->data
.generic_class
;
9708 g_assert (gclass
->is_dynamic
);
9709 dgclass
= (MonoDynamicGenericClass
*) gclass
;
9711 if (dgclass
->initialized
)
9714 gklass
= gclass
->container_class
;
9715 mono_class_init (gklass
);
9717 dgclass
->count_methods
= methods
? mono_array_length (methods
) : 0;
9718 dgclass
->count_ctors
= ctors
? mono_array_length (ctors
) : 0;
9719 dgclass
->count_fields
= fields
? mono_array_length (fields
) : 0;
9720 dgclass
->count_properties
= properties
? mono_array_length (properties
) : 0;
9721 dgclass
->count_events
= events
? mono_array_length (events
) : 0;
9723 dgclass
->methods
= g_new0 (MonoMethod
*, dgclass
->count_methods
);
9724 dgclass
->ctors
= g_new0 (MonoMethod
*, dgclass
->count_ctors
);
9725 dgclass
->fields
= g_new0 (MonoClassField
, dgclass
->count_fields
);
9726 dgclass
->properties
= g_new0 (MonoProperty
, dgclass
->count_properties
);
9727 dgclass
->events
= g_new0 (MonoEvent
, dgclass
->count_events
);
9728 dgclass
->field_objects
= g_new0 (MonoObject
*, dgclass
->count_fields
);
9729 dgclass
->field_generic_types
= g_new0 (MonoType
*, dgclass
->count_fields
);
9731 for (i
= 0; i
< dgclass
->count_methods
; i
++) {
9732 MonoObject
*obj
= mono_array_get (methods
, gpointer
, i
);
9734 dgclass
->methods
[i
] = inflate_method (type
, obj
);
9737 for (i
= 0; i
< dgclass
->count_ctors
; i
++) {
9738 MonoObject
*obj
= mono_array_get (ctors
, gpointer
, i
);
9740 dgclass
->ctors
[i
] = inflate_method (type
, obj
);
9743 for (i
= 0; i
< dgclass
->count_fields
; i
++) {
9744 MonoObject
*obj
= mono_array_get (fields
, gpointer
, i
);
9745 MonoClassField
*field
, *inflated_field
= NULL
;
9747 if (!strcmp (obj
->vtable
->klass
->name
, "FieldBuilder"))
9748 inflated_field
= field
= fieldbuilder_to_mono_class_field (klass
, (MonoReflectionFieldBuilder
*) obj
);
9749 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoField"))
9750 field
= ((MonoReflectionField
*) obj
)->field
;
9752 field
= NULL
; /* prevent compiler warning */
9753 g_assert_not_reached ();
9756 dgclass
->fields
[i
] = *field
;
9757 dgclass
->fields
[i
].parent
= klass
;
9758 dgclass
->fields
[i
].type
= mono_class_inflate_generic_type (
9759 field
->type
, mono_generic_class_get_context ((MonoGenericClass
*) dgclass
));
9760 dgclass
->field_generic_types
[i
] = field
->type
;
9761 MOVING_GC_REGISTER (&dgclass
->field_objects
[i
]);
9762 dgclass
->field_objects
[i
] = obj
;
9764 if (inflated_field
) {
9765 g_free (inflated_field
);
9767 dgclass
->fields
[i
].name
= g_strdup (dgclass
->fields
[i
].name
);
9771 for (i
= 0; i
< dgclass
->count_properties
; i
++) {
9772 MonoObject
*obj
= mono_array_get (properties
, gpointer
, i
);
9773 MonoProperty
*property
= &dgclass
->properties
[i
];
9775 if (!strcmp (obj
->vtable
->klass
->name
, "PropertyBuilder")) {
9776 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*) obj
;
9778 property
->parent
= klass
;
9779 property
->attrs
= pb
->attrs
;
9780 property
->name
= mono_string_to_utf8 (pb
->name
);
9782 property
->get
= inflate_method (type
, (MonoObject
*) pb
->get_method
);
9784 property
->set
= inflate_method (type
, (MonoObject
*) pb
->set_method
);
9785 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoProperty")) {
9786 *property
= *((MonoReflectionProperty
*) obj
)->property
;
9787 property
->name
= g_strdup (property
->name
);
9790 property
->get
= inflate_mono_method (klass
, property
->get
, NULL
);
9792 property
->set
= inflate_mono_method (klass
, property
->set
, NULL
);
9794 g_assert_not_reached ();
9797 for (i
= 0; i
< dgclass
->count_events
; i
++) {
9798 MonoObject
*obj
= mono_array_get (events
, gpointer
, i
);
9799 MonoEvent
*event
= &dgclass
->events
[i
];
9801 if (!strcmp (obj
->vtable
->klass
->name
, "EventBuilder")) {
9802 MonoReflectionEventBuilder
*eb
= (MonoReflectionEventBuilder
*) obj
;
9804 event
->parent
= klass
;
9805 event
->attrs
= eb
->attrs
;
9806 event
->name
= mono_string_to_utf8 (eb
->name
);
9808 event
->add
= inflate_method (type
, (MonoObject
*) eb
->add_method
);
9809 if (eb
->remove_method
)
9810 event
->remove
= inflate_method (type
, (MonoObject
*) eb
->remove_method
);
9811 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoEvent")) {
9812 *event
= *((MonoReflectionEvent
*) obj
)->event
;
9813 event
->name
= g_strdup (event
->name
);
9816 event
->add
= inflate_mono_method (klass
, event
->add
, NULL
);
9818 event
->remove
= inflate_mono_method (klass
, event
->remove
, NULL
);
9820 g_assert_not_reached ();
9823 dgclass
->initialized
= TRUE
;
9827 ensure_generic_class_runtime_vtable (MonoClass
*klass
)
9829 MonoClass
*gklass
= klass
->generic_class
->container_class
;
9832 if (klass
->wastypebuilder
)
9835 ensure_runtime_vtable (gklass
);
9837 klass
->method
.count
= gklass
->method
.count
;
9838 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * (klass
->method
.count
+ 1));
9840 for (i
= 0; i
< klass
->method
.count
; i
++) {
9841 klass
->methods
[i
] = mono_class_inflate_generic_method_full (
9842 gklass
->methods
[i
], klass
, mono_class_get_context (klass
));
9845 klass
->interface_count
= gklass
->interface_count
;
9846 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
9847 for (i
= 0; i
< klass
->interface_count
; ++i
) {
9848 MonoType
*iface_type
= mono_class_inflate_generic_type (&gklass
->interfaces
[i
]->byval_arg
, mono_class_get_context (klass
));
9849 klass
->interfaces
[i
] = mono_class_from_mono_type (iface_type
);
9850 mono_metadata_free_type (iface_type
);
9852 ensure_runtime_vtable (klass
->interfaces
[i
]);
9854 /*We can only finish with this klass once it's parent has as well*/
9855 if (gklass
->wastypebuilder
)
9856 klass
->wastypebuilder
= TRUE
;
9861 ensure_runtime_vtable (MonoClass
*klass
)
9863 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
9866 if (!klass
->image
->dynamic
|| (!tb
&& !klass
->generic_class
) || klass
->wastypebuilder
)
9869 ensure_runtime_vtable (klass
->parent
);
9872 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
9873 num
+= tb
->num_methods
;
9874 klass
->method
.count
= num
;
9875 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * num
);
9876 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
9877 for (i
= 0; i
< num
; ++i
)
9878 klass
->methods
[i
] = ctorbuilder_to_mono_method (klass
, mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
));
9879 num
= tb
->num_methods
;
9881 for (i
= 0; i
< num
; ++i
)
9882 klass
->methods
[j
++] = methodbuilder_to_mono_method (klass
, mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
));
9884 if (tb
->interfaces
) {
9885 klass
->interface_count
= mono_array_length (tb
->interfaces
);
9886 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
9887 for (i
= 0; i
< klass
->interface_count
; ++i
) {
9888 MonoReflectionType
*iface
= mono_array_get (tb
->interfaces
, gpointer
, i
);
9889 klass
->interfaces
[i
] = mono_class_from_mono_type (iface
->type
);
9890 ensure_runtime_vtable (klass
->interfaces
[i
]);
9893 } else if (klass
->generic_class
){
9894 ensure_generic_class_runtime_vtable (klass
);
9897 if (klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
9898 for (i
= 0; i
< klass
->method
.count
; ++i
)
9899 klass
->methods
[i
]->slot
= i
;
9901 mono_class_setup_interface_offsets (klass
);
9902 mono_class_setup_interface_id (klass
);
9906 * The generic vtable is needed even if image->run is not set since some
9907 * runtime code like ves_icall_Type_GetMethodsByName depends on
9908 * method->slot being defined.
9912 * tb->methods could not be freed since it is used for determining
9913 * overrides during dynamic vtable construction.
9918 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
9920 MonoReflectionTypeBuilder
*tb
;
9926 g_assert (klass
->image
->dynamic
);
9928 if (!klass
->reflection_info
)
9931 g_assert (strcmp (((MonoObject
*)klass
->reflection_info
)->vtable
->klass
->name
, "TypeBuilder") == 0);
9933 tb
= (MonoReflectionTypeBuilder
*)klass
->reflection_info
;
9937 for (i
= 0; i
< tb
->num_methods
; ++i
) {
9938 MonoReflectionMethodBuilder
*mb
=
9939 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
9940 if (mb
->override_method
)
9946 *overrides
= g_new0 (MonoMethod
*, onum
* 2);
9949 for (i
= 0; i
< tb
->num_methods
; ++i
) {
9950 MonoReflectionMethodBuilder
*mb
=
9951 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
9952 if (mb
->override_method
) {
9953 (*overrides
) [onum
* 2] =
9954 mb
->override_method
->method
;
9955 (*overrides
) [onum
* 2 + 1] =
9958 /* FIXME: What if 'override_method' is a MethodBuilder ? */
9959 g_assert (mb
->override_method
->method
);
9960 g_assert (mb
->mhandle
);
9967 *num_overrides
= onum
;
9971 typebuilder_setup_fields (MonoClass
*klass
)
9973 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
9974 MonoReflectionFieldBuilder
*fb
;
9975 MonoClassField
*field
;
9976 MonoMemPool
*mp
= klass
->image
->mempool
;
9979 guint32 len
, idx
, real_size
= 0;
9981 klass
->field
.count
= tb
->num_fields
;
9982 klass
->field
.first
= 0;
9984 if (tb
->class_size
) {
9985 g_assert ((tb
->packing_size
& 0xfffffff0) == 0);
9986 klass
->packing_size
= tb
->packing_size
;
9987 real_size
= klass
->instance_size
+ tb
->class_size
;
9990 if (!klass
->field
.count
) {
9991 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
9995 klass
->fields
= mp_g_new0 (mp
, MonoClassField
, klass
->field
.count
);
9996 klass
->field_def_values
= mp_g_new0 (mp
, MonoFieldDefaultValue
, klass
->field
.count
);
9998 for (i
= 0; i
< klass
->field
.count
; ++i
) {
9999 fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10000 field
= &klass
->fields
[i
];
10001 field
->name
= mp_string_to_utf8 (mp
, fb
->name
);
10003 field
->type
= mono_metadata_type_dup (mp
, fb
->type
->type
);
10004 field
->type
->attrs
= fb
->attrs
;
10006 field
->type
= fb
->type
->type
;
10008 if ((fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) && fb
->rva_data
)
10009 klass
->field_def_values
[i
].data
= mono_array_addr (fb
->rva_data
, char, 0);
10010 if (fb
->offset
!= -1)
10011 field
->offset
= fb
->offset
;
10012 field
->parent
= klass
;
10013 fb
->handle
= field
;
10014 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
10016 if (fb
->def_value
) {
10017 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)klass
->image
;
10018 field
->type
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
10019 idx
= encode_constant (assembly
, fb
->def_value
, &klass
->field_def_values
[i
].def_type
);
10020 /* Copy the data from the blob since it might get realloc-ed */
10021 p
= assembly
->blob
.data
+ idx
;
10022 len
= mono_metadata_decode_blob_size (p
, &p2
);
10024 klass
->field_def_values
[i
].data
= mono_mempool_alloc (mp
, len
);
10025 memcpy ((gpointer
)klass
->field_def_values
[i
].data
, p
, len
);
10029 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10030 mono_class_layout_fields (klass
);
10034 typebuilder_setup_properties (MonoClass
*klass
)
10036 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10037 MonoReflectionPropertyBuilder
*pb
;
10038 MonoMemPool
*mp
= klass
->image
->mempool
;
10041 klass
->property
.count
= tb
->properties
? mono_array_length (tb
->properties
) : 0;
10042 klass
->property
.first
= 0;
10044 klass
->properties
= mp_g_new0 (mp
, MonoProperty
, klass
->property
.count
);
10045 for (i
= 0; i
< klass
->property
.count
; ++i
) {
10046 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
10047 klass
->properties
[i
].parent
= klass
;
10048 klass
->properties
[i
].attrs
= pb
->attrs
;
10049 klass
->properties
[i
].name
= mp_string_to_utf8 (mp
, pb
->name
);
10050 if (pb
->get_method
)
10051 klass
->properties
[i
].get
= pb
->get_method
->mhandle
;
10052 if (pb
->set_method
)
10053 klass
->properties
[i
].set
= pb
->set_method
->mhandle
;
10055 mono_save_custom_attrs (klass
->image
, &klass
->properties
[i
], pb
->cattrs
);
10059 MonoReflectionEvent
*
10060 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
10062 MonoEvent
*event
= g_new0 (MonoEvent
, 1);
10066 klass
= my_mono_class_from_mono_type (tb
->type
.type
);
10068 event
->parent
= klass
;
10069 event
->attrs
= eb
->attrs
;
10070 event
->name
= mono_string_to_utf8 (eb
->name
);
10071 if (eb
->add_method
)
10072 event
->add
= eb
->add_method
->mhandle
;
10073 if (eb
->remove_method
)
10074 event
->remove
= eb
->remove_method
->mhandle
;
10075 if (eb
->raise_method
)
10076 event
->raise
= eb
->raise_method
->mhandle
;
10078 if (eb
->other_methods
) {
10079 event
->other
= g_new0 (MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10080 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10081 MonoReflectionMethodBuilder
*mb
=
10082 mono_array_get (eb
->other_methods
,
10083 MonoReflectionMethodBuilder
*, j
);
10084 event
->other
[j
] = mb
->mhandle
;
10088 return mono_event_get_object (mono_object_domain (tb
), klass
, event
);
10092 typebuilder_setup_events (MonoClass
*klass
)
10094 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10095 MonoReflectionEventBuilder
*eb
;
10096 MonoMemPool
*mp
= klass
->image
->mempool
;
10099 klass
->event
.count
= tb
->events
? mono_array_length (tb
->events
) : 0;
10100 klass
->event
.first
= 0;
10102 klass
->events
= mp_g_new0 (mp
, MonoEvent
, klass
->event
.count
);
10103 for (i
= 0; i
< klass
->event
.count
; ++i
) {
10104 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
10105 klass
->events
[i
].parent
= klass
;
10106 klass
->events
[i
].attrs
= eb
->attrs
;
10107 klass
->events
[i
].name
= mp_string_to_utf8 (mp
, eb
->name
);
10108 if (eb
->add_method
)
10109 klass
->events
[i
].add
= eb
->add_method
->mhandle
;
10110 if (eb
->remove_method
)
10111 klass
->events
[i
].remove
= eb
->remove_method
->mhandle
;
10112 if (eb
->raise_method
)
10113 klass
->events
[i
].raise
= eb
->raise_method
->mhandle
;
10115 if (eb
->other_methods
) {
10116 klass
->events
[i
].other
= mp_g_new0 (mp
, MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10117 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10118 MonoReflectionMethodBuilder
*mb
=
10119 mono_array_get (eb
->other_methods
,
10120 MonoReflectionMethodBuilder
*, j
);
10121 klass
->events
[i
].other
[j
] = mb
->mhandle
;
10124 mono_save_custom_attrs (klass
->image
, &klass
->events
[i
], eb
->cattrs
);
10129 remove_instantiations_of (gpointer key
,
10131 gpointer user_data
)
10133 MonoType
*type
= (MonoType
*)key
;
10134 MonoClass
*klass
= (MonoClass
*)user_data
;
10136 if ((type
->type
== MONO_TYPE_GENERICINST
) && (type
->data
.generic_class
->container_class
== klass
))
10142 MonoReflectionType
*
10143 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
10146 MonoDomain
* domain
;
10147 MonoReflectionType
* res
;
10150 MONO_ARCH_SAVE_REGS
;
10152 domain
= mono_object_domain (tb
);
10153 klass
= my_mono_class_from_mono_type (tb
->type
.type
);
10155 mono_save_custom_attrs (klass
->image
, klass
, tb
->cattrs
);
10158 * we need to lock the domain because the lock will be taken inside
10159 * So, we need to keep the locking order correct.
10161 mono_domain_lock (domain
);
10162 mono_loader_lock ();
10163 if (klass
->wastypebuilder
) {
10164 mono_loader_unlock ();
10165 mono_domain_unlock (domain
);
10166 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10169 * Fields to set in klass:
10170 * the various flags: delegate/unicode/contextbound etc.
10172 klass
->flags
= tb
->attrs
;
10173 klass
->has_cctor
= 1;
10174 klass
->has_finalize
= 1;
10177 if (!((MonoDynamicImage
*)klass
->image
)->run
) {
10178 if (klass
->generic_container
) {
10179 /* FIXME: The code below can't handle generic classes */
10180 klass
->wastypebuilder
= TRUE
;
10181 mono_loader_unlock ();
10182 mono_domain_unlock (domain
);
10183 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10188 /* enums are done right away */
10189 if (!klass
->enumtype
)
10190 ensure_runtime_vtable (klass
);
10192 if (tb
->subtypes
) {
10193 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
10194 MonoReflectionTypeBuilder
*subtb
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
10195 klass
->nested_classes
= g_list_prepend_mempool (klass
->image
->mempool
, klass
->nested_classes
, my_mono_class_from_mono_type (subtb
->type
.type
));
10199 klass
->nested_classes_inited
= TRUE
;
10201 /* fields and object layout */
10202 if (klass
->parent
) {
10203 if (!klass
->parent
->size_inited
)
10204 mono_class_init (klass
->parent
);
10205 klass
->instance_size
= klass
->parent
->instance_size
;
10206 klass
->sizes
.class_size
= 0;
10207 klass
->min_align
= klass
->parent
->min_align
;
10208 /* if the type has no fields we won't call the field_setup
10209 * routine which sets up klass->has_references.
10211 klass
->has_references
|= klass
->parent
->has_references
;
10213 klass
->instance_size
= sizeof (MonoObject
);
10214 klass
->min_align
= 1;
10217 /* FIXME: handle packing_size and instance_size */
10218 typebuilder_setup_fields (klass
);
10220 typebuilder_setup_properties (klass
);
10222 typebuilder_setup_events (klass
);
10224 klass
->wastypebuilder
= TRUE
;
10227 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10228 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10229 * we want to return normal System.MonoType objects, so clear these out from the cache.
10231 if (domain
->type_hash
&& klass
->generic_container
)
10232 mono_g_hash_table_foreach_remove (domain
->type_hash
, remove_instantiations_of
, klass
);
10234 mono_loader_unlock ();
10235 mono_domain_unlock (domain
);
10237 if (klass
->enumtype
&& !mono_class_is_valid_enum (klass
)) {
10238 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
10239 mono_raise_exception (mono_get_exception_type_load (tb
->name
, NULL
));
10242 res
= mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10243 g_assert (res
!= (MonoReflectionType
*)tb
);
10249 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
10251 MonoGenericParam
*param
;
10254 MONO_ARCH_SAVE_REGS
;
10256 param
= g_new0 (MonoGenericParam
, 1);
10258 if (gparam
->mbuilder
) {
10259 if (!gparam
->mbuilder
->generic_container
) {
10260 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)gparam
->mbuilder
->type
;
10261 MonoClass
*klass
= my_mono_class_from_mono_type (tb
->type
.type
);
10262 gparam
->mbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
10263 gparam
->mbuilder
->generic_container
->is_method
= TRUE
;
10265 param
->owner
= gparam
->mbuilder
->generic_container
;
10266 } else if (gparam
->tbuilder
) {
10267 if (!gparam
->tbuilder
->generic_container
) {
10268 MonoClass
*klass
= my_mono_class_from_mono_type (gparam
->tbuilder
->type
.type
);
10269 gparam
->tbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
10270 gparam
->tbuilder
->generic_container
->owner
.klass
= klass
;
10272 param
->owner
= gparam
->tbuilder
->generic_container
;
10275 param
->name
= mono_string_to_utf8 (gparam
->name
);
10276 param
->num
= gparam
->index
;
10278 image
= &gparam
->tbuilder
->module
->dynamic_image
->image
;
10279 mono_class_from_generic_parameter (param
, image
, gparam
->mbuilder
!= NULL
);
10281 gparam
->type
.type
= ¶m
->pklass
->byval_arg
;
10283 MOVING_GC_REGISTER (¶m
->pklass
->reflection_info
);
10284 param
->pklass
->reflection_info
= gparam
; /* FIXME: GC pin gparam */
10288 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
10290 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
10291 guint32 na
= mono_array_length (sig
->arguments
);
10296 sigbuffer_init (&buf
, 32);
10298 sigbuffer_add_value (&buf
, 0x07);
10299 sigbuffer_add_value (&buf
, na
);
10300 for (i
= 0; i
< na
; ++i
) {
10301 MonoReflectionType
*type
= mono_array_get (sig
->arguments
, MonoReflectionType
*, i
);
10302 encode_reflection_type (assembly
, type
, &buf
);
10305 buflen
= buf
.p
- buf
.buf
;
10306 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
10307 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
10308 sigbuffer_free (&buf
);
10314 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
10316 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
10317 guint32 na
= mono_array_length (sig
->arguments
);
10322 sigbuffer_init (&buf
, 32);
10324 sigbuffer_add_value (&buf
, 0x06);
10325 for (i
= 0; i
< na
; ++i
) {
10326 MonoReflectionType
*type
= mono_array_get (sig
->arguments
, MonoReflectionType
*, i
);
10327 encode_reflection_type (assembly
, type
, &buf
);
10330 buflen
= buf
.p
- buf
.buf
;
10331 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
10332 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
10333 sigbuffer_free (&buf
);
10339 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10341 ReflectionMethodBuilder rmb
;
10342 MonoMethodSignature
*sig
;
10347 sig
= dynamic_method_to_signature (mb
);
10349 reflection_methodbuilder_from_dynamic_method (&rmb
, mb
);
10352 * Resolve references.
10355 * Every second entry in the refs array is reserved for storing handle_class,
10356 * which is needed by the ldtoken implementation in the JIT.
10358 rmb
.nrefs
= mb
->nrefs
;
10359 rmb
.refs
= g_new0 (gpointer
, mb
->nrefs
+ 1);
10360 for (i
= 0; i
< mb
->nrefs
; i
+= 2) {
10361 MonoClass
*handle_class
;
10363 MonoObject
*obj
= mono_array_get (mb
->refs
, MonoObject
*, i
);
10365 if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
10366 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
10368 * The referenced DynamicMethod should already be created by the managed
10369 * code, except in the case of circular references. In that case, we store
10370 * method in the refs array, and fix it up later when the referenced
10371 * DynamicMethod is created.
10373 if (method
->mhandle
) {
10374 ref
= method
->mhandle
;
10376 /* FIXME: GC object stored in unmanaged memory */
10379 /* FIXME: GC object stored in unmanaged memory */
10380 method
->referenced_by
= g_slist_append (method
->referenced_by
, mb
);
10382 handle_class
= mono_defaults
.methodhandle_class
;
10384 ref
= resolve_object (mb
->module
->image
, obj
, &handle_class
, NULL
);
10387 mono_raise_exception (mono_get_exception_type_load (NULL
, NULL
));
10392 rmb
.refs
[i
] = ref
; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10393 rmb
.refs
[i
+ 1] = handle_class
;
10396 klass
= mb
->owner
? mono_class_from_mono_type (mb
->owner
->type
) : mono_defaults
.object_class
;
10398 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
10400 /* Fix up refs entries pointing at us */
10401 for (l
= mb
->referenced_by
; l
; l
= l
->next
) {
10402 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)l
->data
;
10403 MonoMethodWrapper
*wrapper
= (MonoMethodWrapper
*)method
->mhandle
;
10406 g_assert (method
->mhandle
);
10408 data
= (gpointer
*)wrapper
->method_data
;
10409 for (i
= 0; i
< GPOINTER_TO_UINT (data
[0]); i
+= 2) {
10410 if ((data
[i
+ 1] == mb
) && (data
[i
+ 1 + 1] == mono_defaults
.methodhandle_class
))
10411 data
[i
+ 1] = mb
->mhandle
;
10414 g_slist_free (mb
->referenced_by
);
10418 /* ilgen is no longer needed */
10422 #endif /* DISABLE_REFLECTION_EMIT */
10425 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10430 mono_runtime_free_method (
10431 mono_object_get_domain ((MonoObject
*)mb
), mb
->mhandle
);
10436 * mono_reflection_is_valid_dynamic_token:
10438 * Returns TRUE if token is valid.
10442 mono_reflection_is_valid_dynamic_token (MonoDynamicImage
*image
, guint32 token
)
10444 return mono_g_hash_table_lookup (image
->tokens
, GUINT_TO_POINTER (token
)) != NULL
;
10447 #ifndef DISABLE_REFLECTION_EMIT
10450 * mono_reflection_lookup_dynamic_token:
10452 * Finish the Builder object pointed to by TOKEN and return the corresponding
10453 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10454 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10458 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10460 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)image
;
10464 obj
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
10467 g_assert_not_reached ();
10473 handle_class
= &klass
;
10474 return resolve_object (image
, obj
, handle_class
, context
);
10478 resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10480 gpointer result
= NULL
;
10482 if (strcmp (obj
->vtable
->klass
->name
, "String") == 0) {
10483 result
= mono_string_intern ((MonoString
*)obj
);
10484 *handle_class
= NULL
;
10486 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoType") == 0) {
10487 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
10489 MonoType
*inflated
= mono_class_inflate_generic_type (tb
->type
, context
);
10490 result
= mono_class_from_mono_type (inflated
);
10491 mono_metadata_free_type (inflated
);
10493 result
= mono_class_from_mono_type (tb
->type
);
10495 *handle_class
= mono_defaults
.typehandle_class
;
10497 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoMethod") == 0 ||
10498 strcmp (obj
->vtable
->klass
->name
, "MonoCMethod") == 0 ||
10499 strcmp (obj
->vtable
->klass
->name
, "MonoGenericCMethod") == 0 ||
10500 strcmp (obj
->vtable
->klass
->name
, "MonoGenericMethod") == 0) {
10501 result
= ((MonoReflectionMethod
*)obj
)->method
;
10503 result
= mono_class_inflate_generic_method (result
, context
);
10504 *handle_class
= mono_defaults
.methodhandle_class
;
10506 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodBuilder") == 0) {
10507 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
10508 result
= mb
->mhandle
;
10510 /* Type is not yet created */
10511 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
10513 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10516 * Hopefully this has been filled in by calling CreateType() on the
10520 * TODO: This won't work if the application finishes another
10521 * TypeBuilder instance instead of this one.
10523 result
= mb
->mhandle
;
10526 result
= mono_class_inflate_generic_method (result
, context
);
10527 *handle_class
= mono_defaults
.methodhandle_class
;
10528 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder") == 0) {
10529 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
10531 result
= cb
->mhandle
;
10533 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)cb
->type
;
10535 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10536 result
= cb
->mhandle
;
10539 result
= mono_class_inflate_generic_method (result
, context
);
10540 *handle_class
= mono_defaults
.methodhandle_class
;
10541 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoField") == 0) {
10542 MonoClassField
*field
= ((MonoReflectionField
*)obj
)->field
;
10544 MonoType
*inflated
= mono_class_inflate_generic_type (&field
->parent
->byval_arg
, context
);
10545 MonoClass
*class = mono_class_from_mono_type (inflated
);
10546 MonoClassField
*inflated_field
;
10547 gpointer iter
= NULL
;
10548 mono_metadata_free_type (inflated
);
10549 while ((inflated_field
= mono_class_get_fields (class, &iter
))) {
10550 if (!strcmp (field
->name
, inflated_field
->name
))
10553 g_assert (inflated_field
&& !strcmp (field
->name
, inflated_field
->name
));
10554 result
= inflated_field
;
10558 *handle_class
= mono_defaults
.fieldhandle_class
;
10560 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldBuilder") == 0) {
10561 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
10562 result
= fb
->handle
;
10565 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
10567 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10568 result
= fb
->handle
;
10571 if (fb
->handle
&& fb
->handle
->parent
->generic_container
) {
10572 MonoClass
*klass
= fb
->handle
->parent
;
10573 MonoType
*type
= mono_class_inflate_generic_type (&klass
->byval_arg
, context
);
10574 MonoClass
*inflated
= mono_class_from_mono_type (type
);
10576 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (fb
->handle
));
10578 mono_metadata_free_type (type
);
10580 *handle_class
= mono_defaults
.fieldhandle_class
;
10581 } else if (strcmp (obj
->vtable
->klass
->name
, "TypeBuilder") == 0) {
10582 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
10585 klass
= tb
->type
.type
->data
.klass
;
10586 if (klass
->wastypebuilder
) {
10587 /* Already created */
10591 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10592 result
= tb
->type
.type
->data
.klass
;
10595 *handle_class
= mono_defaults
.typehandle_class
;
10596 } else if (strcmp (obj
->vtable
->klass
->name
, "SignatureHelper") == 0) {
10597 MonoReflectionSigHelper
*helper
= (MonoReflectionSigHelper
*)obj
;
10598 MonoMethodSignature
*sig
;
10601 if (helper
->arguments
)
10602 nargs
= mono_array_length (helper
->arguments
);
10606 sig
= mono_metadata_signature_alloc (image
, nargs
);
10607 sig
->explicit_this
= helper
->call_conv
& 64 ? 1 : 0;
10608 sig
->hasthis
= helper
->call_conv
& 32 ? 1 : 0;
10610 if (helper
->call_conv
== 0) /* unmanaged */
10611 sig
->call_convention
= helper
->unmanaged_call_conv
- 1;
10613 if (helper
->call_conv
& 0x02)
10614 sig
->call_convention
= MONO_CALL_VARARG
;
10616 sig
->call_convention
= MONO_CALL_DEFAULT
;
10618 sig
->param_count
= nargs
;
10619 /* TODO: Copy type ? */
10620 sig
->ret
= helper
->return_type
->type
;
10621 for (i
= 0; i
< nargs
; ++i
) {
10622 MonoReflectionType
*rt
= mono_array_get (helper
->arguments
, MonoReflectionType
*, i
);
10623 sig
->params
[i
] = rt
->type
;
10627 *handle_class
= NULL
;
10628 } else if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
10629 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
10630 /* Already created by the managed code */
10631 g_assert (method
->mhandle
);
10632 result
= method
->mhandle
;
10633 *handle_class
= mono_defaults
.methodhandle_class
;
10634 } else if (strcmp (obj
->vtable
->klass
->name
, "GenericTypeParameterBuilder") == 0) {
10635 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
10636 MonoType
*type
= mono_class_inflate_generic_type (tb
->type
, context
);
10637 result
= mono_class_from_mono_type (type
);
10638 *handle_class
= mono_defaults
.typehandle_class
;
10640 mono_metadata_free_type (type
);
10641 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoGenericClass") == 0) {
10642 MonoReflectionGenericClass
*ref
= (MonoReflectionGenericClass
*)obj
;
10643 MonoType
*type
= mono_class_inflate_generic_type (ref
->type
.type
, context
);
10644 result
= mono_class_from_mono_type (type
);
10645 *handle_class
= mono_defaults
.typehandle_class
;
10647 mono_metadata_free_type (type
);
10648 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldOnTypeBuilderInst") == 0) {
10649 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
10650 MonoClass
*inflated
;
10653 type
= mono_class_inflate_generic_type (f
->inst
->type
.type
, context
);
10654 inflated
= mono_class_from_mono_type (type
);
10656 g_assert (f
->fb
->handle
);
10657 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (f
->fb
->handle
));
10659 mono_metadata_free_type (type
);
10660 *handle_class
= mono_defaults
.fieldhandle_class
;
10661 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
10662 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
10663 MonoType
*type
= mono_class_inflate_generic_type (c
->inst
->type
.type
, context
);
10664 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
10665 g_assert (c
->cb
->mhandle
);
10666 result
= inflate_mono_method (inflated_klass
, c
->cb
->mhandle
, (MonoObject
*)c
->cb
);
10667 *handle_class
= mono_defaults
.methodhandle_class
;
10668 mono_metadata_free_type (type
);
10669 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodOnTypeBuilderInst") == 0) {
10670 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
10671 MonoType
*type
= mono_class_inflate_generic_type (m
->inst
->type
.type
, context
);
10672 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
10673 g_assert (m
->mb
->mhandle
);
10674 result
= inflate_mono_method (inflated_klass
, m
->mb
->mhandle
, (MonoObject
*)m
->mb
);
10675 *handle_class
= mono_defaults
.methodhandle_class
;
10676 mono_metadata_free_type (type
);
10678 g_print (obj
->vtable
->klass
->name
);
10679 g_assert_not_reached ();
10684 #else /* DISABLE_REFLECTION_EMIT */
10687 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
10689 g_assert_not_reached ();
10694 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
10696 g_assert_not_reached ();
10700 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
10702 g_assert_not_reached ();
10706 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
10708 g_assert_not_reached ();
10712 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
10714 g_assert_not_reached ();
10718 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
10720 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10724 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
10726 g_assert_not_reached ();
10729 MonoReflectionModule
*
10730 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
10732 g_assert_not_reached ();
10737 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
10739 g_assert_not_reached ();
10744 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
10746 g_assert_not_reached ();
10751 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
10752 gboolean create_methodspec
, gboolean register_token
)
10754 g_assert_not_reached ();
10759 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
10764 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
10765 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
10768 g_assert_not_reached ();
10772 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
10775 *num_overrides
= 0;
10778 MonoReflectionEvent
*
10779 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
10781 g_assert_not_reached ();
10785 MonoReflectionType
*
10786 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
10788 g_assert_not_reached ();
10793 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
10795 g_assert_not_reached ();
10799 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
10801 g_assert_not_reached ();
10806 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
10808 g_assert_not_reached ();
10813 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10818 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10823 #endif /* DISABLE_REFLECTION_EMIT */
10825 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10826 const static guint32 declsec_flags_map
[] = {
10827 0x00000000, /* empty */
10828 MONO_DECLSEC_FLAG_REQUEST
, /* SECURITY_ACTION_REQUEST (x01) */
10829 MONO_DECLSEC_FLAG_DEMAND
, /* SECURITY_ACTION_DEMAND (x02) */
10830 MONO_DECLSEC_FLAG_ASSERT
, /* SECURITY_ACTION_ASSERT (x03) */
10831 MONO_DECLSEC_FLAG_DENY
, /* SECURITY_ACTION_DENY (x04) */
10832 MONO_DECLSEC_FLAG_PERMITONLY
, /* SECURITY_ACTION_PERMITONLY (x05) */
10833 MONO_DECLSEC_FLAG_LINKDEMAND
, /* SECURITY_ACTION_LINKDEMAND (x06) */
10834 MONO_DECLSEC_FLAG_INHERITANCEDEMAND
, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
10835 MONO_DECLSEC_FLAG_REQUEST_MINIMUM
, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
10836 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL
, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
10837 MONO_DECLSEC_FLAG_REQUEST_REFUSE
, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
10838 MONO_DECLSEC_FLAG_PREJIT_GRANT
, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
10839 MONO_DECLSEC_FLAG_PREJIT_DENY
, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
10840 MONO_DECLSEC_FLAG_NONCAS_DEMAND
, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
10841 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
10842 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
10843 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
10844 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
10845 MONO_DECLSEC_FLAG_DEMAND_CHOICE
, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
10849 * Returns flags that includes all available security action associated to the handle.
10850 * @token: metadata token (either for a class or a method)
10851 * @image: image where resides the metadata.
10854 mono_declsec_get_flags (MonoImage
*image
, guint32 token
)
10856 int index
= mono_metadata_declsec_from_index (image
, token
);
10857 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
10858 guint32 result
= 0;
10862 /* HasSecurity can be present for other, not specially encoded, attributes,
10863 e.g. SuppressUnmanagedCodeSecurityAttribute */
10867 for (i
= index
; i
< t
->rows
; i
++) {
10868 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
10870 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
10871 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
10874 action
= cols
[MONO_DECL_SECURITY_ACTION
];
10875 if ((action
>= MONO_DECLSEC_ACTION_MIN
) && (action
<= MONO_DECLSEC_ACTION_MAX
)) {
10876 result
|= declsec_flags_map
[action
];
10878 g_assert_not_reached ();
10885 * Get the security actions (in the form of flags) associated with the specified method.
10887 * @method: The method for which we want the declarative security flags.
10888 * Return the declarative security flags for the method (only).
10890 * Note: To keep MonoMethod size down we do not cache the declarative security flags
10891 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
10894 mono_declsec_flags_from_method (MonoMethod
*method
)
10896 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
10897 /* FIXME: No cache (for the moment) */
10898 guint32 idx
= mono_method_get_index (method
);
10899 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
10900 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
10901 return mono_declsec_get_flags (method
->klass
->image
, idx
);
10907 * Get the security actions (in the form of flags) associated with the specified class.
10909 * @klass: The class for which we want the declarative security flags.
10910 * Return the declarative security flags for the class.
10912 * Note: We cache the flags inside the MonoClass structure as this will get
10913 * called very often (at least for each method).
10916 mono_declsec_flags_from_class (MonoClass
*klass
)
10918 if (klass
->flags
& TYPE_ATTRIBUTE_HAS_SECURITY
) {
10919 if (!klass
->declsec_flags
) {
10920 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
10921 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
10922 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
10923 /* we cache the flags on classes */
10924 klass
->declsec_flags
= mono_declsec_get_flags (klass
->image
, idx
);
10926 return klass
->declsec_flags
;
10932 * Get the security actions (in the form of flags) associated with the specified assembly.
10934 * @assembly: The assembly for which we want the declarative security flags.
10935 * Return the declarative security flags for the assembly.
10938 mono_declsec_flags_from_assembly (MonoAssembly
*assembly
)
10940 guint32 idx
= 1; /* there is only one assembly */
10941 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
10942 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
10943 return mono_declsec_get_flags (assembly
->image
, idx
);
10948 * Fill actions for the specific index (which may either be an encoded class token or
10949 * an encoded method token) from the metadata image.
10950 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
10953 fill_actions_from_index (MonoImage
*image
, guint32 token
, MonoDeclSecurityActions
* actions
,
10954 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
10956 MonoBoolean result
= FALSE
;
10958 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
10959 int index
= mono_metadata_declsec_from_index (image
, token
);
10962 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
10963 for (i
= index
; i
< t
->rows
; i
++) {
10964 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
10966 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
10969 /* if present only replace (class) permissions with method permissions */
10970 /* if empty accept either class or method permissions */
10971 if (cols
[MONO_DECL_SECURITY_ACTION
] == id_std
) {
10972 if (!actions
->demand
.blob
) {
10973 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
10974 actions
->demand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
10975 actions
->demand
.blob
= (char*) (blob
+ 2);
10976 actions
->demand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
10979 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_noncas
) {
10980 if (!actions
->noncasdemand
.blob
) {
10981 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
10982 actions
->noncasdemand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
10983 actions
->noncasdemand
.blob
= (char*) (blob
+ 2);
10984 actions
->noncasdemand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
10987 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_choice
) {
10988 if (!actions
->demandchoice
.blob
) {
10989 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
10990 actions
->demandchoice
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
10991 actions
->demandchoice
.blob
= (char*) (blob
+ 2);
10992 actions
->demandchoice
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11002 mono_declsec_get_class_demands_params (MonoClass
*klass
, MonoDeclSecurityActions
* demands
,
11003 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11005 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
11006 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11007 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11008 return fill_actions_from_index (klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
11012 mono_declsec_get_method_demands_params (MonoMethod
*method
, MonoDeclSecurityActions
* demands
,
11013 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11015 guint32 idx
= mono_method_get_index (method
);
11016 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11017 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11018 return fill_actions_from_index (method
->klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
11022 * Collect all actions (that requires to generate code in mini) assigned for
11023 * the specified method.
11024 * Note: Don't use the content of actions if the function return FALSE.
11027 mono_declsec_get_demands (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
11029 guint32 mask
= MONO_DECLSEC_FLAG_DEMAND
| MONO_DECLSEC_FLAG_NONCAS_DEMAND
|
11030 MONO_DECLSEC_FLAG_DEMAND_CHOICE
;
11031 MonoBoolean result
= FALSE
;
11034 /* quick exit if no declarative security is present in the metadata */
11035 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11038 /* we want the original as the wrapper is "free" of the security informations */
11039 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11040 method
= mono_marshal_method_from_wrapper (method
);
11045 /* First we look for method-level attributes */
11046 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11047 mono_class_init (method
->klass
);
11048 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11050 result
= mono_declsec_get_method_demands_params (method
, demands
,
11051 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
11054 /* Here we use (or create) the class declarative cache to look for demands */
11055 flags
= mono_declsec_flags_from_class (method
->klass
);
11056 if (flags
& mask
) {
11058 mono_class_init (method
->klass
);
11059 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11061 result
|= mono_declsec_get_class_demands_params (method
->klass
, demands
,
11062 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
11065 /* The boolean return value is used as a shortcut in case nothing needs to
11066 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11072 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11074 * Note: Don't use the content of actions if the function return FALSE.
11077 mono_declsec_get_linkdemands (MonoMethod
*method
, MonoDeclSecurityActions
* klass
, MonoDeclSecurityActions
*cmethod
)
11079 MonoBoolean result
= FALSE
;
11082 /* quick exit if no declarative security is present in the metadata */
11083 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11086 /* we want the original as the wrapper is "free" of the security informations */
11087 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11088 method
= mono_marshal_method_from_wrapper (method
);
11093 /* results are independant - zeroize both */
11094 memset (cmethod
, 0, sizeof (MonoDeclSecurityActions
));
11095 memset (klass
, 0, sizeof (MonoDeclSecurityActions
));
11097 /* First we look for method-level attributes */
11098 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11099 mono_class_init (method
->klass
);
11101 result
= mono_declsec_get_method_demands_params (method
, cmethod
,
11102 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
11105 /* Here we use (or create) the class declarative cache to look for demands */
11106 flags
= mono_declsec_flags_from_class (method
->klass
);
11107 if (flags
& (MONO_DECLSEC_FLAG_LINKDEMAND
| MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
| MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
)) {
11108 mono_class_init (method
->klass
);
11110 result
|= mono_declsec_get_class_demands_params (method
->klass
, klass
,
11111 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
11118 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11120 * @klass The inherited class - this is the class that provides the security check (attributes)
11122 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11124 * Note: Don't use the content of actions if the function return FALSE.
11127 mono_declsec_get_inheritdemands_class (MonoClass
*klass
, MonoDeclSecurityActions
* demands
)
11129 MonoBoolean result
= FALSE
;
11132 /* quick exit if no declarative security is present in the metadata */
11133 if (!klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11136 /* Here we use (or create) the class declarative cache to look for demands */
11137 flags
= mono_declsec_flags_from_class (klass
);
11138 if (flags
& (MONO_DECLSEC_FLAG_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
)) {
11139 mono_class_init (klass
);
11140 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11142 result
|= mono_declsec_get_class_demands_params (klass
, demands
,
11143 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
11150 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11152 * Note: Don't use the content of actions if the function return FALSE.
11155 mono_declsec_get_inheritdemands_method (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
11157 /* quick exit if no declarative security is present in the metadata */
11158 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11161 /* we want the original as the wrapper is "free" of the security informations */
11162 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11163 method
= mono_marshal_method_from_wrapper (method
);
11168 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11169 mono_class_init (method
->klass
);
11170 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11172 return mono_declsec_get_method_demands_params (method
, demands
,
11173 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
11180 get_declsec_action (MonoImage
*image
, guint32 token
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11182 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11186 int index
= mono_metadata_declsec_from_index (image
, token
);
11190 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11191 for (i
= index
; i
< t
->rows
; i
++) {
11192 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11194 /* shortcut - index are ordered */
11195 if (token
!= cols
[MONO_DECL_SECURITY_PARENT
])
11198 if (cols
[MONO_DECL_SECURITY_ACTION
] == action
) {
11199 const char *metadata
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11200 entry
->blob
= (char*) (metadata
+ 2);
11201 entry
->size
= mono_metadata_decode_blob_size (metadata
, &metadata
);
11210 mono_declsec_get_method_action (MonoMethod
*method
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11212 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11213 guint32 idx
= mono_method_get_index (method
);
11214 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11215 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11216 return get_declsec_action (method
->klass
->image
, idx
, action
, entry
);
11222 mono_declsec_get_class_action (MonoClass
*klass
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11225 guint32 flags
= mono_declsec_flags_from_class (klass
);
11226 if (declsec_flags_map
[action
] & flags
) {
11227 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
11228 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11229 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11230 return get_declsec_action (klass
->image
, idx
, action
, entry
);
11236 mono_declsec_get_assembly_action (MonoAssembly
*assembly
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11238 guint32 idx
= 1; /* there is only one assembly */
11239 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11240 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
11242 return get_declsec_action (assembly
->image
, idx
, action
, entry
);
11246 mono_reflection_call_is_assignable_to (MonoClass
*klass
, MonoClass
*oklass
)
11248 MonoObject
*res
, *exc
;
11250 static MonoClass
*System_Reflection_Emit_TypeBuilder
= NULL
;
11251 static MonoMethod
*method
= NULL
;
11253 if (!System_Reflection_Emit_TypeBuilder
) {
11254 System_Reflection_Emit_TypeBuilder
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection.Emit", "TypeBuilder");
11255 g_assert (System_Reflection_Emit_TypeBuilder
);
11257 if (method
== NULL
) {
11258 method
= mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder
, "IsAssignableTo", 1);
11263 * The result of mono_type_get_object () might be a System.MonoType but we
11264 * need a TypeBuilder so use klass->reflection_info.
11266 g_assert (klass
->reflection_info
);
11267 g_assert (!strcmp (((MonoObject
*)(klass
->reflection_info
))->vtable
->klass
->name
, "TypeBuilder"));
11269 params
[0] = mono_type_get_object (mono_domain_get (), &oklass
->byval_arg
);
11271 res
= mono_runtime_invoke (method
, (MonoObject
*)(klass
->reflection_info
), params
, &exc
);
11275 return *(MonoBoolean
*)mono_object_unbox (res
);