2 * reflection.c: Routines for creating an image at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 #include "mono/utils/mono-digest.h"
13 #include "mono/utils/mono-membar.h"
14 #include "mono/metadata/reflection.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/metadata-internals.h"
17 #include <mono/metadata/profiler-private.h>
18 #include "mono/metadata/class-internals.h"
19 #include "mono/metadata/gc-internal.h"
20 #include "mono/metadata/tokentype.h"
21 #include "mono/metadata/domain-internals.h"
22 #include "mono/metadata/opcodes.h"
23 #include "mono/metadata/assembly.h"
24 #include "mono/metadata/object-internals.h"
25 #include <mono/metadata/exception.h>
26 #include <mono/metadata/marshal.h>
27 #include <mono/metadata/security-manager.h>
36 #include "mono-endian.h"
37 #include <mono/metadata/gc-internal.h>
38 #include <mono/metadata/mempool-internals.h>
39 #include <mono/metadata/security-core-clr.h>
42 static void* reflection_info_desc
= NULL
;
43 #define MOVING_GC_REGISTER(addr) do { \
44 if (!reflection_info_desc) { \
46 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
48 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
51 #define MOVING_GC_REGISTER(addr)
60 #define TEXT_OFFSET 512
61 #define CLI_H_SIZE 136
62 #define FILE_ALIGN 512
63 #define VIRT_ALIGN 8192
64 #define START_TEXT_RVA 0x00002000
67 MonoReflectionILGen
*ilgen
;
68 MonoReflectionType
*rtype
;
69 MonoArray
*parameters
;
70 MonoArray
*generic_params
;
71 MonoGenericContainer
*generic_container
;
77 guint32
*table_idx
; /* note: it's a pointer */
81 MonoBoolean init_locals
;
82 MonoBoolean skip_visibility
;
83 MonoArray
*return_modreq
;
84 MonoArray
*return_modopt
;
85 MonoArray
*param_modreq
;
86 MonoArray
*param_modopt
;
87 MonoArray
*permissions
;
92 int charset
, extra_flags
, native_cc
;
93 MonoString
*dll
, *dllentry
;
94 } ReflectionMethodBuilder
;
98 MonoReflectionGenericParam
*gparam
;
99 } GenericParamTableEntry
;
101 const unsigned char table_sizes
[MONO_TABLE_NUM
] = {
111 MONO_INTERFACEIMPL_SIZE
,
112 MONO_MEMBERREF_SIZE
, /* 0x0A */
114 MONO_CUSTOM_ATTR_SIZE
,
115 MONO_FIELD_MARSHAL_SIZE
,
116 MONO_DECL_SECURITY_SIZE
,
117 MONO_CLASS_LAYOUT_SIZE
,
118 MONO_FIELD_LAYOUT_SIZE
, /* 0x10 */
119 MONO_STAND_ALONE_SIGNATURE_SIZE
,
123 MONO_PROPERTY_MAP_SIZE
,
126 MONO_METHOD_SEMA_SIZE
,
127 MONO_METHODIMPL_SIZE
,
128 MONO_MODULEREF_SIZE
, /* 0x1A */
134 MONO_ASSEMBLY_SIZE
, /* 0x20 */
135 MONO_ASSEMBLY_PROCESSOR_SIZE
,
136 MONO_ASSEMBLYOS_SIZE
,
137 MONO_ASSEMBLYREF_SIZE
,
138 MONO_ASSEMBLYREFPROC_SIZE
,
139 MONO_ASSEMBLYREFOS_SIZE
,
143 MONO_NESTED_CLASS_SIZE
,
145 MONO_GENERICPARAM_SIZE
, /* 0x2A */
146 MONO_METHODSPEC_SIZE
,
147 MONO_GENPARCONSTRAINT_SIZE
151 #ifndef DISABLE_REFLECTION_EMIT
152 static guint32
mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
);
153 static guint32
mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
);
154 static guint32
mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*cb
);
155 static guint32
mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
);
156 static void ensure_runtime_vtable (MonoClass
*klass
);
157 static gpointer
resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
);
158 static guint32
mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
);
159 static guint32
encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
);
160 static gpointer
register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
);
163 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
);
164 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
);
165 static guint32
mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
);
166 static guint32
mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
);
167 static void mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
);
168 static guint32
encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
);
169 static guint32
encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
);
170 static char* type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
);
171 static void encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
);
172 static void get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
);
173 static MonoObject
*mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
);
174 static MonoReflectionType
*mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
);
175 static MonoType
* mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
);
178 mono_reflection_init (void)
183 sigbuffer_init (SigBuffer
*buf
, int size
)
185 buf
->buf
= g_malloc (size
);
187 buf
->end
= buf
->buf
+ size
;
191 sigbuffer_make_room (SigBuffer
*buf
, int size
)
193 if (buf
->end
- buf
->p
< size
) {
194 int new_size
= buf
->end
- buf
->buf
+ size
+ 32;
195 char *p
= g_realloc (buf
->buf
, new_size
);
196 size
= buf
->p
- buf
->buf
;
199 buf
->end
= buf
->buf
+ new_size
;
204 sigbuffer_add_value (SigBuffer
*buf
, guint32 val
)
206 sigbuffer_make_room (buf
, 6);
207 mono_metadata_encode_value (val
, buf
->p
, &buf
->p
);
211 sigbuffer_add_byte (SigBuffer
*buf
, guint8 val
)
213 sigbuffer_make_room (buf
, 1);
219 sigbuffer_add_mem (SigBuffer
*buf
, char *p
, guint32 size
)
221 sigbuffer_make_room (buf
, size
);
222 memcpy (buf
->p
, p
, size
);
227 sigbuffer_free (SigBuffer
*buf
)
232 #ifndef DISABLE_REFLECTION_EMIT
236 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
240 image_g_malloc (MonoImage
*image
, guint size
)
243 return mono_image_alloc (image
, size
);
245 return g_malloc (size
);
247 #endif /* !DISABLE_REFLECTION_EMIT */
252 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
256 image_g_malloc0 (MonoImage
*image
, guint size
)
259 return mono_image_alloc0 (image
, size
);
261 return g_malloc0 (size
);
264 #ifndef DISABLE_REFLECTION_EMIT
266 image_strdup (MonoImage
*image
, const char *s
)
269 return mono_image_strdup (image
, s
);
275 #define image_g_new(image,struct_type, n_structs) \
276 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
278 #define image_g_new0(image,struct_type, n_structs) \
279 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
283 alloc_table (MonoDynamicTable
*table
, guint nrows
)
286 g_assert (table
->columns
);
287 if (nrows
+ 1 >= table
->alloc_rows
) {
288 while (nrows
+ 1 >= table
->alloc_rows
) {
289 if (table
->alloc_rows
== 0)
290 table
->alloc_rows
= 16;
292 table
->alloc_rows
*= 2;
295 table
->values
= g_renew (guint32
, table
->values
, (table
->alloc_rows
) * table
->columns
);
300 make_room_in_stream (MonoDynamicStream
*stream
, int size
)
302 if (size
<= stream
->alloc_size
)
305 while (stream
->alloc_size
<= size
) {
306 if (stream
->alloc_size
< 4096)
307 stream
->alloc_size
= 4096;
309 stream
->alloc_size
*= 2;
312 stream
->data
= g_realloc (stream
->data
, stream
->alloc_size
);
316 string_heap_insert (MonoDynamicStream
*sh
, const char *str
)
320 gpointer oldkey
, oldval
;
322 if (g_hash_table_lookup_extended (sh
->hash
, str
, &oldkey
, &oldval
))
323 return GPOINTER_TO_UINT (oldval
);
325 len
= strlen (str
) + 1;
328 make_room_in_stream (sh
, idx
+ len
);
331 * We strdup the string even if we already copy them in sh->data
332 * so that the string pointers in the hash remain valid even if
333 * we need to realloc sh->data. We may want to avoid that later.
335 g_hash_table_insert (sh
->hash
, g_strdup (str
), GUINT_TO_POINTER (idx
));
336 memcpy (sh
->data
+ idx
, str
, len
);
342 string_heap_insert_mstring (MonoDynamicStream
*sh
, MonoString
*str
)
344 char *name
= mono_string_to_utf8 (str
);
346 idx
= string_heap_insert (sh
, name
);
351 #ifndef DISABLE_REFLECTION_EMIT
353 string_heap_init (MonoDynamicStream
*sh
)
356 sh
->alloc_size
= 4096;
357 sh
->data
= g_malloc (4096);
358 sh
->hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
359 string_heap_insert (sh
, "");
364 mono_image_add_stream_data (MonoDynamicStream
*stream
, const char *data
, guint32 len
)
368 make_room_in_stream (stream
, stream
->index
+ len
);
369 memcpy (stream
->data
+ stream
->index
, data
, len
);
371 stream
->index
+= len
;
373 * align index? Not without adding an additional param that controls it since
374 * we may store a blob value in pieces.
380 mono_image_add_stream_zero (MonoDynamicStream
*stream
, guint32 len
)
384 make_room_in_stream (stream
, stream
->index
+ len
);
385 memset (stream
->data
+ stream
->index
, 0, len
);
387 stream
->index
+= len
;
392 stream_data_align (MonoDynamicStream
*stream
)
395 guint32 count
= stream
->index
% 4;
397 /* we assume the stream data will be aligned */
399 mono_image_add_stream_data (stream
, buf
, 4 - count
);
402 #ifndef DISABLE_REFLECTION_EMIT
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 #ifndef DISABLE_REFLECTION_EMIT
536 default_class_from_mono_type (MonoType
*type
)
538 switch (type
->type
) {
539 case MONO_TYPE_OBJECT
:
540 return mono_defaults
.object_class
;
542 return mono_defaults
.void_class
;
543 case MONO_TYPE_BOOLEAN
:
544 return mono_defaults
.boolean_class
;
546 return mono_defaults
.char_class
;
548 return mono_defaults
.sbyte_class
;
550 return mono_defaults
.byte_class
;
552 return mono_defaults
.int16_class
;
554 return mono_defaults
.uint16_class
;
556 return mono_defaults
.int32_class
;
558 return mono_defaults
.uint32_class
;
560 return mono_defaults
.int_class
;
562 return mono_defaults
.uint_class
;
564 return mono_defaults
.int64_class
;
566 return mono_defaults
.uint64_class
;
568 return mono_defaults
.single_class
;
570 return mono_defaults
.double_class
;
571 case MONO_TYPE_STRING
:
572 return mono_defaults
.string_class
;
574 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type
->type
);
575 g_assert_not_reached ();
583 encode_generic_class (MonoDynamicImage
*assembly
, MonoGenericClass
*gclass
, SigBuffer
*buf
)
586 MonoGenericInst
*class_inst
;
591 class_inst
= gclass
->context
.class_inst
;
593 sigbuffer_add_value (buf
, MONO_TYPE_GENERICINST
);
594 klass
= gclass
->container_class
;
595 sigbuffer_add_value (buf
, klass
->byval_arg
.type
);
596 sigbuffer_add_value (buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
598 sigbuffer_add_value (buf
, class_inst
->type_argc
);
599 for (i
= 0; i
< class_inst
->type_argc
; ++i
)
600 encode_type (assembly
, class_inst
->type_argv
[i
], buf
);
605 encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
)
608 g_assert_not_reached ();
613 sigbuffer_add_value (buf
, MONO_TYPE_BYREF
);
617 case MONO_TYPE_BOOLEAN
:
631 case MONO_TYPE_STRING
:
632 case MONO_TYPE_OBJECT
:
633 case MONO_TYPE_TYPEDBYREF
:
634 sigbuffer_add_value (buf
, type
->type
);
637 sigbuffer_add_value (buf
, type
->type
);
638 encode_type (assembly
, type
->data
.type
, buf
);
640 case MONO_TYPE_SZARRAY
:
641 sigbuffer_add_value (buf
, type
->type
);
642 encode_type (assembly
, &type
->data
.klass
->byval_arg
, buf
);
644 case MONO_TYPE_VALUETYPE
:
645 case MONO_TYPE_CLASS
: {
646 MonoClass
*k
= mono_class_from_mono_type (type
);
648 if (k
->generic_container
) {
649 MonoGenericClass
*gclass
= mono_metadata_lookup_generic_class (k
, k
->generic_container
->context
.class_inst
, TRUE
);
650 encode_generic_class (assembly
, gclass
, buf
);
653 * Make sure we use the correct type.
655 sigbuffer_add_value (buf
, k
->byval_arg
.type
);
657 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
658 * otherwise two typerefs could point to the same type, leading to
659 * verification errors.
661 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, &k
->byval_arg
));
665 case MONO_TYPE_ARRAY
:
666 sigbuffer_add_value (buf
, type
->type
);
667 encode_type (assembly
, &type
->data
.array
->eklass
->byval_arg
, buf
);
668 sigbuffer_add_value (buf
, type
->data
.array
->rank
);
669 sigbuffer_add_value (buf
, 0); /* FIXME: set to 0 for now */
670 sigbuffer_add_value (buf
, 0);
672 case MONO_TYPE_GENERICINST
:
673 encode_generic_class (assembly
, type
->data
.generic_class
, buf
);
677 sigbuffer_add_value (buf
, type
->type
);
678 sigbuffer_add_value (buf
, mono_type_get_generic_param_num (type
));
681 g_error ("need to encode type %x", type
->type
);
686 encode_reflection_type (MonoDynamicImage
*assembly
, MonoReflectionType
*type
, SigBuffer
*buf
)
689 sigbuffer_add_value (buf
, MONO_TYPE_VOID
);
694 ((type
= mono_reflection_type_get_underlying_system_type (type
)) && type
->type
)) {
695 encode_type (assembly
, type
->type
, buf
);
699 g_assert_not_reached ();
704 encode_custom_modifiers (MonoDynamicImage
*assembly
, MonoArray
*modreq
, MonoArray
*modopt
, SigBuffer
*buf
)
709 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
710 MonoReflectionType
*mod
= mono_type_array_get (modreq
, i
);
711 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_REQD
);
712 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
->type
));
716 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
717 MonoReflectionType
*mod
= mono_type_array_get (modopt
, i
);
718 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_OPT
);
719 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
->type
));
724 #ifndef DISABLE_REFLECTION_EMIT
726 method_encode_signature (MonoDynamicImage
*assembly
, MonoMethodSignature
*sig
)
730 guint32 nparams
= sig
->param_count
;
736 sigbuffer_init (&buf
, 32);
738 * FIXME: vararg, explicit_this, differenc call_conv values...
740 idx
= sig
->call_convention
;
742 idx
|= 0x20; /* hasthis */
743 if (sig
->generic_param_count
)
744 idx
|= 0x10; /* generic */
745 sigbuffer_add_byte (&buf
, idx
);
746 if (sig
->generic_param_count
)
747 sigbuffer_add_value (&buf
, sig
->generic_param_count
);
748 sigbuffer_add_value (&buf
, nparams
);
749 encode_type (assembly
, sig
->ret
, &buf
);
750 for (i
= 0; i
< nparams
; ++i
) {
751 if (i
== sig
->sentinelpos
)
752 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
753 encode_type (assembly
, sig
->params
[i
], &buf
);
755 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
756 sigbuffer_free (&buf
);
762 method_builder_encode_signature (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
765 * FIXME: reuse code from method_encode_signature().
769 guint32 nparams
= mb
->parameters
? mono_array_length (mb
->parameters
): 0;
770 guint32 ngparams
= mb
->generic_params
? mono_array_length (mb
->generic_params
): 0;
771 guint32 notypes
= mb
->opt_types
? mono_array_length (mb
->opt_types
): 0;
774 sigbuffer_init (&buf
, 32);
775 /* LAMESPEC: all the call conv spec is foobared */
776 idx
= mb
->call_conv
& 0x60; /* has-this, explicit-this */
777 if (mb
->call_conv
& 2)
778 idx
|= 0x5; /* vararg */
779 if (!(mb
->attrs
& METHOD_ATTRIBUTE_STATIC
))
780 idx
|= 0x20; /* hasthis */
782 idx
|= 0x10; /* generic */
783 sigbuffer_add_byte (&buf
, idx
);
785 sigbuffer_add_value (&buf
, ngparams
);
786 sigbuffer_add_value (&buf
, nparams
+ notypes
);
787 encode_custom_modifiers (assembly
, mb
->return_modreq
, mb
->return_modopt
, &buf
);
788 encode_reflection_type (assembly
, mb
->rtype
, &buf
);
789 for (i
= 0; i
< nparams
; ++i
) {
790 MonoArray
*modreq
= NULL
;
791 MonoArray
*modopt
= NULL
;
792 MonoReflectionType
*pt
;
794 if (mb
->param_modreq
&& (i
< mono_array_length (mb
->param_modreq
)))
795 modreq
= mono_array_get (mb
->param_modreq
, MonoArray
*, i
);
796 if (mb
->param_modopt
&& (i
< mono_array_length (mb
->param_modopt
)))
797 modopt
= mono_array_get (mb
->param_modopt
, MonoArray
*, i
);
798 encode_custom_modifiers (assembly
, modreq
, modopt
, &buf
);
799 pt
= mono_type_array_get (mb
->parameters
, i
);
800 encode_reflection_type (assembly
, pt
, &buf
);
803 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
804 for (i
= 0; i
< notypes
; ++i
) {
805 MonoReflectionType
*pt
;
807 pt
= mono_type_array_get (mb
->opt_types
, i
);
808 encode_reflection_type (assembly
, pt
, &buf
);
811 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
812 sigbuffer_free (&buf
);
817 encode_locals (MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
)
819 MonoDynamicTable
*table
;
821 guint32 idx
, sig_idx
;
822 guint nl
= mono_array_length (ilgen
->locals
);
826 sigbuffer_init (&buf
, 32);
827 sigbuffer_add_value (&buf
, 0x07);
828 sigbuffer_add_value (&buf
, nl
);
829 for (i
= 0; i
< nl
; ++i
) {
830 MonoReflectionLocalBuilder
*lb
= mono_array_get (ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
833 sigbuffer_add_value (&buf
, MONO_TYPE_PINNED
);
835 encode_reflection_type (assembly
, monotype_cast (lb
->type
), &buf
);
837 sig_idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
838 sigbuffer_free (&buf
);
840 if (assembly
->standalonesig_cache
== NULL
)
841 assembly
->standalonesig_cache
= g_hash_table_new (NULL
, NULL
);
842 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
)));
846 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
847 idx
= table
->next_idx
++;
849 alloc_table (table
, table
->rows
);
850 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
852 values
[MONO_STAND_ALONE_SIGNATURE
] = sig_idx
;
854 g_hash_table_insert (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
), GUINT_TO_POINTER (idx
));
860 method_count_clauses (MonoReflectionILGen
*ilgen
)
862 guint32 num_clauses
= 0;
865 MonoILExceptionInfo
*ex_info
;
866 for (i
= 0; i
< mono_array_length (ilgen
->ex_handlers
); ++i
) {
867 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
868 if (ex_info
->handlers
)
869 num_clauses
+= mono_array_length (ex_info
->handlers
);
877 #ifndef DISABLE_REFLECTION_EMIT
878 static MonoExceptionClause
*
879 method_encode_clauses (MonoImage
*image
, MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
, guint32 num_clauses
)
881 MonoExceptionClause
*clauses
;
882 MonoExceptionClause
*clause
;
883 MonoILExceptionInfo
*ex_info
;
884 MonoILExceptionBlock
*ex_block
;
885 guint32 finally_start
;
886 int i
, j
, clause_index
;;
888 clauses
= image_g_new0 (image
, MonoExceptionClause
, num_clauses
);
891 for (i
= mono_array_length (ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
892 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
893 finally_start
= ex_info
->start
+ ex_info
->len
;
894 if (!ex_info
->handlers
)
896 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
897 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
898 clause
= &(clauses
[clause_index
]);
900 clause
->flags
= ex_block
->type
;
901 clause
->try_offset
= ex_info
->start
;
903 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
904 clause
->try_len
= finally_start
- ex_info
->start
;
906 clause
->try_len
= ex_info
->len
;
907 clause
->handler_offset
= ex_block
->start
;
908 clause
->handler_len
= ex_block
->len
;
909 if (ex_block
->extype
) {
910 clause
->data
.catch_class
= mono_class_from_mono_type (monotype_cast (ex_block
->extype
)->type
);
912 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
913 clause
->data
.filter_offset
= ex_block
->filter_offset
;
915 clause
->data
.filter_offset
= 0;
917 finally_start
= ex_block
->start
+ ex_block
->len
;
925 #endif /* !DISABLE_REFLECTION_EMIT */
928 method_encode_code (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
934 gint32 num_locals
= 0;
935 gint32 num_exception
= 0;
938 char fat_header
[12];
941 guint32 local_sig
= 0;
942 guint32 header_size
= 12;
945 if ((mb
->attrs
& (METHOD_ATTRIBUTE_PINVOKE_IMPL
| METHOD_ATTRIBUTE_ABSTRACT
)) ||
946 (mb
->iattrs
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)))
950 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
952 code
= mb
->ilgen
->code
;
953 code_size
= mb
->ilgen
->code_len
;
954 max_stack
= mb
->ilgen
->max_stack
;
955 num_locals
= mb
->ilgen
->locals
? mono_array_length (mb
->ilgen
->locals
) : 0;
956 if (mb
->ilgen
->ex_handlers
)
957 num_exception
= method_count_clauses (mb
->ilgen
);
961 char *name
= mono_string_to_utf8 (mb
->name
);
962 char *str
= g_strdup_printf ("Method %s does not have any IL associated", name
);
963 MonoException
*exception
= mono_get_exception_argument (NULL
, "a method does not have any IL associated");
966 mono_raise_exception (exception
);
969 code_size
= mono_array_length (code
);
970 max_stack
= 8; /* we probably need to run a verifier on the code... */
973 stream_data_align (&assembly
->code
);
975 /* check for exceptions, maxstack, locals */
976 maybe_small
= (max_stack
<= 8) && (!num_locals
) && (!num_exception
);
978 if (code_size
< 64 && !(code_size
& 1)) {
979 flags
= (code_size
<< 2) | 0x2;
980 } else if (code_size
< 32 && (code_size
& 1)) {
981 flags
= (code_size
<< 2) | 0x6; /* LAMESPEC: see metadata.c */
985 idx
= mono_image_add_stream_data (&assembly
->code
, &flags
, 1);
986 /* add to the fixup todo list */
987 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
988 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 1));
989 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
990 return assembly
->text_rva
+ idx
;
994 local_sig
= MONO_TOKEN_SIGNATURE
| encode_locals (assembly
, mb
->ilgen
);
996 * FIXME: need to set also the header size in fat_flags.
997 * (and more sects and init locals flags)
1001 fat_flags
|= METHOD_HEADER_MORE_SECTS
;
1002 if (mb
->init_locals
)
1003 fat_flags
|= METHOD_HEADER_INIT_LOCALS
;
1004 fat_header
[0] = fat_flags
;
1005 fat_header
[1] = (header_size
/ 4 ) << 4;
1006 short_value
= GUINT16_TO_LE (max_stack
);
1007 memcpy (fat_header
+ 2, &short_value
, 2);
1008 int_value
= GUINT32_TO_LE (code_size
);
1009 memcpy (fat_header
+ 4, &int_value
, 4);
1010 int_value
= GUINT32_TO_LE (local_sig
);
1011 memcpy (fat_header
+ 8, &int_value
, 4);
1012 idx
= mono_image_add_stream_data (&assembly
->code
, fat_header
, 12);
1013 /* add to the fixup todo list */
1014 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1015 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 12));
1017 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1018 if (num_exception
) {
1019 unsigned char sheader
[4];
1020 MonoILExceptionInfo
* ex_info
;
1021 MonoILExceptionBlock
* ex_block
;
1024 stream_data_align (&assembly
->code
);
1025 /* always use fat format for now */
1026 sheader
[0] = METHOD_HEADER_SECTION_FAT_FORMAT
| METHOD_HEADER_SECTION_EHTABLE
;
1027 num_exception
*= 6 * sizeof (guint32
);
1028 num_exception
+= 4; /* include the size of the header */
1029 sheader
[1] = num_exception
& 0xff;
1030 sheader
[2] = (num_exception
>> 8) & 0xff;
1031 sheader
[3] = (num_exception
>> 16) & 0xff;
1032 mono_image_add_stream_data (&assembly
->code
, (char*)sheader
, 4);
1033 /* fat header, so we are already aligned */
1035 for (i
= mono_array_length (mb
->ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
1036 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (mb
->ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
1037 if (ex_info
->handlers
) {
1038 int finally_start
= ex_info
->start
+ ex_info
->len
;
1039 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
1041 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
1043 val
= GUINT32_TO_LE (ex_block
->type
);
1044 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1046 val
= GUINT32_TO_LE (ex_info
->start
);
1047 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1048 /* need fault, too, probably */
1049 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
1050 val
= GUINT32_TO_LE (finally_start
- ex_info
->start
);
1052 val
= GUINT32_TO_LE (ex_info
->len
);
1053 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1054 /* handler offset */
1055 val
= GUINT32_TO_LE (ex_block
->start
);
1056 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1058 val
= GUINT32_TO_LE (ex_block
->len
);
1059 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1060 finally_start
= ex_block
->start
+ ex_block
->len
;
1061 if (ex_block
->extype
) {
1062 val
= mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly
, monotype_cast (ex_block
->extype
)->type
));
1064 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
1065 val
= ex_block
->filter_offset
;
1069 val
= GUINT32_TO_LE (val
);
1070 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1071 /*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",
1072 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);*/
1075 g_error ("No clauses for ex info block %d", i
);
1079 return assembly
->text_rva
+ idx
;
1083 find_index_in_table (MonoDynamicImage
*assembly
, int table_idx
, int col
, guint32 token
)
1086 MonoDynamicTable
*table
;
1089 table
= &assembly
->tables
[table_idx
];
1091 g_assert (col
< table
->columns
);
1093 values
= table
->values
+ table
->columns
;
1094 for (i
= 1; i
<= table
->rows
; ++i
) {
1095 if (values
[col
] == token
)
1097 values
+= table
->columns
;
1103 * LOCKING: Acquires the loader lock.
1105 static MonoCustomAttrInfo
*
1106 lookup_custom_attr (MonoImage
*image
, gpointer member
)
1108 MonoCustomAttrInfo
* res
;
1110 res
= mono_image_property_lookup (image
, member
, MONO_PROP_DYNAMIC_CATTR
);
1115 return g_memdup (res
, sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (res
->num_attrs
- MONO_ZERO_LEN_ARRAY
));
1119 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttr
*cattr
)
1121 /* FIXME: Need to do more checks */
1122 if (cattr
->ctor
->method
&& (cattr
->ctor
->method
->klass
->image
!= image
)) {
1123 int visibility
= cattr
->ctor
->method
->klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
1125 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
1132 static MonoCustomAttrInfo
*
1133 mono_custom_attrs_from_builders (MonoImage
*alloc_img
, MonoImage
*image
, MonoArray
*cattrs
)
1135 int i
, index
, count
, not_visible
;
1136 MonoCustomAttrInfo
*ainfo
;
1137 MonoReflectionCustomAttr
*cattr
;
1141 /* FIXME: check in assembly the Run flag is set */
1143 count
= mono_array_length (cattrs
);
1145 /* Skip nonpublic attributes since MS.NET seems to do the same */
1146 /* FIXME: This needs to be done more globally */
1148 for (i
= 0; i
< count
; ++i
) {
1149 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1150 if (!custom_attr_visible (image
, cattr
))
1153 count
-= not_visible
;
1155 ainfo
= image_g_malloc0 (alloc_img
, sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (count
- MONO_ZERO_LEN_ARRAY
));
1157 ainfo
->image
= image
;
1158 ainfo
->num_attrs
= count
;
1159 ainfo
->cached
= alloc_img
!= NULL
;
1161 for (i
= 0; i
< count
; ++i
) {
1162 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1163 if (custom_attr_visible (image
, cattr
)) {
1164 unsigned char *saved
= mono_image_alloc (image
, mono_array_length (cattr
->data
));
1165 memcpy (saved
, mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1166 ainfo
->attrs
[index
].ctor
= cattr
->ctor
->method
;
1167 ainfo
->attrs
[index
].data
= saved
;
1168 ainfo
->attrs
[index
].data_size
= mono_array_length (cattr
->data
);
1176 #ifndef DISABLE_REFLECTION_EMIT
1178 * LOCKING: Acquires the loader lock.
1181 mono_save_custom_attrs (MonoImage
*image
, void *obj
, MonoArray
*cattrs
)
1183 MonoCustomAttrInfo
*ainfo
, *tmp
;
1185 if (!cattrs
|| !mono_array_length (cattrs
))
1188 ainfo
= mono_custom_attrs_from_builders (image
, image
, cattrs
);
1190 mono_loader_lock ();
1191 tmp
= mono_image_property_lookup (image
, obj
, MONO_PROP_DYNAMIC_CATTR
);
1193 mono_custom_attrs_free (tmp
);
1194 mono_image_property_insert (image
, obj
, MONO_PROP_DYNAMIC_CATTR
, ainfo
);
1195 mono_loader_unlock ();
1201 mono_custom_attrs_free (MonoCustomAttrInfo
*ainfo
)
1208 * idx is the table index of the object
1209 * type is one of MONO_CUSTOM_ATTR_*
1212 mono_image_add_cattrs (MonoDynamicImage
*assembly
, guint32 idx
, guint32 type
, MonoArray
*cattrs
)
1214 MonoDynamicTable
*table
;
1215 MonoReflectionCustomAttr
*cattr
;
1217 guint32 count
, i
, token
;
1219 char *p
= blob_size
;
1221 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1224 count
= mono_array_length (cattrs
);
1225 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1226 table
->rows
+= count
;
1227 alloc_table (table
, table
->rows
);
1228 values
= table
->values
+ table
->next_idx
* MONO_CUSTOM_ATTR_SIZE
;
1229 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1231 for (i
= 0; i
< count
; ++i
) {
1232 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1233 values
[MONO_CUSTOM_ATTR_PARENT
] = idx
;
1234 token
= mono_image_create_token (assembly
, (MonoObject
*)cattr
->ctor
, FALSE
, FALSE
);
1235 type
= mono_metadata_token_index (token
);
1236 type
<<= MONO_CUSTOM_ATTR_TYPE_BITS
;
1237 switch (mono_metadata_token_table (token
)) {
1238 case MONO_TABLE_METHOD
:
1239 type
|= MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
1241 case MONO_TABLE_MEMBERREF
:
1242 type
|= MONO_CUSTOM_ATTR_TYPE_MEMBERREF
;
1245 g_warning ("got wrong token in custom attr");
1248 values
[MONO_CUSTOM_ATTR_TYPE
] = type
;
1250 mono_metadata_encode_value (mono_array_length (cattr
->data
), p
, &p
);
1251 values
[MONO_CUSTOM_ATTR_VALUE
] = add_to_blob_cached (assembly
, blob_size
, p
- blob_size
,
1252 mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1253 values
+= MONO_CUSTOM_ATTR_SIZE
;
1259 mono_image_add_decl_security (MonoDynamicImage
*assembly
, guint32 parent_token
, MonoArray
*permissions
)
1261 MonoDynamicTable
*table
;
1263 guint32 count
, i
, idx
;
1264 MonoReflectionPermissionSet
*perm
;
1269 count
= mono_array_length (permissions
);
1270 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
1271 table
->rows
+= count
;
1272 alloc_table (table
, table
->rows
);
1274 for (i
= 0; i
< mono_array_length (permissions
); ++i
) {
1275 perm
= (MonoReflectionPermissionSet
*)mono_array_addr (permissions
, MonoReflectionPermissionSet
, i
);
1277 values
= table
->values
+ table
->next_idx
* MONO_DECL_SECURITY_SIZE
;
1279 idx
= mono_metadata_token_index (parent_token
);
1280 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
1281 switch (mono_metadata_token_table (parent_token
)) {
1282 case MONO_TABLE_TYPEDEF
:
1283 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
1285 case MONO_TABLE_METHOD
:
1286 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
1288 case MONO_TABLE_ASSEMBLY
:
1289 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
1292 g_assert_not_reached ();
1295 values
[MONO_DECL_SECURITY_ACTION
] = perm
->action
;
1296 values
[MONO_DECL_SECURITY_PARENT
] = idx
;
1297 values
[MONO_DECL_SECURITY_PERMISSIONSET
] = add_mono_string_to_blob_cached (assembly
, perm
->pset
);
1304 * Fill in the MethodDef and ParamDef tables for a method.
1305 * This is used for both normal methods and constructors.
1308 mono_image_basic_method (ReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1310 MonoDynamicTable
*table
;
1314 /* room in this table is already allocated */
1315 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
1316 *mb
->table_idx
= table
->next_idx
++;
1317 g_hash_table_insert (assembly
->method_to_table_idx
, mb
->mhandle
, GUINT_TO_POINTER ((*mb
->table_idx
)));
1318 values
= table
->values
+ *mb
->table_idx
* MONO_METHOD_SIZE
;
1319 values
[MONO_METHOD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1320 values
[MONO_METHOD_FLAGS
] = mb
->attrs
;
1321 values
[MONO_METHOD_IMPLFLAGS
] = mb
->iattrs
;
1322 values
[MONO_METHOD_SIGNATURE
] = method_builder_encode_signature (assembly
, mb
);
1323 values
[MONO_METHOD_RVA
] = method_encode_code (assembly
, mb
);
1325 table
= &assembly
->tables
[MONO_TABLE_PARAM
];
1326 values
[MONO_METHOD_PARAMLIST
] = table
->next_idx
;
1328 mono_image_add_decl_security (assembly
,
1329 mono_metadata_make_token (MONO_TABLE_METHOD
, *mb
->table_idx
), mb
->permissions
);
1332 MonoDynamicTable
*mtable
;
1335 mtable
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1336 mvalues
= mtable
->values
+ mtable
->next_idx
* MONO_FIELD_MARSHAL_SIZE
;
1339 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1340 if (mono_array_get (mb
->pinfo
, gpointer
, i
))
1343 table
->rows
+= count
;
1344 alloc_table (table
, table
->rows
);
1345 values
= table
->values
+ table
->next_idx
* MONO_PARAM_SIZE
;
1346 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1347 MonoReflectionParamBuilder
*pb
;
1348 if ((pb
= mono_array_get (mb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
1349 values
[MONO_PARAM_FLAGS
] = pb
->attrs
;
1350 values
[MONO_PARAM_SEQUENCE
] = i
;
1351 if (pb
->name
!= NULL
) {
1352 values
[MONO_PARAM_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1354 values
[MONO_PARAM_NAME
] = 0;
1356 values
+= MONO_PARAM_SIZE
;
1357 if (pb
->marshal_info
) {
1359 alloc_table (mtable
, mtable
->rows
);
1360 mvalues
= mtable
->values
+ mtable
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1361 mvalues
[MONO_FIELD_MARSHAL_PARENT
] = (table
->next_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_PARAMDEF
;
1362 mvalues
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, pb
->marshal_info
);
1364 pb
->table_idx
= table
->next_idx
++;
1365 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
1366 guint32 field_type
= 0;
1367 mtable
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1369 alloc_table (mtable
, mtable
->rows
);
1370 mvalues
= mtable
->values
+ mtable
->rows
* MONO_CONSTANT_SIZE
;
1371 mvalues
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_PARAM
| (pb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1372 mvalues
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, pb
->def_value
, &field_type
);
1373 mvalues
[MONO_CONSTANT_TYPE
] = field_type
;
1374 mvalues
[MONO_CONSTANT_PADDING
] = 0;
1382 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
)
1384 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1386 rmb
->ilgen
= mb
->ilgen
;
1387 rmb
->rtype
= monotype_cast (mb
->rtype
);
1388 rmb
->parameters
= mb
->parameters
;
1389 rmb
->generic_params
= mb
->generic_params
;
1390 rmb
->generic_container
= mb
->generic_container
;
1391 rmb
->opt_types
= NULL
;
1392 rmb
->pinfo
= mb
->pinfo
;
1393 rmb
->attrs
= mb
->attrs
;
1394 rmb
->iattrs
= mb
->iattrs
;
1395 rmb
->call_conv
= mb
->call_conv
;
1396 rmb
->code
= mb
->code
;
1397 rmb
->type
= mb
->type
;
1398 rmb
->name
= mb
->name
;
1399 rmb
->table_idx
= &mb
->table_idx
;
1400 rmb
->init_locals
= mb
->init_locals
;
1401 rmb
->skip_visibility
= FALSE
;
1402 rmb
->return_modreq
= mb
->return_modreq
;
1403 rmb
->return_modopt
= mb
->return_modopt
;
1404 rmb
->param_modreq
= mb
->param_modreq
;
1405 rmb
->param_modopt
= mb
->param_modopt
;
1406 rmb
->permissions
= mb
->permissions
;
1407 rmb
->mhandle
= mb
->mhandle
;
1412 rmb
->charset
= mb
->charset
;
1413 rmb
->extra_flags
= mb
->extra_flags
;
1414 rmb
->native_cc
= mb
->native_cc
;
1415 rmb
->dllentry
= mb
->dllentry
;
1421 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
)
1423 const char *name
= mb
->attrs
& METHOD_ATTRIBUTE_STATIC
? ".cctor": ".ctor";
1425 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1427 rmb
->ilgen
= mb
->ilgen
;
1428 rmb
->rtype
= mono_type_get_object (mono_domain_get (), &mono_defaults
.void_class
->byval_arg
);
1429 rmb
->parameters
= mb
->parameters
;
1430 rmb
->generic_params
= NULL
;
1431 rmb
->generic_container
= NULL
;
1432 rmb
->opt_types
= NULL
;
1433 rmb
->pinfo
= mb
->pinfo
;
1434 rmb
->attrs
= mb
->attrs
;
1435 rmb
->iattrs
= mb
->iattrs
;
1436 rmb
->call_conv
= mb
->call_conv
;
1438 rmb
->type
= mb
->type
;
1439 rmb
->name
= mono_string_new (mono_domain_get (), name
);
1440 rmb
->table_idx
= &mb
->table_idx
;
1441 rmb
->init_locals
= mb
->init_locals
;
1442 rmb
->skip_visibility
= FALSE
;
1443 rmb
->return_modreq
= NULL
;
1444 rmb
->return_modopt
= NULL
;
1445 rmb
->param_modreq
= mb
->param_modreq
;
1446 rmb
->param_modopt
= mb
->param_modopt
;
1447 rmb
->permissions
= mb
->permissions
;
1448 rmb
->mhandle
= mb
->mhandle
;
1453 #ifndef DISABLE_REFLECTION_EMIT
1455 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder
*rmb
, MonoReflectionDynamicMethod
*mb
)
1457 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1459 rmb
->ilgen
= mb
->ilgen
;
1460 rmb
->rtype
= mb
->rtype
;
1461 rmb
->parameters
= mb
->parameters
;
1462 rmb
->generic_params
= NULL
;
1463 rmb
->generic_container
= NULL
;
1464 rmb
->opt_types
= NULL
;
1466 rmb
->attrs
= mb
->attrs
;
1468 rmb
->call_conv
= mb
->call_conv
;
1470 rmb
->type
= (MonoObject
*) mb
->owner
;
1471 rmb
->name
= mb
->name
;
1472 rmb
->table_idx
= NULL
;
1473 rmb
->init_locals
= mb
->init_locals
;
1474 rmb
->skip_visibility
= mb
->skip_visibility
;
1475 rmb
->return_modreq
= NULL
;
1476 rmb
->return_modopt
= NULL
;
1477 rmb
->param_modreq
= NULL
;
1478 rmb
->param_modopt
= NULL
;
1479 rmb
->permissions
= NULL
;
1480 rmb
->mhandle
= mb
->mhandle
;
1487 mono_image_add_methodimpl (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
1489 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
1490 MonoDynamicTable
*table
;
1494 if (!mb
->override_method
)
1497 table
= &assembly
->tables
[MONO_TABLE_METHODIMPL
];
1499 alloc_table (table
, table
->rows
);
1500 values
= table
->values
+ table
->rows
* MONO_METHODIMPL_SIZE
;
1501 values
[MONO_METHODIMPL_CLASS
] = tb
->table_idx
;
1502 values
[MONO_METHODIMPL_BODY
] = MONO_METHODDEFORREF_METHODDEF
| (mb
->table_idx
<< MONO_METHODDEFORREF_BITS
);
1504 tok
= mono_image_create_token (assembly
, (MonoObject
*)mb
->override_method
, FALSE
, FALSE
);
1505 switch (mono_metadata_token_table (tok
)) {
1506 case MONO_TABLE_MEMBERREF
:
1507 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
1509 case MONO_TABLE_METHOD
:
1510 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
1513 g_assert_not_reached ();
1515 values
[MONO_METHODIMPL_DECLARATION
] = tok
;
1519 mono_image_get_method_info (MonoReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1521 MonoDynamicTable
*table
;
1523 ReflectionMethodBuilder rmb
;
1526 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
1528 mono_image_basic_method (&rmb
, assembly
);
1529 mb
->table_idx
= *rmb
.table_idx
;
1531 if (mb
->dll
) { /* It's a P/Invoke method */
1533 /* map CharSet values to on-disk values */
1534 int ncharset
= (mb
->charset
? (mb
->charset
- 1) * 2 : 0);
1535 int extra_flags
= mb
->extra_flags
;
1536 table
= &assembly
->tables
[MONO_TABLE_IMPLMAP
];
1538 alloc_table (table
, table
->rows
);
1539 values
= table
->values
+ table
->rows
* MONO_IMPLMAP_SIZE
;
1541 values
[MONO_IMPLMAP_FLAGS
] = (mb
->native_cc
<< 8) | ncharset
| extra_flags
;
1542 values
[MONO_IMPLMAP_MEMBER
] = (mb
->table_idx
<< 1) | 1; /* memberforwarded: method */
1544 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->dllentry
);
1546 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1547 moduleref
= string_heap_insert_mstring (&assembly
->sheap
, mb
->dll
);
1548 if (!(values
[MONO_IMPLMAP_SCOPE
] = find_index_in_table (assembly
, MONO_TABLE_MODULEREF
, MONO_MODULEREF_NAME
, moduleref
))) {
1549 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
1551 alloc_table (table
, table
->rows
);
1552 table
->values
[table
->rows
* MONO_MODULEREF_SIZE
+ MONO_MODULEREF_NAME
] = moduleref
;
1553 values
[MONO_IMPLMAP_SCOPE
] = table
->rows
;
1557 if (mb
->generic_params
) {
1558 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
1559 table
->rows
+= mono_array_length (mb
->generic_params
);
1560 alloc_table (table
, table
->rows
);
1561 for (i
= 0; i
< mono_array_length (mb
->generic_params
); ++i
) {
1562 guint32 owner
= MONO_TYPEORMETHOD_METHOD
| (mb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
1564 mono_image_get_generic_param_info (
1565 mono_array_get (mb
->generic_params
, gpointer
, i
), owner
, assembly
);
1572 mono_image_get_ctor_info (MonoDomain
*domain
, MonoReflectionCtorBuilder
*mb
, MonoDynamicImage
*assembly
)
1574 ReflectionMethodBuilder rmb
;
1576 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
1578 mono_image_basic_method (&rmb
, assembly
);
1579 mb
->table_idx
= *rmb
.table_idx
;
1583 type_get_fully_qualified_name (MonoType
*type
)
1585 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1589 type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
) {
1593 klass
= mono_class_from_mono_type (type
);
1595 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1596 ta
= klass
->image
->assembly
;
1597 if (ta
->dynamic
|| (ta
== ass
)) {
1598 if (klass
->generic_class
|| klass
->generic_container
)
1599 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1600 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_FULL_NAME
);
1602 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1605 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1608 #ifndef DISABLE_REFLECTION_EMIT
1610 fieldref_encode_signature (MonoDynamicImage
*assembly
, MonoType
*type
)
1615 if (!assembly
->save
)
1618 sigbuffer_init (&buf
, 32);
1620 sigbuffer_add_value (&buf
, 0x06);
1621 /* encode custom attributes before the type */
1622 /* FIXME: This should probably go in encode_type () */
1623 if (type
->num_mods
) {
1624 for (i
= 0; i
< type
->num_mods
; ++i
) {
1625 if (type
->modifiers
[i
].required
)
1626 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_REQD
);
1628 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_OPT
);
1629 sigbuffer_add_value (&buf
, type
->modifiers
[i
].token
);
1632 encode_type (assembly
, type
, &buf
);
1633 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1634 sigbuffer_free (&buf
);
1640 field_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
1645 sigbuffer_init (&buf
, 32);
1647 sigbuffer_add_value (&buf
, 0x06);
1648 encode_custom_modifiers (assembly
, fb
->modreq
, fb
->modopt
, &buf
);
1649 /* encode custom attributes before the type */
1650 encode_reflection_type (assembly
, monotype_cast (fb
->type
), &buf
);
1651 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1652 sigbuffer_free (&buf
);
1657 encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
) {
1658 char blob_size
[64];
1659 char *b
= blob_size
;
1662 guint32 idx
= 0, len
= 0, dummy
= 0;
1664 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1665 guint32 fpa_double
[2];
1670 p
= buf
= g_malloc (64);
1672 *ret_type
= MONO_TYPE_CLASS
;
1674 box_val
= (char*)&dummy
;
1676 box_val
= ((char*)val
) + sizeof (MonoObject
);
1677 *ret_type
= val
->vtable
->klass
->byval_arg
.type
;
1680 switch (*ret_type
) {
1681 case MONO_TYPE_BOOLEAN
:
1686 case MONO_TYPE_CHAR
:
1703 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1704 fpa_p
= (guint32
*)box_val
;
1705 fpa_double
[0] = fpa_p
[1];
1706 fpa_double
[1] = fpa_p
[0];
1707 box_val
= (char*)fpa_double
;
1711 case MONO_TYPE_VALUETYPE
:
1712 if (val
->vtable
->klass
->enumtype
) {
1713 *ret_type
= mono_class_enum_basetype (val
->vtable
->klass
)->type
;
1716 g_error ("we can't encode valuetypes");
1717 case MONO_TYPE_CLASS
:
1719 case MONO_TYPE_STRING
: {
1720 MonoString
*str
= (MonoString
*)val
;
1721 /* there is no signature */
1722 len
= str
->length
* 2;
1723 mono_metadata_encode_value (len
, b
, &b
);
1724 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1726 char *swapped
= g_malloc (2 * mono_string_length (str
));
1727 const char *p
= (const char*)mono_string_chars (str
);
1729 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
1730 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
1734 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
1740 case MONO_TYPE_GENERICINST
:
1741 *ret_type
= val
->vtable
->klass
->generic_class
->container_class
->byval_arg
.type
;
1744 g_error ("we don't encode constant type 0x%02x yet", *ret_type
);
1747 /* there is no signature */
1748 mono_metadata_encode_value (len
, b
, &b
);
1749 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1750 idx
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
1751 swap_with_size (blob_size
, box_val
, len
, 1);
1752 mono_image_add_stream_data (&assembly
->blob
, blob_size
, len
);
1754 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, box_val
, len
);
1762 encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
) {
1767 sigbuffer_init (&buf
, 32);
1769 sigbuffer_add_value (&buf
, minfo
->type
);
1771 switch (minfo
->type
) {
1772 case MONO_NATIVE_BYVALTSTR
:
1773 case MONO_NATIVE_BYVALARRAY
:
1774 sigbuffer_add_value (&buf
, minfo
->count
);
1776 case MONO_NATIVE_LPARRAY
:
1777 if (minfo
->eltype
|| minfo
->has_size
) {
1778 sigbuffer_add_value (&buf
, minfo
->eltype
);
1779 if (minfo
->has_size
) {
1780 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? minfo
->param_num
: 0);
1781 sigbuffer_add_value (&buf
, minfo
->count
!= -1? minfo
->count
: 0);
1783 /* LAMESPEC: ElemMult is undocumented */
1784 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? 1: 0);
1788 case MONO_NATIVE_CUSTOM
:
1790 str
= mono_string_to_utf8 (minfo
->guid
);
1792 sigbuffer_add_value (&buf
, len
);
1793 sigbuffer_add_mem (&buf
, str
, len
);
1796 sigbuffer_add_value (&buf
, 0);
1798 /* native type name */
1799 sigbuffer_add_value (&buf
, 0);
1800 /* custom marshaler type name */
1801 if (minfo
->marshaltype
|| minfo
->marshaltyperef
) {
1802 if (minfo
->marshaltyperef
)
1803 str
= type_get_fully_qualified_name (monotype_cast (minfo
->marshaltyperef
)->type
);
1805 str
= mono_string_to_utf8 (minfo
->marshaltype
);
1807 sigbuffer_add_value (&buf
, len
);
1808 sigbuffer_add_mem (&buf
, str
, len
);
1811 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1812 sigbuffer_add_value (&buf
, 0);
1814 if (minfo
->mcookie
) {
1815 str
= mono_string_to_utf8 (minfo
->mcookie
);
1817 sigbuffer_add_value (&buf
, len
);
1818 sigbuffer_add_mem (&buf
, str
, len
);
1821 sigbuffer_add_value (&buf
, 0);
1827 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1828 sigbuffer_free (&buf
);
1833 mono_image_get_field_info (MonoReflectionFieldBuilder
*fb
, MonoDynamicImage
*assembly
)
1835 MonoDynamicTable
*table
;
1838 /* maybe this fixup should be done in the C# code */
1839 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
)
1840 fb
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
1841 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
1842 fb
->table_idx
= table
->next_idx
++;
1843 g_hash_table_insert (assembly
->field_to_table_idx
, fb
->handle
, GUINT_TO_POINTER (fb
->table_idx
));
1844 values
= table
->values
+ fb
->table_idx
* MONO_FIELD_SIZE
;
1845 values
[MONO_FIELD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, fb
->name
);
1846 values
[MONO_FIELD_FLAGS
] = fb
->attrs
;
1847 values
[MONO_FIELD_SIGNATURE
] = field_encode_signature (assembly
, fb
);
1849 if (fb
->offset
!= -1) {
1850 table
= &assembly
->tables
[MONO_TABLE_FIELDLAYOUT
];
1852 alloc_table (table
, table
->rows
);
1853 values
= table
->values
+ table
->rows
* MONO_FIELD_LAYOUT_SIZE
;
1854 values
[MONO_FIELD_LAYOUT_FIELD
] = fb
->table_idx
;
1855 values
[MONO_FIELD_LAYOUT_OFFSET
] = fb
->offset
;
1857 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
) {
1858 guint32 field_type
= 0;
1859 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1861 alloc_table (table
, table
->rows
);
1862 values
= table
->values
+ table
->rows
* MONO_CONSTANT_SIZE
;
1863 values
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_FIEDDEF
| (fb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1864 values
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, fb
->def_value
, &field_type
);
1865 values
[MONO_CONSTANT_TYPE
] = field_type
;
1866 values
[MONO_CONSTANT_PADDING
] = 0;
1868 if (fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
1870 table
= &assembly
->tables
[MONO_TABLE_FIELDRVA
];
1872 alloc_table (table
, table
->rows
);
1873 values
= table
->values
+ table
->rows
* MONO_FIELD_RVA_SIZE
;
1874 values
[MONO_FIELD_RVA_FIELD
] = fb
->table_idx
;
1876 * We store it in the code section because it's simpler for now.
1879 if (mono_array_length (fb
->rva_data
) >= 10)
1880 stream_data_align (&assembly
->code
);
1881 rva_idx
= mono_image_add_stream_data (&assembly
->code
, mono_array_addr (fb
->rva_data
, char, 0), mono_array_length (fb
->rva_data
));
1883 rva_idx
= mono_image_add_stream_zero (&assembly
->code
, mono_class_value_size (fb
->handle
->parent
, NULL
));
1884 values
[MONO_FIELD_RVA_RVA
] = rva_idx
+ assembly
->text_rva
;
1886 if (fb
->marshal_info
) {
1887 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1889 alloc_table (table
, table
->rows
);
1890 values
= table
->values
+ table
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1891 values
[MONO_FIELD_MARSHAL_PARENT
] = (fb
->table_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_FIELDSREF
;
1892 values
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, fb
->marshal_info
);
1897 property_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionPropertyBuilder
*fb
)
1900 guint32 nparams
= 0;
1901 MonoReflectionMethodBuilder
*mb
= fb
->get_method
;
1902 MonoReflectionMethodBuilder
*smb
= fb
->set_method
;
1905 if (mb
&& mb
->parameters
)
1906 nparams
= mono_array_length (mb
->parameters
);
1907 if (!mb
&& smb
&& smb
->parameters
)
1908 nparams
= mono_array_length (smb
->parameters
) - 1;
1909 sigbuffer_init (&buf
, 32);
1910 sigbuffer_add_byte (&buf
, 0x08);
1911 sigbuffer_add_value (&buf
, nparams
);
1913 encode_reflection_type (assembly
, monotype_cast (mb
->rtype
), &buf
);
1914 for (i
= 0; i
< nparams
; ++i
) {
1915 MonoReflectionType
*pt
= mono_type_array_get (mb
->parameters
, i
);
1916 encode_reflection_type (assembly
, pt
, &buf
);
1918 } else if (smb
&& smb
->parameters
) {
1919 /* the property type is the last param */
1920 encode_reflection_type (assembly
, mono_type_array_get (smb
->parameters
, nparams
), &buf
);
1921 for (i
= 0; i
< nparams
; ++i
) {
1922 MonoReflectionType
*pt
= mono_type_array_get (smb
->parameters
, i
);
1923 encode_reflection_type (assembly
, pt
, &buf
);
1926 encode_reflection_type (assembly
, monotype_cast (fb
->type
), &buf
);
1929 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1930 sigbuffer_free (&buf
);
1935 mono_image_get_property_info (MonoReflectionPropertyBuilder
*pb
, MonoDynamicImage
*assembly
)
1937 MonoDynamicTable
*table
;
1939 guint num_methods
= 0;
1943 * we need to set things in the following tables:
1944 * PROPERTYMAP (info already filled in _get_type_info ())
1945 * PROPERTY (rows already preallocated in _get_type_info ())
1946 * METHOD (method info already done with the generic method code)
1949 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
1950 pb
->table_idx
= table
->next_idx
++;
1951 values
= table
->values
+ pb
->table_idx
* MONO_PROPERTY_SIZE
;
1952 values
[MONO_PROPERTY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1953 values
[MONO_PROPERTY_FLAGS
] = pb
->attrs
;
1954 values
[MONO_PROPERTY_TYPE
] = property_encode_signature (assembly
, pb
);
1956 /* FIXME: we still don't handle 'other' methods */
1957 if (pb
->get_method
) num_methods
++;
1958 if (pb
->set_method
) num_methods
++;
1960 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
1961 table
->rows
+= num_methods
;
1962 alloc_table (table
, table
->rows
);
1964 if (pb
->get_method
) {
1965 semaidx
= table
->next_idx
++;
1966 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
1967 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_GETTER
;
1968 values
[MONO_METHOD_SEMA_METHOD
] = pb
->get_method
->table_idx
;
1969 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
1971 if (pb
->set_method
) {
1972 semaidx
= table
->next_idx
++;
1973 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
1974 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_SETTER
;
1975 values
[MONO_METHOD_SEMA_METHOD
] = pb
->set_method
->table_idx
;
1976 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
1981 mono_image_get_event_info (MonoReflectionEventBuilder
*eb
, MonoDynamicImage
*assembly
)
1983 MonoDynamicTable
*table
;
1985 guint num_methods
= 0;
1989 * we need to set things in the following tables:
1990 * EVENTMAP (info already filled in _get_type_info ())
1991 * EVENT (rows already preallocated in _get_type_info ())
1992 * METHOD (method info already done with the generic method code)
1995 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
1996 eb
->table_idx
= table
->next_idx
++;
1997 values
= table
->values
+ eb
->table_idx
* MONO_EVENT_SIZE
;
1998 values
[MONO_EVENT_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, eb
->name
);
1999 values
[MONO_EVENT_FLAGS
] = eb
->attrs
;
2000 values
[MONO_EVENT_TYPE
] = mono_image_typedef_or_ref (assembly
, eb
->type
->type
);
2003 * FIXME: we still don't handle 'other' methods
2005 if (eb
->add_method
) num_methods
++;
2006 if (eb
->remove_method
) num_methods
++;
2007 if (eb
->raise_method
) num_methods
++;
2009 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
2010 table
->rows
+= num_methods
;
2011 alloc_table (table
, table
->rows
);
2013 if (eb
->add_method
) {
2014 semaidx
= table
->next_idx
++;
2015 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2016 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_ADD_ON
;
2017 values
[MONO_METHOD_SEMA_METHOD
] = eb
->add_method
->table_idx
;
2018 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2020 if (eb
->remove_method
) {
2021 semaidx
= table
->next_idx
++;
2022 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2023 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_REMOVE_ON
;
2024 values
[MONO_METHOD_SEMA_METHOD
] = eb
->remove_method
->table_idx
;
2025 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2027 if (eb
->raise_method
) {
2028 semaidx
= table
->next_idx
++;
2029 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2030 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_FIRE
;
2031 values
[MONO_METHOD_SEMA_METHOD
] = eb
->raise_method
->table_idx
;
2032 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2037 encode_constraints (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2039 MonoDynamicTable
*table
;
2040 guint32 num_constraints
, i
;
2044 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
2045 num_constraints
= gparam
->iface_constraints
?
2046 mono_array_length (gparam
->iface_constraints
) : 0;
2047 table
->rows
+= num_constraints
;
2048 if (gparam
->base_type
)
2050 alloc_table (table
, table
->rows
);
2052 if (gparam
->base_type
) {
2053 table_idx
= table
->next_idx
++;
2054 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2056 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2057 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2058 assembly
, gparam
->base_type
->type
);
2061 for (i
= 0; i
< num_constraints
; i
++) {
2062 MonoReflectionType
*constraint
= mono_array_get (
2063 gparam
->iface_constraints
, gpointer
, i
);
2065 table_idx
= table
->next_idx
++;
2066 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2068 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2069 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2070 assembly
, constraint
->type
);
2075 mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2077 GenericParamTableEntry
*entry
;
2080 * The GenericParam table must be sorted according to the `owner' field.
2081 * We need to do this sorting prior to writing the GenericParamConstraint
2082 * table, since we have to use the final GenericParam table indices there
2083 * and they must also be sorted.
2086 entry
= g_new0 (GenericParamTableEntry
, 1);
2087 entry
->owner
= owner
;
2088 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2089 MOVING_GC_REGISTER (&entry
->gparam
);
2090 entry
->gparam
= gparam
;
2092 g_ptr_array_add (assembly
->gen_params
, entry
);
2096 write_generic_param_entry (MonoDynamicImage
*assembly
, GenericParamTableEntry
*entry
)
2098 MonoDynamicTable
*table
;
2099 MonoGenericParam
*param
;
2103 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
2104 table_idx
= table
->next_idx
++;
2105 values
= table
->values
+ table_idx
* MONO_GENERICPARAM_SIZE
;
2107 param
= entry
->gparam
->type
.type
->data
.generic_param
;
2109 values
[MONO_GENERICPARAM_OWNER
] = entry
->owner
;
2110 values
[MONO_GENERICPARAM_FLAGS
] = entry
->gparam
->attrs
;
2111 values
[MONO_GENERICPARAM_NUMBER
] = mono_generic_param_num (param
);
2112 values
[MONO_GENERICPARAM_NAME
] = string_heap_insert (&assembly
->sheap
, mono_generic_param_info (param
)->name
);
2114 mono_image_add_cattrs (assembly
, table_idx
, MONO_CUSTOM_ATTR_GENERICPAR
, entry
->gparam
->cattrs
);
2116 encode_constraints (entry
->gparam
, table_idx
, assembly
);
2120 resolution_scope_from_image (MonoDynamicImage
*assembly
, MonoImage
*image
)
2122 MonoDynamicTable
*table
;
2125 guint32 cols
[MONO_ASSEMBLY_SIZE
];
2129 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, image
))))
2132 if (image
->assembly
->dynamic
&& (image
->assembly
== assembly
->image
.assembly
)) {
2133 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
2134 token
= table
->next_idx
++;
2136 alloc_table (table
, table
->rows
);
2137 values
= table
->values
+ token
* MONO_MODULEREF_SIZE
;
2138 values
[MONO_MODULEREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->module_name
);
2140 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2141 token
|= MONO_RESOLTION_SCOPE_MODULEREF
;
2142 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2147 if (image
->assembly
->dynamic
)
2149 memset (cols
, 0, sizeof (cols
));
2151 /* image->assembly->image is the manifest module */
2152 image
= image
->assembly
->image
;
2153 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_ASSEMBLY
], 0, cols
, MONO_ASSEMBLY_SIZE
);
2156 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLYREF
];
2157 token
= table
->next_idx
++;
2159 alloc_table (table
, table
->rows
);
2160 values
= table
->values
+ token
* MONO_ASSEMBLYREF_SIZE
;
2161 values
[MONO_ASSEMBLYREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->assembly_name
);
2162 values
[MONO_ASSEMBLYREF_MAJOR_VERSION
] = cols
[MONO_ASSEMBLY_MAJOR_VERSION
];
2163 values
[MONO_ASSEMBLYREF_MINOR_VERSION
] = cols
[MONO_ASSEMBLY_MINOR_VERSION
];
2164 values
[MONO_ASSEMBLYREF_BUILD_NUMBER
] = cols
[MONO_ASSEMBLY_BUILD_NUMBER
];
2165 values
[MONO_ASSEMBLYREF_REV_NUMBER
] = cols
[MONO_ASSEMBLY_REV_NUMBER
];
2166 values
[MONO_ASSEMBLYREF_FLAGS
] = 0;
2167 values
[MONO_ASSEMBLYREF_CULTURE
] = 0;
2168 values
[MONO_ASSEMBLYREF_HASH_VALUE
] = 0;
2170 if (strcmp ("", image
->assembly
->aname
.culture
)) {
2171 values
[MONO_ASSEMBLYREF_CULTURE
] = string_heap_insert (&assembly
->sheap
,
2172 image
->assembly
->aname
.culture
);
2175 if ((pubkey
= mono_image_get_public_key (image
, &publen
))) {
2176 guchar pubtoken
[9];
2178 mono_digest_get_public_token (pubtoken
+ 1, (guchar
*)pubkey
, publen
);
2179 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = mono_image_add_stream_data (&assembly
->blob
, (char*)pubtoken
, 9);
2181 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = 0;
2183 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2184 token
|= MONO_RESOLTION_SCOPE_ASSEMBLYREF
;
2185 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2190 create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
)
2192 MonoDynamicTable
*table
;
2197 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
))))
2200 sigbuffer_init (&buf
, 32);
2201 switch (type
->type
) {
2202 case MONO_TYPE_FNPTR
:
2204 case MONO_TYPE_SZARRAY
:
2205 case MONO_TYPE_ARRAY
:
2207 case MONO_TYPE_MVAR
:
2208 case MONO_TYPE_GENERICINST
:
2209 encode_type (assembly
, type
, &buf
);
2211 case MONO_TYPE_CLASS
:
2212 case MONO_TYPE_VALUETYPE
: {
2213 MonoClass
*k
= mono_class_from_mono_type (type
);
2214 if (!k
|| !k
->generic_container
) {
2215 sigbuffer_free (&buf
);
2218 encode_type (assembly
, type
, &buf
);
2222 sigbuffer_free (&buf
);
2226 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2227 if (assembly
->save
) {
2228 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2229 alloc_table (table
, table
->rows
+ 1);
2230 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2231 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2233 sigbuffer_free (&buf
);
2235 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2236 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
2242 mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
)
2244 MonoDynamicTable
*table
;
2246 guint32 token
, scope
, enclosing
;
2249 /* if the type requires a typespec, we must try that first*/
2250 if (try_typespec
&& (token
= create_typespec (assembly
, type
)))
2252 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typeref
, type
));
2255 klass
= mono_class_from_mono_type (type
);
2257 klass
= mono_class_from_mono_type (type
);
2260 * If it's in the same module and not a generic type parameter:
2262 if ((klass
->image
== &assembly
->image
) && (type
->type
!= MONO_TYPE_VAR
) &&
2263 (type
->type
!= MONO_TYPE_MVAR
)) {
2264 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
2265 token
= MONO_TYPEDEFORREF_TYPEDEF
| (tb
->table_idx
<< MONO_TYPEDEFORREF_BITS
);
2266 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), klass
->reflection_info
);
2270 if (klass
->nested_in
) {
2271 enclosing
= mono_image_typedef_or_ref_full (assembly
, &klass
->nested_in
->byval_arg
, FALSE
);
2272 /* get the typeref idx of the enclosing type */
2273 enclosing
>>= MONO_TYPEDEFORREF_BITS
;
2274 scope
= (enclosing
<< MONO_RESOLTION_SCOPE_BITS
) | MONO_RESOLTION_SCOPE_TYPEREF
;
2276 scope
= resolution_scope_from_image (assembly
, klass
->image
);
2278 table
= &assembly
->tables
[MONO_TABLE_TYPEREF
];
2279 if (assembly
->save
) {
2280 alloc_table (table
, table
->rows
+ 1);
2281 values
= table
->values
+ table
->next_idx
* MONO_TYPEREF_SIZE
;
2282 values
[MONO_TYPEREF_SCOPE
] = scope
;
2283 values
[MONO_TYPEREF_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
2284 values
[MONO_TYPEREF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
2286 token
= MONO_TYPEDEFORREF_TYPEREF
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
); /* typeref */
2287 g_hash_table_insert (assembly
->typeref
, type
, GUINT_TO_POINTER(token
));
2289 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), klass
->reflection_info
);
2294 * Despite the name, we handle also TypeSpec (with the above helper).
2297 mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
)
2299 return mono_image_typedef_or_ref_full (assembly
, type
, TRUE
);
2302 #ifndef DISABLE_REFLECTION_EMIT
2304 * Insert a memberef row into the metadata: the token that point to the memberref
2305 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2306 * mono_image_get_fieldref_token()).
2307 * The sig param is an index to an already built signature.
2310 mono_image_get_memberref_token (MonoDynamicImage
*assembly
, MonoType
*type
, const char *name
, guint32 sig
)
2312 MonoDynamicTable
*table
;
2314 guint32 token
, pclass
;
2317 parent
= mono_image_typedef_or_ref (assembly
, type
);
2318 switch (parent
& MONO_TYPEDEFORREF_MASK
) {
2319 case MONO_TYPEDEFORREF_TYPEREF
:
2320 pclass
= MONO_MEMBERREF_PARENT_TYPEREF
;
2322 case MONO_TYPEDEFORREF_TYPESPEC
:
2323 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2325 case MONO_TYPEDEFORREF_TYPEDEF
:
2326 pclass
= MONO_MEMBERREF_PARENT_TYPEDEF
;
2329 g_warning ("unknown typeref or def token 0x%08x for %s", parent
, name
);
2332 /* extract the index */
2333 parent
>>= MONO_TYPEDEFORREF_BITS
;
2335 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2337 if (assembly
->save
) {
2338 alloc_table (table
, table
->rows
+ 1);
2339 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2340 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2341 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2342 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2345 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2352 mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
)
2355 MonoMethodSignature
*sig
;
2357 create_typespec
= create_typespec
&& method
->is_generic
&& method
->klass
->image
!= &assembly
->image
;
2359 if (create_typespec
) {
2360 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1)));
2365 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2366 if (token
&& !create_typespec
)
2369 g_assert (!method
->is_inflated
);
2372 * A methodref signature can't contain an unmanaged calling convention.
2374 sig
= mono_metadata_signature_dup (mono_method_signature (method
));
2375 if ((sig
->call_convention
!= MONO_CALL_DEFAULT
) && (sig
->call_convention
!= MONO_CALL_VARARG
))
2376 sig
->call_convention
= MONO_CALL_DEFAULT
;
2377 token
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
,
2378 method
->name
, method_encode_signature (assembly
, sig
));
2380 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2383 if (create_typespec
) {
2384 MonoDynamicTable
*table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2385 g_assert (mono_metadata_token_table (token
) == MONO_TABLE_MEMBERREF
);
2386 token
= (mono_metadata_token_index (token
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2388 if (assembly
->save
) {
2391 alloc_table (table
, table
->rows
+ 1);
2392 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2393 values
[MONO_METHODSPEC_METHOD
] = token
;
2394 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_sig (assembly
, &mono_method_get_generic_container (method
)->context
);
2397 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2399 /*methodspec and memberef tokens are diferent, */
2400 g_hash_table_insert (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1), GUINT_TO_POINTER (token
));
2407 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
)
2410 ReflectionMethodBuilder rmb
;
2413 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2417 name
= mono_string_to_utf8 (method
->name
);
2418 reflection_methodbuilder_from_method_builder (&rmb
, method
);
2421 * A methodref signature can't contain an unmanaged calling convention.
2422 * Since some flags are encoded as part of call_conv, we need to check against it.
2424 if ((rmb
.call_conv
& ~0x60) != MONO_CALL_DEFAULT
&& (rmb
.call_conv
& ~0x60) != MONO_CALL_VARARG
)
2425 rmb
.call_conv
= (rmb
.call_conv
& 0x60) | MONO_CALL_DEFAULT
;
2426 token
= mono_image_get_memberref_token (assembly
, ((MonoReflectionTypeBuilder
*)rmb
.type
)->type
.type
,
2427 name
, method_builder_encode_signature (assembly
, &rmb
));
2430 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2435 mono_image_get_varargs_method_token (MonoDynamicImage
*assembly
, guint32 original
,
2436 const gchar
*name
, guint32 sig
)
2438 MonoDynamicTable
*table
;
2442 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2444 if (assembly
->save
) {
2445 alloc_table (table
, table
->rows
+ 1);
2446 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2447 values
[MONO_MEMBERREF_CLASS
] = original
;
2448 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2449 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2452 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2459 encode_generic_method_definition_sig (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2463 guint32 nparams
= mono_array_length (mb
->generic_params
);
2466 if (!assembly
->save
)
2469 sigbuffer_init (&buf
, 32);
2471 sigbuffer_add_value (&buf
, 0xa);
2472 sigbuffer_add_value (&buf
, nparams
);
2474 for (i
= 0; i
< nparams
; i
++) {
2475 sigbuffer_add_value (&buf
, MONO_TYPE_MVAR
);
2476 sigbuffer_add_value (&buf
, i
);
2479 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2480 sigbuffer_free (&buf
);
2485 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2487 MonoDynamicTable
*table
;
2489 guint32 token
, mtoken
= 0;
2491 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->methodspec
, mb
));
2495 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2497 mtoken
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2498 switch (mono_metadata_token_table (mtoken
)) {
2499 case MONO_TABLE_MEMBERREF
:
2500 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2502 case MONO_TABLE_METHOD
:
2503 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2506 g_assert_not_reached ();
2509 if (assembly
->save
) {
2510 alloc_table (table
, table
->rows
+ 1);
2511 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2512 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2513 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_definition_sig (assembly
, mb
);
2516 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2519 mono_g_hash_table_insert (assembly
->methodspec
, mb
, GUINT_TO_POINTER(token
));
2524 mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
)
2528 if (mb
->generic_params
&& create_methodspec
)
2529 return mono_image_get_methodspec_token_for_generic_method_definition (assembly
, mb
);
2531 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, mb
));
2535 token
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2536 g_hash_table_insert (assembly
->handleref
, mb
, GUINT_TO_POINTER(token
));
2541 mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*mb
)
2544 ReflectionMethodBuilder rmb
;
2547 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, mb
));
2551 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
2553 name
= mono_string_to_utf8 (rmb
.name
);
2554 token
= mono_image_get_memberref_token (assembly
, ((MonoReflectionTypeBuilder
*)rmb
.type
)->type
.type
,
2555 name
, method_builder_encode_signature (assembly
, &rmb
));
2558 g_hash_table_insert (assembly
->handleref
, mb
, GUINT_TO_POINTER(token
));
2564 is_field_on_inst (MonoClassField
*field
)
2566 return (field
->parent
->generic_class
&& field
->parent
->generic_class
->is_dynamic
&& ((MonoDynamicGenericClass
*)field
->parent
->generic_class
)->fields
);
2570 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2573 get_field_on_inst_generic_type (MonoClassField
*field
)
2575 MonoDynamicGenericClass
*dgclass
;
2578 g_assert (is_field_on_inst (field
));
2580 dgclass
= (MonoDynamicGenericClass
*)field
->parent
->generic_class
;
2581 field_index
= field
- dgclass
->fields
;
2583 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
2584 return dgclass
->field_generic_types
[field_index
];
2587 #ifndef DISABLE_REFLECTION_EMIT
2589 mono_image_get_fieldref_token (MonoDynamicImage
*assembly
, MonoReflectionField
*f
)
2593 MonoClassField
*field
;
2595 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, f
));
2598 g_assert (f
->field
->parent
);
2601 if (field
->parent
->generic_class
&& field
->parent
->generic_class
->container_class
&& field
->parent
->generic_class
->container_class
->fields
) {
2602 int index
= field
- field
->parent
->fields
;
2603 type
= field
->parent
->generic_class
->container_class
->fields
[index
].type
;
2605 if (is_field_on_inst (f
->field
))
2606 type
= get_field_on_inst_generic_type (f
->field
);
2608 type
= f
->field
->type
;
2610 token
= mono_image_get_memberref_token (assembly
, &f
->field
->parent
->byval_arg
,
2611 mono_field_get_name (f
->field
),
2612 fieldref_encode_signature (assembly
, type
));
2613 g_hash_table_insert (assembly
->handleref
, f
, GUINT_TO_POINTER(token
));
2618 mono_image_get_field_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionFieldOnTypeBuilderInst
*f
)
2622 MonoGenericClass
*gclass
;
2623 MonoDynamicGenericClass
*dgclass
;
2624 MonoReflectionFieldBuilder
*fb
= f
->fb
;
2627 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, f
));
2630 klass
= mono_class_from_mono_type (f
->inst
->type
.type
);
2631 gclass
= f
->inst
->type
.type
->data
.generic_class
;
2632 g_assert (gclass
->is_dynamic
);
2633 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2635 name
= mono_string_to_utf8 (fb
->name
);
2636 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
,
2637 field_encode_signature (assembly
, fb
));
2639 g_hash_table_insert (assembly
->handleref
, f
, GUINT_TO_POINTER (token
));
2644 mono_image_get_ctor_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionCtorOnTypeBuilderInst
*c
, gboolean create_methodspec
)
2648 MonoGenericClass
*gclass
;
2649 MonoDynamicGenericClass
*dgclass
;
2650 MonoReflectionCtorBuilder
*cb
= c
->cb
;
2651 ReflectionMethodBuilder rmb
;
2654 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2656 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, c
));
2659 klass
= mono_class_from_mono_type (c
->inst
->type
.type
);
2660 gclass
= c
->inst
->type
.type
->data
.generic_class
;
2661 g_assert (gclass
->is_dynamic
);
2662 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2664 reflection_methodbuilder_from_ctor_builder (&rmb
, cb
);
2666 name
= mono_string_to_utf8 (rmb
.name
);
2668 sig
= method_builder_encode_signature (assembly
, &rmb
);
2670 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2673 g_hash_table_insert (assembly
->handleref
, c
, GUINT_TO_POINTER (token
));
2678 mono_image_get_method_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionMethodOnTypeBuilderInst
*m
, gboolean create_methodspec
)
2682 MonoGenericClass
*gclass
;
2683 MonoReflectionMethodBuilder
*mb
= m
->mb
;
2684 ReflectionMethodBuilder rmb
;
2687 if (create_methodspec
&& mb
->generic_params
)
2689 g_assert_not_reached ();
2691 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, m
));
2694 klass
= mono_class_from_mono_type (m
->inst
->type
.type
);
2695 gclass
= m
->inst
->type
.type
->data
.generic_class
;
2696 g_assert (gclass
->is_dynamic
);
2698 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
2700 name
= mono_string_to_utf8 (rmb
.name
);
2702 sig
= method_builder_encode_signature (assembly
, &rmb
);
2704 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2707 g_hash_table_insert (assembly
->handleref
, m
, GUINT_TO_POINTER (token
));
2712 encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
)
2716 guint32 nparams
= context
->method_inst
->type_argc
;
2719 if (!assembly
->save
)
2722 sigbuffer_init (&buf
, 32);
2724 * FIXME: vararg, explicit_this, differenc call_conv values...
2726 sigbuffer_add_value (&buf
, 0xa); /* FIXME FIXME FIXME */
2727 sigbuffer_add_value (&buf
, nparams
);
2729 for (i
= 0; i
< nparams
; i
++)
2730 encode_type (assembly
, context
->method_inst
->type_argv
[i
], &buf
);
2732 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2733 sigbuffer_free (&buf
);
2738 method_encode_methodspec (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2740 MonoDynamicTable
*table
;
2742 guint32 token
, mtoken
= 0, sig
;
2743 MonoMethodInflated
*imethod
;
2744 MonoMethod
*declaring
;
2746 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2748 g_assert (method
->is_inflated
);
2749 imethod
= (MonoMethodInflated
*) method
;
2750 declaring
= imethod
->declaring
;
2752 sig
= method_encode_signature (assembly
, mono_method_signature (declaring
));
2753 mtoken
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
, declaring
->name
, sig
);
2755 if (!mono_method_signature (declaring
)->generic_param_count
)
2758 switch (mono_metadata_token_table (mtoken
)) {
2759 case MONO_TABLE_MEMBERREF
:
2760 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2762 case MONO_TABLE_METHOD
:
2763 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2766 g_assert_not_reached ();
2769 sig
= encode_generic_method_sig (assembly
, mono_method_get_context (method
));
2771 if (assembly
->save
) {
2772 alloc_table (table
, table
->rows
+ 1);
2773 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2774 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2775 values
[MONO_METHODSPEC_SIGNATURE
] = sig
;
2778 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2785 mono_image_get_methodspec_token (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2787 MonoMethodInflated
*imethod
;
2790 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2794 g_assert (method
->is_inflated
);
2795 imethod
= (MonoMethodInflated
*) method
;
2797 if (mono_method_signature (imethod
->declaring
)->generic_param_count
) {
2798 token
= method_encode_methodspec (assembly
, method
);
2800 guint32 sig
= method_encode_signature (
2801 assembly
, mono_method_signature (imethod
->declaring
));
2802 token
= mono_image_get_memberref_token (
2803 assembly
, &method
->klass
->byval_arg
, method
->name
, sig
);
2806 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2811 mono_image_get_inflated_method_token (MonoDynamicImage
*assembly
, MonoMethod
*m
)
2813 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) m
;
2816 sig
= method_encode_signature (assembly
, mono_method_signature (imethod
->declaring
));
2817 token
= mono_image_get_memberref_token (
2818 assembly
, &m
->klass
->byval_arg
, m
->name
, sig
);
2824 create_generic_typespec (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
)
2826 MonoDynamicTable
*table
;
2834 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2835 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2836 * Because of this, we must not insert it into the `typeref' hash table.
2839 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, tb
->type
.type
));
2843 sigbuffer_init (&buf
, 32);
2845 g_assert (tb
->generic_params
);
2846 klass
= mono_class_from_mono_type (tb
->type
.type
);
2848 if (tb
->generic_container
)
2849 mono_reflection_create_generic_class (tb
);
2851 sigbuffer_add_value (&buf
, MONO_TYPE_GENERICINST
);
2852 g_assert (klass
->generic_container
);
2853 sigbuffer_add_value (&buf
, klass
->byval_arg
.type
);
2854 sigbuffer_add_value (&buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
2856 count
= mono_array_length (tb
->generic_params
);
2857 sigbuffer_add_value (&buf
, count
);
2858 for (i
= 0; i
< count
; i
++) {
2859 MonoReflectionGenericParam
*gparam
;
2861 gparam
= mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
);
2863 encode_type (assembly
, gparam
->type
.type
, &buf
);
2866 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2868 if (assembly
->save
) {
2869 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2870 alloc_table (table
, table
->rows
+ 1);
2871 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2872 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2874 sigbuffer_free (&buf
);
2876 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2877 g_hash_table_insert (assembly
->typespec
, tb
->type
.type
, GUINT_TO_POINTER(token
));
2883 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2886 add_custom_modifiers (MonoDynamicImage
*assembly
, MonoType
*type
, MonoArray
*modreq
, MonoArray
*modopt
)
2888 int i
, count
, len
, pos
;
2893 count
+= mono_array_length (modreq
);
2895 count
+= mono_array_length (modopt
);
2898 return mono_metadata_type_dup (NULL
, type
);
2900 len
= sizeof (MonoType
) + ((gint32
)count
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoCustomMod
);
2902 memcpy (t
, type
, sizeof (MonoType
));
2904 t
->num_mods
= count
;
2907 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
2908 MonoReflectionType
*mod
= mono_type_array_get (modreq
, i
);
2909 t
->modifiers
[pos
].required
= 1;
2910 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
->type
);
2915 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
2916 MonoReflectionType
*mod
= mono_type_array_get (modopt
, i
);
2917 t
->modifiers
[pos
].required
= 0;
2918 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
->type
);
2927 mono_image_get_generic_field_token (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
2929 MonoDynamicTable
*table
;
2931 MonoType
*custom
= NULL
;
2933 guint32 token
, pclass
, parent
, sig
;
2936 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, fb
));
2940 klass
= mono_class_from_mono_type (fb
->typeb
->type
);
2941 name
= mono_string_to_utf8 (fb
->name
);
2943 /* fb->type does not include the custom modifiers */
2944 /* FIXME: We should do this in one place when a fieldbuilder is created */
2945 if (fb
->modreq
|| fb
->modopt
) {
2946 custom
= add_custom_modifiers (assembly
, monotype_cast (fb
->type
)->type
, fb
->modreq
, fb
->modopt
);
2947 sig
= fieldref_encode_signature (assembly
, custom
);
2950 sig
= fieldref_encode_signature (assembly
, monotype_cast (fb
->type
)->type
);
2953 parent
= create_generic_typespec (assembly
, (MonoReflectionTypeBuilder
*) fb
->typeb
);
2954 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_TYPEDEFORREF_TYPESPEC
);
2956 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2957 parent
>>= MONO_TYPEDEFORREF_BITS
;
2959 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2961 if (assembly
->save
) {
2962 alloc_table (table
, table
->rows
+ 1);
2963 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2964 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2965 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2966 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2969 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2971 g_hash_table_insert (assembly
->handleref
, fb
, GUINT_TO_POINTER(token
));
2977 mono_reflection_encode_sighelper (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
2984 if (!assembly
->save
)
2987 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2988 g_assert (helper
->type
== 2);
2990 if (helper
->arguments
)
2991 nargs
= mono_array_length (helper
->arguments
);
2995 size
= 10 + (nargs
* 10);
2997 sigbuffer_init (&buf
, 32);
2999 /* Encode calling convention */
3000 /* Change Any to Standard */
3001 if ((helper
->call_conv
& 0x03) == 0x03)
3002 helper
->call_conv
= 0x01;
3003 /* explicit_this implies has_this */
3004 if (helper
->call_conv
& 0x40)
3005 helper
->call_conv
&= 0x20;
3007 if (helper
->call_conv
== 0) { /* Unmanaged */
3008 idx
= helper
->unmanaged_call_conv
- 1;
3011 idx
= helper
->call_conv
& 0x60; /* has_this + explicit_this */
3012 if (helper
->call_conv
& 0x02) /* varargs */
3016 sigbuffer_add_byte (&buf
, idx
);
3017 sigbuffer_add_value (&buf
, nargs
);
3018 encode_reflection_type (assembly
, helper
->return_type
, &buf
);
3019 for (i
= 0; i
< nargs
; ++i
) {
3020 MonoArray
*modreqs
= NULL
;
3021 MonoArray
*modopts
= NULL
;
3022 MonoReflectionType
*pt
;
3024 if (helper
->modreqs
&& (i
< mono_array_length (helper
->modreqs
)))
3025 modreqs
= mono_array_get (helper
->modreqs
, MonoArray
*, i
);
3026 if (helper
->modopts
&& (i
< mono_array_length (helper
->modopts
)))
3027 modopts
= mono_array_get (helper
->modopts
, MonoArray
*, i
);
3029 encode_custom_modifiers (assembly
, modreqs
, modopts
, &buf
);
3030 pt
= mono_type_array_get (helper
->arguments
, i
);
3031 encode_reflection_type (assembly
, pt
, &buf
);
3033 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3034 sigbuffer_free (&buf
);
3040 mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
3043 MonoDynamicTable
*table
;
3046 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
3047 idx
= table
->next_idx
++;
3049 alloc_table (table
, table
->rows
);
3050 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
3052 values
[MONO_STAND_ALONE_SIGNATURE
] =
3053 mono_reflection_encode_sighelper (assembly
, helper
);
3059 reflection_cc_to_file (int call_conv
) {
3060 switch (call_conv
& 0x3) {
3062 case 1: return MONO_CALL_DEFAULT
;
3063 case 2: return MONO_CALL_VARARG
;
3065 g_assert_not_reached ();
3069 #endif /* !DISABLE_REFLECTION_EMIT */
3073 MonoMethodSignature
*sig
;
3078 #ifndef DISABLE_REFLECTION_EMIT
3080 mono_image_get_array_token (MonoDynamicImage
*assembly
, MonoReflectionArrayMethod
*m
)
3085 MonoMethodSignature
*sig
;
3088 name
= mono_string_to_utf8 (m
->name
);
3089 nparams
= mono_array_length (m
->parameters
);
3090 sig
= g_malloc0 (sizeof (MonoMethodSignature
) + sizeof (MonoType
*) * nparams
);
3092 sig
->sentinelpos
= -1;
3093 sig
->call_convention
= reflection_cc_to_file (m
->call_conv
);
3094 sig
->param_count
= nparams
;
3095 sig
->ret
= m
->ret
? m
->ret
->type
: &mono_defaults
.void_class
->byval_arg
;
3096 for (i
= 0; i
< nparams
; ++i
) {
3097 MonoReflectionType
*t
= mono_type_array_get (m
->parameters
, i
);
3098 sig
->params
[i
] = t
->type
;
3101 for (tmp
= assembly
->array_methods
; tmp
; tmp
= tmp
->next
) {
3103 if (strcmp (name
, am
->name
) == 0 &&
3104 mono_metadata_type_equal (am
->parent
, m
->parent
->type
) &&
3105 mono_metadata_signature_equal (am
->sig
, sig
)) {
3108 m
->table_idx
= am
->token
& 0xffffff;
3112 am
= g_new0 (ArrayMethod
, 1);
3115 am
->parent
= m
->parent
->type
;
3116 am
->token
= mono_image_get_memberref_token (assembly
, am
->parent
, name
,
3117 method_encode_signature (assembly
, sig
));
3118 assembly
->array_methods
= g_list_prepend (assembly
->array_methods
, am
);
3119 m
->table_idx
= am
->token
& 0xffffff;
3125 * Insert into the metadata tables all the info about the TypeBuilder tb.
3126 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3129 mono_image_get_type_info (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
, MonoDynamicImage
*assembly
)
3131 MonoDynamicTable
*table
;
3133 int i
, is_object
= 0, is_system
= 0;
3136 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
3137 values
= table
->values
+ tb
->table_idx
* MONO_TYPEDEF_SIZE
;
3138 values
[MONO_TYPEDEF_FLAGS
] = tb
->attrs
;
3139 n
= mono_string_to_utf8 (tb
->name
);
3140 if (strcmp (n
, "Object") == 0)
3142 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, n
);
3144 n
= mono_string_to_utf8 (tb
->nspace
);
3145 if (strcmp (n
, "System") == 0)
3147 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, n
);
3149 if (tb
->parent
&& !(is_system
&& is_object
) &&
3150 !(tb
->attrs
& TYPE_ATTRIBUTE_INTERFACE
)) { /* interfaces don't have a parent */
3151 values
[MONO_TYPEDEF_EXTENDS
] = mono_image_typedef_or_ref (assembly
, monotype_cast (tb
->parent
)->type
);
3153 values
[MONO_TYPEDEF_EXTENDS
] = 0;
3155 values
[MONO_TYPEDEF_FIELD_LIST
] = assembly
->tables
[MONO_TABLE_FIELD
].next_idx
;
3156 values
[MONO_TYPEDEF_METHOD_LIST
] = assembly
->tables
[MONO_TABLE_METHOD
].next_idx
;
3159 * if we have explicitlayout or sequentiallayouts, output data in the
3160 * ClassLayout table.
3162 if (((tb
->attrs
& TYPE_ATTRIBUTE_LAYOUT_MASK
) != TYPE_ATTRIBUTE_AUTO_LAYOUT
) &&
3163 ((tb
->class_size
> 0) || (tb
->packing_size
> 0))) {
3164 table
= &assembly
->tables
[MONO_TABLE_CLASSLAYOUT
];
3166 alloc_table (table
, table
->rows
);
3167 values
= table
->values
+ table
->rows
* MONO_CLASS_LAYOUT_SIZE
;
3168 values
[MONO_CLASS_LAYOUT_PARENT
] = tb
->table_idx
;
3169 values
[MONO_CLASS_LAYOUT_CLASS_SIZE
] = tb
->class_size
;
3170 values
[MONO_CLASS_LAYOUT_PACKING_SIZE
] = tb
->packing_size
;
3173 /* handle interfaces */
3174 if (tb
->interfaces
) {
3175 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3177 table
->rows
+= mono_array_length (tb
->interfaces
);
3178 alloc_table (table
, table
->rows
);
3179 values
= table
->values
+ (i
+ 1) * MONO_INTERFACEIMPL_SIZE
;
3180 for (i
= 0; i
< mono_array_length (tb
->interfaces
); ++i
) {
3181 MonoReflectionType
* iface
= (MonoReflectionType
*) mono_array_get (tb
->interfaces
, gpointer
, i
);
3182 values
[MONO_INTERFACEIMPL_CLASS
] = tb
->table_idx
;
3183 values
[MONO_INTERFACEIMPL_INTERFACE
] = mono_image_typedef_or_ref (assembly
, iface
->type
);
3184 values
+= MONO_INTERFACEIMPL_SIZE
;
3190 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
3191 table
->rows
+= tb
->num_fields
;
3192 alloc_table (table
, table
->rows
);
3193 for (i
= 0; i
< tb
->num_fields
; ++i
)
3194 mono_image_get_field_info (
3195 mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
3198 /* handle constructors */
3200 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3201 table
->rows
+= mono_array_length (tb
->ctors
);
3202 alloc_table (table
, table
->rows
);
3203 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
)
3204 mono_image_get_ctor_info (domain
,
3205 mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
), assembly
);
3208 /* handle methods */
3210 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3211 table
->rows
+= tb
->num_methods
;
3212 alloc_table (table
, table
->rows
);
3213 for (i
= 0; i
< tb
->num_methods
; ++i
)
3214 mono_image_get_method_info (
3215 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
3218 /* Do the same with properties etc.. */
3219 if (tb
->events
&& mono_array_length (tb
->events
)) {
3220 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
3221 table
->rows
+= mono_array_length (tb
->events
);
3222 alloc_table (table
, table
->rows
);
3223 table
= &assembly
->tables
[MONO_TABLE_EVENTMAP
];
3225 alloc_table (table
, table
->rows
);
3226 values
= table
->values
+ table
->rows
* MONO_EVENT_MAP_SIZE
;
3227 values
[MONO_EVENT_MAP_PARENT
] = tb
->table_idx
;
3228 values
[MONO_EVENT_MAP_EVENTLIST
] = assembly
->tables
[MONO_TABLE_EVENT
].next_idx
;
3229 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
)
3230 mono_image_get_event_info (
3231 mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
), assembly
);
3233 if (tb
->properties
&& mono_array_length (tb
->properties
)) {
3234 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
3235 table
->rows
+= mono_array_length (tb
->properties
);
3236 alloc_table (table
, table
->rows
);
3237 table
= &assembly
->tables
[MONO_TABLE_PROPERTYMAP
];
3239 alloc_table (table
, table
->rows
);
3240 values
= table
->values
+ table
->rows
* MONO_PROPERTY_MAP_SIZE
;
3241 values
[MONO_PROPERTY_MAP_PARENT
] = tb
->table_idx
;
3242 values
[MONO_PROPERTY_MAP_PROPERTY_LIST
] = assembly
->tables
[MONO_TABLE_PROPERTY
].next_idx
;
3243 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
)
3244 mono_image_get_property_info (
3245 mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
), assembly
);
3248 /* handle generic parameters */
3249 if (tb
->generic_params
) {
3250 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
3251 table
->rows
+= mono_array_length (tb
->generic_params
);
3252 alloc_table (table
, table
->rows
);
3253 for (i
= 0; i
< mono_array_length (tb
->generic_params
); ++i
) {
3254 guint32 owner
= MONO_TYPEORMETHOD_TYPE
| (tb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
3256 mono_image_get_generic_param_info (
3257 mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
), owner
, assembly
);
3261 mono_image_add_decl_security (assembly
,
3262 mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
), tb
->permissions
);
3265 MonoDynamicTable
*ntable
;
3267 ntable
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3268 ntable
->rows
+= mono_array_length (tb
->subtypes
);
3269 alloc_table (ntable
, ntable
->rows
);
3270 values
= ntable
->values
+ ntable
->next_idx
* MONO_NESTED_CLASS_SIZE
;
3272 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
3273 MonoReflectionTypeBuilder
*subtype
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3275 values
[MONO_NESTED_CLASS_NESTED
] = subtype
->table_idx
;
3276 values
[MONO_NESTED_CLASS_ENCLOSING
] = tb
->table_idx
;
3277 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3278 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3279 mono_string_to_utf8 (tb->name), tb->table_idx,
3280 ntable->next_idx, ntable->rows);*/
3281 values
+= MONO_NESTED_CLASS_SIZE
;
3288 collect_types (GPtrArray
*types
, MonoReflectionTypeBuilder
*type
)
3292 g_ptr_array_add (types
, type
); /* FIXME: GC object added to unmanaged memory */
3294 if (!type
->subtypes
)
3297 for (i
= 0; i
< mono_array_length (type
->subtypes
); ++i
) {
3298 MonoReflectionTypeBuilder
*subtype
= mono_array_get (type
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3299 collect_types (types
, subtype
);
3304 compare_types_by_table_idx (MonoReflectionTypeBuilder
**type1
, MonoReflectionTypeBuilder
**type2
)
3306 if ((*type1
)->table_idx
< (*type2
)->table_idx
)
3309 if ((*type1
)->table_idx
> (*type2
)->table_idx
)
3316 params_add_cattrs (MonoDynamicImage
*assembly
, MonoArray
*pinfo
) {
3321 for (i
= 0; i
< mono_array_length (pinfo
); ++i
) {
3322 MonoReflectionParamBuilder
*pb
;
3323 pb
= mono_array_get (pinfo
, MonoReflectionParamBuilder
*, i
);
3326 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PARAMDEF
, pb
->cattrs
);
3331 type_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
) {
3334 mono_image_add_cattrs (assembly
, tb
->table_idx
, MONO_CUSTOM_ATTR_TYPEDEF
, tb
->cattrs
);
3336 for (i
= 0; i
< tb
->num_fields
; ++i
) {
3337 MonoReflectionFieldBuilder
* fb
;
3338 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
);
3339 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3343 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
) {
3344 MonoReflectionEventBuilder
* eb
;
3345 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
3346 mono_image_add_cattrs (assembly
, eb
->table_idx
, MONO_CUSTOM_ATTR_EVENT
, eb
->cattrs
);
3349 if (tb
->properties
) {
3350 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
) {
3351 MonoReflectionPropertyBuilder
* pb
;
3352 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
3353 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PROPERTY
, pb
->cattrs
);
3357 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
3358 MonoReflectionCtorBuilder
* cb
;
3359 cb
= mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
);
3360 mono_image_add_cattrs (assembly
, cb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, cb
->cattrs
);
3361 params_add_cattrs (assembly
, cb
->pinfo
);
3366 for (i
= 0; i
< tb
->num_methods
; ++i
) {
3367 MonoReflectionMethodBuilder
* mb
;
3368 mb
= mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
3369 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3370 params_add_cattrs (assembly
, mb
->pinfo
);
3375 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3376 type_add_cattrs (assembly
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
));
3381 module_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionModuleBuilder
*moduleb
)
3385 mono_image_add_cattrs (assembly
, moduleb
->table_idx
, MONO_CUSTOM_ATTR_MODULE
, moduleb
->cattrs
);
3387 if (moduleb
->global_methods
) {
3388 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
3389 MonoReflectionMethodBuilder
* mb
= mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
3390 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3391 params_add_cattrs (assembly
, mb
->pinfo
);
3395 if (moduleb
->global_fields
) {
3396 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
) {
3397 MonoReflectionFieldBuilder
*fb
= mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
);
3398 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3402 if (moduleb
->types
) {
3403 for (i
= 0; i
< moduleb
->num_types
; ++i
)
3404 type_add_cattrs (assembly
, mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
));
3409 mono_image_fill_file_table (MonoDomain
*domain
, MonoReflectionModule
*module
, MonoDynamicImage
*assembly
)
3411 MonoDynamicTable
*table
;
3415 char *b
= blob_size
;
3418 table
= &assembly
->tables
[MONO_TABLE_FILE
];
3420 alloc_table (table
, table
->rows
);
3421 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
3422 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_METADATA
;
3423 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, module
->image
->module_name
);
3424 if (module
->image
->dynamic
) {
3425 /* This depends on the fact that the main module is emitted last */
3426 dir
= mono_string_to_utf8 (((MonoReflectionModuleBuilder
*)module
)->assemblyb
->dir
);
3427 path
= g_strdup_printf ("%s%c%s", dir
, G_DIR_SEPARATOR
, module
->image
->module_name
);
3430 path
= g_strdup (module
->image
->name
);
3432 mono_sha1_get_digest_from_file (path
, hash
);
3435 mono_metadata_encode_value (20, b
, &b
);
3436 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
3437 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
3442 mono_image_fill_module_table (MonoDomain
*domain
, MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
)
3444 MonoDynamicTable
*table
;
3447 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
3448 mb
->table_idx
= table
->next_idx
++;
3449 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->module
.name
);
3450 i
= mono_image_add_stream_data (&assembly
->guid
, mono_array_addr (mb
->guid
, char, 0), 16);
3453 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_GENERATION
] = 0;
3454 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_MVID
] = i
;
3455 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENC
] = 0;
3456 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENCBASE
] = 0;
3460 mono_image_fill_export_table_from_class (MonoDomain
*domain
, MonoClass
*klass
,
3461 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3463 MonoDynamicTable
*table
;
3467 visib
= klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
3468 if (! ((visib
& TYPE_ATTRIBUTE_PUBLIC
) || (visib
& TYPE_ATTRIBUTE_NESTED_PUBLIC
)))
3471 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3473 alloc_table (table
, table
->rows
);
3474 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3476 values
[MONO_EXP_TYPE_FLAGS
] = klass
->flags
;
3477 values
[MONO_EXP_TYPE_TYPEDEF
] = klass
->type_token
;
3478 if (klass
->nested_in
)
3479 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (parent_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
3481 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (module_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_FILE
;
3482 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3483 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3485 res
= table
->next_idx
;
3489 /* Emit nested types */
3490 if (klass
->ext
&& klass
->ext
->nested_classes
) {
3493 for (tmp
= klass
->ext
->nested_classes
; tmp
; tmp
= tmp
->next
)
3494 mono_image_fill_export_table_from_class (domain
, tmp
->data
, module_index
, table
->next_idx
- 1, assembly
);
3501 mono_image_fill_export_table (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
,
3502 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3507 klass
= mono_class_from_mono_type (tb
->type
.type
);
3509 klass
->type_token
= mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
);
3511 idx
= mono_image_fill_export_table_from_class (domain
, klass
, module_index
,
3512 parent_index
, assembly
);
3516 * We need to do this ourselves since klass->nested_classes is not set up.
3519 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3520 mono_image_fill_export_table (domain
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
), module_index
, idx
, assembly
);
3525 mono_image_fill_export_table_from_module (MonoDomain
*domain
, MonoReflectionModule
*module
,
3526 guint32 module_index
, MonoDynamicImage
*assembly
)
3528 MonoImage
*image
= module
->image
;
3532 t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
3534 for (i
= 0; i
< t
->rows
; ++i
) {
3535 MonoClass
*klass
= mono_class_get (image
, mono_metadata_make_token (MONO_TABLE_TYPEDEF
, i
+ 1));
3537 if (klass
->flags
& TYPE_ATTRIBUTE_PUBLIC
)
3538 mono_image_fill_export_table_from_class (domain
, klass
, module_index
, 0, assembly
);
3543 add_exported_type (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
, MonoClass
*klass
)
3545 MonoDynamicTable
*table
;
3547 guint32 scope
, idx
, res
, impl
;
3548 gboolean forwarder
= TRUE
;
3550 if (klass
->nested_in
) {
3551 impl
= add_exported_type (assemblyb
, assembly
, klass
->nested_in
);
3554 scope
= resolution_scope_from_image (assembly
, klass
->image
);
3555 g_assert ((scope
& MONO_RESOLTION_SCOPE_MASK
) == MONO_RESOLTION_SCOPE_ASSEMBLYREF
);
3556 idx
= scope
>> MONO_RESOLTION_SCOPE_BITS
;
3557 impl
= (idx
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_ASSEMBLYREF
;
3560 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3563 alloc_table (table
, table
->rows
);
3564 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3566 values
[MONO_EXP_TYPE_FLAGS
] = forwarder
? TYPE_ATTRIBUTE_FORWARDER
: 0;
3567 values
[MONO_EXP_TYPE_TYPEDEF
] = 0;
3568 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = impl
;
3569 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3570 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3572 res
= (table
->next_idx
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
3580 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
)
3585 if (!assemblyb
->type_forwarders
)
3588 for (i
= 0; i
< mono_array_length (assemblyb
->type_forwarders
); ++i
) {
3589 MonoReflectionType
*t
= mono_type_array_get (assemblyb
->type_forwarders
, i
);
3595 klass
= mono_class_from_mono_type (t
->type
);
3597 add_exported_type (assemblyb
, assembly
, klass
);
3601 #define align_pointer(base,p)\
3603 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3605 (p) += 4 - (__diff & 3);\
3609 compare_constants (const void *a
, const void *b
)
3611 const guint32
*a_values
= a
;
3612 const guint32
*b_values
= b
;
3613 return a_values
[MONO_CONSTANT_PARENT
] - b_values
[MONO_CONSTANT_PARENT
];
3617 compare_semantics (const void *a
, const void *b
)
3619 const guint32
*a_values
= a
;
3620 const guint32
*b_values
= b
;
3621 int assoc
= a_values
[MONO_METHOD_SEMA_ASSOCIATION
] - b_values
[MONO_METHOD_SEMA_ASSOCIATION
];
3624 return a_values
[MONO_METHOD_SEMA_SEMANTICS
] - b_values
[MONO_METHOD_SEMA_SEMANTICS
];
3628 compare_custom_attrs (const void *a
, const void *b
)
3630 const guint32
*a_values
= a
;
3631 const guint32
*b_values
= b
;
3633 return a_values
[MONO_CUSTOM_ATTR_PARENT
] - b_values
[MONO_CUSTOM_ATTR_PARENT
];
3637 compare_field_marshal (const void *a
, const void *b
)
3639 const guint32
*a_values
= a
;
3640 const guint32
*b_values
= b
;
3642 return a_values
[MONO_FIELD_MARSHAL_PARENT
] - b_values
[MONO_FIELD_MARSHAL_PARENT
];
3646 compare_nested (const void *a
, const void *b
)
3648 const guint32
*a_values
= a
;
3649 const guint32
*b_values
= b
;
3651 return a_values
[MONO_NESTED_CLASS_NESTED
] - b_values
[MONO_NESTED_CLASS_NESTED
];
3655 compare_genericparam (const void *a
, const void *b
)
3657 const GenericParamTableEntry
**a_entry
= (const GenericParamTableEntry
**) a
;
3658 const GenericParamTableEntry
**b_entry
= (const GenericParamTableEntry
**) b
;
3660 if ((*b_entry
)->owner
== (*a_entry
)->owner
)
3662 mono_type_get_generic_param_num ((*a_entry
)->gparam
->type
.type
) -
3663 mono_type_get_generic_param_num ((*b_entry
)->gparam
->type
.type
);
3665 return (*a_entry
)->owner
- (*b_entry
)->owner
;
3669 compare_declsecurity_attrs (const void *a
, const void *b
)
3671 const guint32
*a_values
= a
;
3672 const guint32
*b_values
= b
;
3674 return a_values
[MONO_DECL_SECURITY_PARENT
] - b_values
[MONO_DECL_SECURITY_PARENT
];
3678 compare_interface_impl (const void *a
, const void *b
)
3680 const guint32
*a_values
= a
;
3681 const guint32
*b_values
= b
;
3683 int klass
= a_values
[MONO_INTERFACEIMPL_CLASS
] - b_values
[MONO_INTERFACEIMPL_CLASS
];
3687 return a_values
[MONO_INTERFACEIMPL_INTERFACE
] - b_values
[MONO_INTERFACEIMPL_INTERFACE
];
3691 pad_heap (MonoDynamicStream
*sh
)
3693 if (sh
->index
& 3) {
3694 int sz
= 4 - (sh
->index
& 3);
3695 memset (sh
->data
+ sh
->index
, 0, sz
);
3702 MonoDynamicStream
*stream
;
3706 * build_compressed_metadata() fills in the blob of data that represents the
3707 * raw metadata as it will be saved in the PE file. The five streams are output
3708 * and the metadata tables are comnpressed from the guint32 array representation,
3709 * to the compressed on-disk format.
3712 build_compressed_metadata (MonoDynamicImage
*assembly
)
3714 MonoDynamicTable
*table
;
3716 guint64 valid_mask
= 0;
3717 guint64 sorted_mask
;
3718 guint32 heapt_size
= 0;
3719 guint32 meta_size
= 256; /* allow for header and other stuff */
3720 guint32 table_offset
;
3721 guint32 ntables
= 0;
3727 struct StreamDesc stream_desc
[5];
3729 qsort (assembly
->gen_params
->pdata
, assembly
->gen_params
->len
, sizeof (gpointer
), compare_genericparam
);
3730 for (i
= 0; i
< assembly
->gen_params
->len
; i
++){
3731 GenericParamTableEntry
*entry
= g_ptr_array_index (assembly
->gen_params
, i
);
3732 write_generic_param_entry (assembly
, entry
);
3735 stream_desc
[0].name
= "#~";
3736 stream_desc
[0].stream
= &assembly
->tstream
;
3737 stream_desc
[1].name
= "#Strings";
3738 stream_desc
[1].stream
= &assembly
->sheap
;
3739 stream_desc
[2].name
= "#US";
3740 stream_desc
[2].stream
= &assembly
->us
;
3741 stream_desc
[3].name
= "#Blob";
3742 stream_desc
[3].stream
= &assembly
->blob
;
3743 stream_desc
[4].name
= "#GUID";
3744 stream_desc
[4].stream
= &assembly
->guid
;
3746 /* tables that are sorted */
3747 sorted_mask
= ((guint64
)1 << MONO_TABLE_CONSTANT
) | ((guint64
)1 << MONO_TABLE_FIELDMARSHAL
)
3748 | ((guint64
)1 << MONO_TABLE_METHODSEMANTICS
) | ((guint64
)1 << MONO_TABLE_CLASSLAYOUT
)
3749 | ((guint64
)1 << MONO_TABLE_FIELDLAYOUT
) | ((guint64
)1 << MONO_TABLE_FIELDRVA
)
3750 | ((guint64
)1 << MONO_TABLE_IMPLMAP
) | ((guint64
)1 << MONO_TABLE_NESTEDCLASS
)
3751 | ((guint64
)1 << MONO_TABLE_METHODIMPL
) | ((guint64
)1 << MONO_TABLE_CUSTOMATTRIBUTE
)
3752 | ((guint64
)1 << MONO_TABLE_DECLSECURITY
) | ((guint64
)1 << MONO_TABLE_GENERICPARAM
)
3753 | ((guint64
)1 << MONO_TABLE_INTERFACEIMPL
);
3755 /* Compute table sizes */
3756 /* the MonoImage has already been created in mono_image_basic_init() */
3757 meta
= &assembly
->image
;
3759 /* sizes should be multiple of 4 */
3760 pad_heap (&assembly
->blob
);
3761 pad_heap (&assembly
->guid
);
3762 pad_heap (&assembly
->sheap
);
3763 pad_heap (&assembly
->us
);
3765 /* Setup the info used by compute_sizes () */
3766 meta
->idx_blob_wide
= assembly
->blob
.index
>= 65536 ? 1 : 0;
3767 meta
->idx_guid_wide
= assembly
->guid
.index
>= 65536 ? 1 : 0;
3768 meta
->idx_string_wide
= assembly
->sheap
.index
>= 65536 ? 1 : 0;
3770 meta_size
+= assembly
->blob
.index
;
3771 meta_size
+= assembly
->guid
.index
;
3772 meta_size
+= assembly
->sheap
.index
;
3773 meta_size
+= assembly
->us
.index
;
3775 for (i
=0; i
< MONO_TABLE_NUM
; ++i
)
3776 meta
->tables
[i
].rows
= assembly
->tables
[i
].rows
;
3778 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3779 if (meta
->tables
[i
].rows
== 0)
3781 valid_mask
|= (guint64
)1 << i
;
3783 meta
->tables
[i
].row_size
= mono_metadata_compute_size (
3784 meta
, i
, &meta
->tables
[i
].size_bitfield
);
3785 heapt_size
+= meta
->tables
[i
].row_size
* meta
->tables
[i
].rows
;
3787 heapt_size
+= 24; /* #~ header size */
3788 heapt_size
+= ntables
* 4;
3789 /* make multiple of 4 */
3792 meta_size
+= heapt_size
;
3793 meta
->raw_metadata
= g_malloc0 (meta_size
);
3794 p
= (unsigned char*)meta
->raw_metadata
;
3795 /* the metadata signature */
3796 *p
++ = 'B'; *p
++ = 'S'; *p
++ = 'J'; *p
++ = 'B';
3797 /* version numbers and 4 bytes reserved */
3798 int16val
= (guint16
*)p
;
3799 *int16val
++ = GUINT16_TO_LE (meta
->md_version_major
);
3800 *int16val
= GUINT16_TO_LE (meta
->md_version_minor
);
3802 /* version string */
3803 int32val
= (guint32
*)p
;
3804 *int32val
= GUINT32_TO_LE ((strlen (meta
->version
) + 3) & (~3)); /* needs to be multiple of 4 */
3806 memcpy (p
, meta
->version
, strlen (meta
->version
));
3807 p
+= GUINT32_FROM_LE (*int32val
);
3808 align_pointer (meta
->raw_metadata
, p
);
3809 int16val
= (guint16
*)p
;
3810 *int16val
++ = GUINT16_TO_LE (0); /* flags must be 0 */
3811 *int16val
= GUINT16_TO_LE (5); /* number of streams */
3815 * write the stream info.
3817 table_offset
= (p
- (unsigned char*)meta
->raw_metadata
) + 5 * 8 + 40; /* room needed for stream headers */
3818 table_offset
+= 3; table_offset
&= ~3;
3820 assembly
->tstream
.index
= heapt_size
;
3821 for (i
= 0; i
< 5; ++i
) {
3822 int32val
= (guint32
*)p
;
3823 stream_desc
[i
].stream
->offset
= table_offset
;
3824 *int32val
++ = GUINT32_TO_LE (table_offset
);
3825 *int32val
= GUINT32_TO_LE (stream_desc
[i
].stream
->index
);
3826 table_offset
+= GUINT32_FROM_LE (*int32val
);
3827 table_offset
+= 3; table_offset
&= ~3;
3829 strcpy ((char*)p
, stream_desc
[i
].name
);
3830 p
+= strlen (stream_desc
[i
].name
) + 1;
3831 align_pointer (meta
->raw_metadata
, p
);
3834 * now copy the data, the table stream header and contents goes first.
3836 g_assert ((p
- (unsigned char*)meta
->raw_metadata
) < assembly
->tstream
.offset
);
3837 p
= (guchar
*)meta
->raw_metadata
+ assembly
->tstream
.offset
;
3838 int32val
= (guint32
*)p
;
3839 *int32val
= GUINT32_TO_LE (0); /* reserved */
3842 if (mono_framework_version () > 1) {
3843 *p
++ = 2; /* version */
3846 *p
++ = 1; /* version */
3850 if (meta
->idx_string_wide
)
3852 if (meta
->idx_guid_wide
)
3854 if (meta
->idx_blob_wide
)
3857 *p
++ = 1; /* reserved */
3858 int64val
= (guint64
*)p
;
3859 *int64val
++ = GUINT64_TO_LE (valid_mask
);
3860 *int64val
++ = GUINT64_TO_LE (valid_mask
& sorted_mask
); /* bitvector of sorted tables */
3862 int32val
= (guint32
*)p
;
3863 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3864 if (meta
->tables
[i
].rows
== 0)
3866 *int32val
++ = GUINT32_TO_LE (meta
->tables
[i
].rows
);
3868 p
= (unsigned char*)int32val
;
3870 /* sort the tables that still need sorting */
3871 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
3873 qsort (table
->values
+ MONO_CONSTANT_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CONSTANT_SIZE
, compare_constants
);
3874 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
3876 qsort (table
->values
+ MONO_METHOD_SEMA_SIZE
, table
->rows
, sizeof (guint32
) * MONO_METHOD_SEMA_SIZE
, compare_semantics
);
3877 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
3879 qsort (table
->values
+ MONO_CUSTOM_ATTR_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CUSTOM_ATTR_SIZE
, compare_custom_attrs
);
3880 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
3882 qsort (table
->values
+ MONO_FIELD_MARSHAL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_FIELD_MARSHAL_SIZE
, compare_field_marshal
);
3883 table
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3885 qsort (table
->values
+ MONO_NESTED_CLASS_SIZE
, table
->rows
, sizeof (guint32
) * MONO_NESTED_CLASS_SIZE
, compare_nested
);
3886 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3887 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
3889 qsort (table
->values
+ MONO_DECL_SECURITY_SIZE
, table
->rows
, sizeof (guint32
) * MONO_DECL_SECURITY_SIZE
, compare_declsecurity_attrs
);
3890 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3892 qsort (table
->values
+ MONO_INTERFACEIMPL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_INTERFACEIMPL_SIZE
, compare_interface_impl
);
3894 /* compress the tables */
3895 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3898 guint32 bitfield
= meta
->tables
[i
].size_bitfield
;
3899 if (!meta
->tables
[i
].rows
)
3901 if (assembly
->tables
[i
].columns
!= mono_metadata_table_count (bitfield
))
3902 g_error ("col count mismatch in %d: %d %d", i
, assembly
->tables
[i
].columns
, mono_metadata_table_count (bitfield
));
3903 meta
->tables
[i
].base
= (char*)p
;
3904 for (row
= 1; row
<= meta
->tables
[i
].rows
; ++row
) {
3905 values
= assembly
->tables
[i
].values
+ row
* assembly
->tables
[i
].columns
;
3906 for (col
= 0; col
< assembly
->tables
[i
].columns
; ++col
) {
3907 switch (mono_metadata_table_size (bitfield
, col
)) {
3909 *p
++ = values
[col
];
3912 *p
++ = values
[col
] & 0xff;
3913 *p
++ = (values
[col
] >> 8) & 0xff;
3916 *p
++ = values
[col
] & 0xff;
3917 *p
++ = (values
[col
] >> 8) & 0xff;
3918 *p
++ = (values
[col
] >> 16) & 0xff;
3919 *p
++ = (values
[col
] >> 24) & 0xff;
3922 g_assert_not_reached ();
3926 g_assert ((p
- (const unsigned char*)meta
->tables
[i
].base
) == (meta
->tables
[i
].rows
* meta
->tables
[i
].row_size
));
3929 g_assert (assembly
->guid
.offset
+ assembly
->guid
.index
< meta_size
);
3930 memcpy (meta
->raw_metadata
+ assembly
->sheap
.offset
, assembly
->sheap
.data
, assembly
->sheap
.index
);
3931 memcpy (meta
->raw_metadata
+ assembly
->us
.offset
, assembly
->us
.data
, assembly
->us
.index
);
3932 memcpy (meta
->raw_metadata
+ assembly
->blob
.offset
, assembly
->blob
.data
, assembly
->blob
.index
);
3933 memcpy (meta
->raw_metadata
+ assembly
->guid
.offset
, assembly
->guid
.data
, assembly
->guid
.index
);
3935 assembly
->meta_size
= assembly
->guid
.offset
+ assembly
->guid
.index
;
3939 * Some tables in metadata need to be sorted according to some criteria, but
3940 * when methods and fields are first created with reflection, they may be assigned a token
3941 * that doesn't correspond to the final token they will get assigned after the sorting.
3942 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3943 * with the reflection objects that represent them. Once all the tables are set up, the
3944 * reflection objects will contains the correct table index. fixup_method() will fixup the
3945 * tokens for the method with ILGenerator @ilgen.
3948 fixup_method (MonoReflectionILGen
*ilgen
, gpointer value
, MonoDynamicImage
*assembly
)
3950 guint32 code_idx
= GPOINTER_TO_UINT (value
);
3951 MonoReflectionILTokenInfo
*iltoken
;
3952 MonoReflectionFieldBuilder
*field
;
3953 MonoReflectionCtorBuilder
*ctor
;
3954 MonoReflectionMethodBuilder
*method
;
3955 MonoReflectionTypeBuilder
*tb
;
3956 MonoReflectionArrayMethod
*am
;
3958 unsigned char *target
;
3960 for (i
= 0; i
< ilgen
->num_token_fixups
; ++i
) {
3961 iltoken
= (MonoReflectionILTokenInfo
*)mono_array_addr_with_size (ilgen
->token_fixups
, sizeof (MonoReflectionILTokenInfo
), i
);
3962 target
= (guchar
*)assembly
->code
.data
+ code_idx
+ iltoken
->code_pos
;
3963 switch (target
[3]) {
3964 case MONO_TABLE_FIELD
:
3965 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
3966 field
= (MonoReflectionFieldBuilder
*)iltoken
->member
;
3967 idx
= field
->table_idx
;
3968 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
3969 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
3970 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->field_to_table_idx
, f
));
3972 g_assert_not_reached ();
3975 case MONO_TABLE_METHOD
:
3976 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
3977 method
= (MonoReflectionMethodBuilder
*)iltoken
->member
;
3978 idx
= method
->table_idx
;
3979 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
3980 ctor
= (MonoReflectionCtorBuilder
*)iltoken
->member
;
3981 idx
= ctor
->table_idx
;
3982 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
3983 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod")) {
3984 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
3985 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
3987 g_assert_not_reached ();
3990 case MONO_TABLE_TYPEDEF
:
3991 if (strcmp (iltoken
->member
->vtable
->klass
->name
, "TypeBuilder"))
3992 g_assert_not_reached ();
3993 tb
= (MonoReflectionTypeBuilder
*)iltoken
->member
;
3994 idx
= tb
->table_idx
;
3996 case MONO_TABLE_MEMBERREF
:
3997 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoArrayMethod")) {
3998 am
= (MonoReflectionArrayMethod
*)iltoken
->member
;
3999 idx
= am
->table_idx
;
4000 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
4001 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod") ||
4002 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod") ||
4003 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericCMethod")) {
4004 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4005 g_assert (m
->klass
->generic_class
|| m
->klass
->generic_container
);
4007 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
4009 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
4010 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
4011 g_assert (is_field_on_inst (f
));
4013 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder") ||
4014 !strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
4016 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldOnTypeBuilderInst")) {
4018 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodOnTypeBuilderInst")) {
4020 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst")) {
4023 g_assert_not_reached ();
4026 case MONO_TABLE_METHODSPEC
:
4027 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod")) {
4028 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4029 g_assert (mono_method_signature (m
)->generic_param_count
);
4031 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
4034 g_assert_not_reached ();
4038 g_error ("got unexpected table 0x%02x in fixup", target
[3]);
4040 target
[0] = idx
& 0xff;
4041 target
[1] = (idx
>> 8) & 0xff;
4042 target
[2] = (idx
>> 16) & 0xff;
4049 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4050 * value is not known when the table is emitted.
4053 fixup_cattrs (MonoDynamicImage
*assembly
)
4055 MonoDynamicTable
*table
;
4057 guint32 type
, i
, idx
, token
;
4060 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4062 for (i
= 0; i
< table
->rows
; ++i
) {
4063 values
= table
->values
+ ((i
+ 1) * MONO_CUSTOM_ATTR_SIZE
);
4065 type
= values
[MONO_CUSTOM_ATTR_TYPE
];
4066 if ((type
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_METHODDEF
) {
4067 idx
= type
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
4068 token
= mono_metadata_make_token (MONO_TABLE_METHOD
, idx
);
4069 ctor
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4072 if (!strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
4073 MonoMethod
*m
= ((MonoReflectionMethod
*)ctor
)->method
;
4074 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4075 values
[MONO_CUSTOM_ATTR_TYPE
] = (idx
<< MONO_CUSTOM_ATTR_TYPE_BITS
) | MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
4082 assembly_add_resource_manifest (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
, guint32 implementation
)
4084 MonoDynamicTable
*table
;
4087 table
= &assembly
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4089 alloc_table (table
, table
->rows
);
4090 values
= table
->values
+ table
->next_idx
* MONO_MANIFEST_SIZE
;
4091 values
[MONO_MANIFEST_OFFSET
] = rsrc
->offset
;
4092 values
[MONO_MANIFEST_FLAGS
] = rsrc
->attrs
;
4093 values
[MONO_MANIFEST_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, rsrc
->name
);
4094 values
[MONO_MANIFEST_IMPLEMENTATION
] = implementation
;
4099 assembly_add_resource (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
)
4101 MonoDynamicTable
*table
;
4105 char *b
= blob_size
;
4107 guint32 idx
, offset
;
4109 if (rsrc
->filename
) {
4110 name
= mono_string_to_utf8 (rsrc
->filename
);
4111 sname
= g_path_get_basename (name
);
4113 table
= &assembly
->tables
[MONO_TABLE_FILE
];
4115 alloc_table (table
, table
->rows
);
4116 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
4117 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_NO_METADATA
;
4118 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, sname
);
4121 mono_sha1_get_digest_from_file (name
, hash
);
4122 mono_metadata_encode_value (20, b
, &b
);
4123 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
4124 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
4126 idx
= table
->next_idx
++;
4128 idx
= MONO_IMPLEMENTATION_FILE
| (idx
<< MONO_IMPLEMENTATION_BITS
);
4134 data
= mono_array_addr (rsrc
->data
, char, 0);
4135 len
= mono_array_length (rsrc
->data
);
4141 sizebuf
[0] = offset
; sizebuf
[1] = offset
>> 8;
4142 sizebuf
[2] = offset
>> 16; sizebuf
[3] = offset
>> 24;
4143 rsrc
->offset
= mono_image_add_stream_data (&assembly
->resources
, sizebuf
, 4);
4144 mono_image_add_stream_data (&assembly
->resources
, data
, len
);
4148 * The entry should be emitted into the MANIFESTRESOURCE table of
4149 * the main module, but that needs to reference the FILE table
4150 * which isn't emitted yet.
4157 assembly_add_resource_manifest (mb
, assembly
, rsrc
, idx
);
4161 set_version_from_string (MonoString
*version
, guint32
*values
)
4163 gchar
*ver
, *p
, *str
;
4166 values
[MONO_ASSEMBLY_MAJOR_VERSION
] = 0;
4167 values
[MONO_ASSEMBLY_MINOR_VERSION
] = 0;
4168 values
[MONO_ASSEMBLY_REV_NUMBER
] = 0;
4169 values
[MONO_ASSEMBLY_BUILD_NUMBER
] = 0;
4172 ver
= str
= mono_string_to_utf8 (version
);
4173 for (i
= 0; i
< 4; ++i
) {
4174 values
[MONO_ASSEMBLY_MAJOR_VERSION
+ i
] = strtol (ver
, &p
, 10);
4180 /* handle Revision and Build */
4190 load_public_key (MonoArray
*pkey
, MonoDynamicImage
*assembly
) {
4194 char *b
= blob_size
;
4199 len
= mono_array_length (pkey
);
4200 mono_metadata_encode_value (len
, b
, &b
);
4201 token
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
- blob_size
);
4202 mono_image_add_stream_data (&assembly
->blob
, mono_array_addr (pkey
, char, 0), len
);
4204 assembly
->public_key
= g_malloc (len
);
4205 memcpy (assembly
->public_key
, mono_array_addr (pkey
, char, 0), len
);
4206 assembly
->public_key_len
= len
;
4208 /* Special case: check for ECMA key (16 bytes) */
4209 if ((len
== MONO_ECMA_KEY_LENGTH
) && mono_is_ecma_key (mono_array_addr (pkey
, char, 0), len
)) {
4210 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4211 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
;
4212 } else if (len
>= MONO_PUBLIC_KEY_HEADER_LENGTH
+ MONO_MINIMUM_PUBLIC_KEY_LENGTH
) {
4213 /* minimum key size (in 2.0) is 384 bits */
4214 assembly
->strong_name_size
= len
- MONO_PUBLIC_KEY_HEADER_LENGTH
;
4216 /* FIXME - verifier */
4217 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len
), (int)len
);
4218 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
; /* to be safe */
4220 assembly
->strong_name
= g_malloc0 (assembly
->strong_name_size
);
4226 mono_image_emit_manifest (MonoReflectionModuleBuilder
*moduleb
)
4228 MonoDynamicTable
*table
;
4229 MonoDynamicImage
*assembly
;
4230 MonoReflectionAssemblyBuilder
*assemblyb
;
4234 guint32 module_index
;
4236 assemblyb
= moduleb
->assemblyb
;
4237 assembly
= moduleb
->dynamic_image
;
4238 domain
= mono_object_domain (assemblyb
);
4240 /* Emit ASSEMBLY table */
4241 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLY
];
4242 alloc_table (table
, 1);
4243 values
= table
->values
+ MONO_ASSEMBLY_SIZE
;
4244 values
[MONO_ASSEMBLY_HASH_ALG
] = assemblyb
->algid
? assemblyb
->algid
: ASSEMBLY_HASH_SHA1
;
4245 values
[MONO_ASSEMBLY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->name
);
4246 if (assemblyb
->culture
) {
4247 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->culture
);
4249 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert (&assembly
->sheap
, "");
4251 values
[MONO_ASSEMBLY_PUBLIC_KEY
] = load_public_key (assemblyb
->public_key
, assembly
);
4252 values
[MONO_ASSEMBLY_FLAGS
] = assemblyb
->flags
;
4253 set_version_from_string (assemblyb
->version
, values
);
4255 /* Emit FILE + EXPORTED_TYPE table */
4257 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4259 MonoReflectionModuleBuilder
*file_module
=
4260 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4261 if (file_module
!= moduleb
) {
4262 mono_image_fill_file_table (domain
, (MonoReflectionModule
*)file_module
, assembly
);
4264 if (file_module
->types
) {
4265 for (j
= 0; j
< file_module
->num_types
; ++j
) {
4266 MonoReflectionTypeBuilder
*tb
= mono_array_get (file_module
->types
, MonoReflectionTypeBuilder
*, j
);
4267 mono_image_fill_export_table (domain
, tb
, module_index
, 0, assembly
);
4272 if (assemblyb
->loaded_modules
) {
4273 for (i
= 0; i
< mono_array_length (assemblyb
->loaded_modules
); ++i
) {
4274 MonoReflectionModule
*file_module
=
4275 mono_array_get (assemblyb
->loaded_modules
, MonoReflectionModule
*, i
);
4276 mono_image_fill_file_table (domain
, file_module
, assembly
);
4278 mono_image_fill_export_table_from_module (domain
, file_module
, module_index
, assembly
);
4281 if (assemblyb
->type_forwarders
)
4282 mono_image_fill_export_table_from_type_forwarders (assemblyb
, assembly
);
4284 /* Emit MANIFESTRESOURCE table */
4286 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4288 MonoReflectionModuleBuilder
*file_module
=
4289 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4290 /* The table for the main module is emitted later */
4291 if (file_module
!= moduleb
) {
4293 if (file_module
->resources
) {
4294 int len
= mono_array_length (file_module
->resources
);
4295 for (j
= 0; j
< len
; ++j
) {
4296 MonoReflectionResource
* res
= (MonoReflectionResource
*)mono_array_addr (file_module
->resources
, MonoReflectionResource
, j
);
4297 assembly_add_resource_manifest (file_module
, assembly
, res
, MONO_IMPLEMENTATION_FILE
| (module_index
<< MONO_IMPLEMENTATION_BITS
));
4304 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4307 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4308 * for the modulebuilder @moduleb.
4309 * At the end of the process, method and field tokens are fixed up and the
4310 * on-disk compressed metadata representation is created.
4313 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4315 MonoDynamicTable
*table
;
4316 MonoDynamicImage
*assembly
;
4317 MonoReflectionAssemblyBuilder
*assemblyb
;
4323 assemblyb
= moduleb
->assemblyb
;
4324 assembly
= moduleb
->dynamic_image
;
4325 domain
= mono_object_domain (assemblyb
);
4327 if (assembly
->text_rva
)
4330 assembly
->text_rva
= START_TEXT_RVA
;
4332 if (moduleb
->is_main
) {
4333 mono_image_emit_manifest (moduleb
);
4336 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4337 table
->rows
= 1; /* .<Module> */
4339 alloc_table (table
, table
->rows
);
4341 * Set the first entry.
4343 values
= table
->values
+ table
->columns
;
4344 values
[MONO_TYPEDEF_FLAGS
] = 0;
4345 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, "<Module>") ;
4346 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, "") ;
4347 values
[MONO_TYPEDEF_EXTENDS
] = 0;
4348 values
[MONO_TYPEDEF_FIELD_LIST
] = 1;
4349 values
[MONO_TYPEDEF_METHOD_LIST
] = 1;
4352 * handle global methods
4353 * FIXME: test what to do when global methods are defined in multiple modules.
4355 if (moduleb
->global_methods
) {
4356 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
4357 table
->rows
+= mono_array_length (moduleb
->global_methods
);
4358 alloc_table (table
, table
->rows
);
4359 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
)
4360 mono_image_get_method_info (
4361 mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
4363 if (moduleb
->global_fields
) {
4364 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
4365 table
->rows
+= mono_array_length (moduleb
->global_fields
);
4366 alloc_table (table
, table
->rows
);
4367 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
)
4368 mono_image_get_field_info (
4369 mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
4372 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
4373 alloc_table (table
, 1);
4374 mono_image_fill_module_table (domain
, moduleb
, assembly
);
4376 /* Collect all types into a list sorted by their table_idx */
4377 types
= g_ptr_array_new ();
4380 for (i
= 0; i
< moduleb
->num_types
; ++i
) {
4381 MonoReflectionTypeBuilder
*type
= mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
);
4382 collect_types (types
, type
);
4385 g_ptr_array_sort (types
, (GCompareFunc
)compare_types_by_table_idx
);
4386 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4387 table
->rows
+= types
->len
;
4388 alloc_table (table
, table
->rows
);
4391 * Emit type names + namespaces at one place inside the string heap,
4392 * so load_class_names () needs to touch fewer pages.
4394 for (i
= 0; i
< types
->len
; ++i
) {
4395 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4396 string_heap_insert_mstring (&assembly
->sheap
, tb
->nspace
);
4398 for (i
= 0; i
< types
->len
; ++i
) {
4399 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4400 string_heap_insert_mstring (&assembly
->sheap
, tb
->name
);
4403 for (i
= 0; i
< types
->len
; ++i
) {
4404 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4405 mono_image_get_type_info (domain
, type
, assembly
);
4409 * table->rows is already set above and in mono_image_fill_module_table.
4411 /* add all the custom attributes at the end, once all the indexes are stable */
4412 mono_image_add_cattrs (assembly
, 1, MONO_CUSTOM_ATTR_ASSEMBLY
, assemblyb
->cattrs
);
4414 /* CAS assembly permissions */
4415 if (assemblyb
->permissions_minimum
)
4416 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_minimum
);
4417 if (assemblyb
->permissions_optional
)
4418 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_optional
);
4419 if (assemblyb
->permissions_refused
)
4420 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_refused
);
4422 module_add_cattrs (assembly
, moduleb
);
4425 mono_g_hash_table_foreach (assembly
->token_fixups
, (GHFunc
)fixup_method
, assembly
);
4427 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4428 * the final tokens and don't need another fixup pass. */
4430 if (moduleb
->global_methods
) {
4431 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
4432 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4433 moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
4434 mono_image_add_methodimpl (assembly
, mb
);
4438 for (i
= 0; i
< types
->len
; ++i
) {
4439 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4440 if (type
->methods
) {
4441 for (j
= 0; j
< type
->num_methods
; ++j
) {
4442 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4443 type
->methods
, MonoReflectionMethodBuilder
*, j
);
4445 mono_image_add_methodimpl (assembly
, mb
);
4450 g_ptr_array_free (types
, TRUE
);
4452 fixup_cattrs (assembly
);
4455 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4458 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4460 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4463 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4467 guint32 import_lookup_table
;
4471 guint32 import_address_table_rva
;
4479 #ifndef DISABLE_REFLECTION_EMIT
4482 * mono_image_insert_string:
4483 * @module: module builder object
4486 * Insert @str into the user string stream of @module.
4489 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
4491 MonoDynamicImage
*assembly
;
4496 MONO_ARCH_SAVE_REGS
;
4498 if (!module
->dynamic_image
)
4499 mono_image_module_basic_init (module
);
4501 assembly
= module
->dynamic_image
;
4503 if (assembly
->save
) {
4504 mono_metadata_encode_value (1 | (str
->length
* 2), b
, &b
);
4505 idx
= mono_image_add_stream_data (&assembly
->us
, buf
, b
-buf
);
4506 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4508 char *swapped
= g_malloc (2 * mono_string_length (str
));
4509 const char *p
= (const char*)mono_string_chars (str
);
4511 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
4512 mono_image_add_stream_data (&assembly
->us
, swapped
, str
->length
* 2);
4516 mono_image_add_stream_data (&assembly
->us
, (const char*)mono_string_chars (str
), str
->length
* 2);
4518 mono_image_add_stream_data (&assembly
->us
, "", 1);
4520 idx
= assembly
->us
.index
++;
4523 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (MONO_TOKEN_STRING
| idx
), str
);
4525 return MONO_TOKEN_STRING
| idx
;
4529 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
4534 klass
= obj
->vtable
->klass
;
4535 if (strcmp (klass
->name
, "MonoMethod") == 0) {
4536 MonoMethod
*method
= ((MonoReflectionMethod
*)obj
)->method
;
4537 MonoMethodSignature
*sig
, *old
;
4538 guint32 sig_token
, parent
;
4541 g_assert (opt_param_types
&& (mono_method_signature (method
)->sentinelpos
>= 0));
4543 nargs
= mono_array_length (opt_param_types
);
4544 old
= mono_method_signature (method
);
4545 sig
= mono_metadata_signature_alloc ( &assembly
->image
, old
->param_count
+ nargs
);
4547 sig
->hasthis
= old
->hasthis
;
4548 sig
->explicit_this
= old
->explicit_this
;
4549 sig
->call_convention
= old
->call_convention
;
4550 sig
->generic_param_count
= old
->generic_param_count
;
4551 sig
->param_count
= old
->param_count
+ nargs
;
4552 sig
->sentinelpos
= old
->param_count
;
4553 sig
->ret
= old
->ret
;
4555 for (i
= 0; i
< old
->param_count
; i
++)
4556 sig
->params
[i
] = old
->params
[i
];
4558 for (i
= 0; i
< nargs
; i
++) {
4559 MonoReflectionType
*rt
= mono_array_get (opt_param_types
, MonoReflectionType
*, i
);
4560 sig
->params
[old
->param_count
+ i
] = rt
->type
;
4563 parent
= mono_image_typedef_or_ref (assembly
, &method
->klass
->byval_arg
);
4564 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_MEMBERREF_PARENT_TYPEREF
);
4565 parent
>>= MONO_TYPEDEFORREF_BITS
;
4567 parent
<<= MONO_MEMBERREF_PARENT_BITS
;
4568 parent
|= MONO_MEMBERREF_PARENT_TYPEREF
;
4570 sig_token
= method_encode_signature (assembly
, sig
);
4571 token
= mono_image_get_varargs_method_token (assembly
, parent
, method
->name
, sig_token
);
4572 } else if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4573 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4574 ReflectionMethodBuilder rmb
;
4575 guint32 parent
, sig
;
4578 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
4579 rmb
.opt_types
= opt_param_types
;
4581 sig
= method_builder_encode_signature (assembly
, &rmb
);
4583 parent
= mono_image_create_token (assembly
, obj
, TRUE
, TRUE
);
4584 g_assert (mono_metadata_token_table (parent
) == MONO_TABLE_METHOD
);
4586 parent
= mono_metadata_token_index (parent
) << MONO_MEMBERREF_PARENT_BITS
;
4587 parent
|= MONO_MEMBERREF_PARENT_METHODDEF
;
4589 name
= mono_string_to_utf8 (rmb
.name
);
4590 token
= mono_image_get_varargs_method_token (
4591 assembly
, parent
, name
, sig
);
4594 g_error ("requested method token for %s\n", klass
->name
);
4601 * mono_image_create_token:
4602 * @assembly: a dynamic assembly
4604 * @register_token: Whenever to register the token in the assembly->tokens hash.
4606 * Get a token to insert in the IL code stream for the given MemberInfo.
4607 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4608 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4612 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
4613 gboolean create_methodspec
, gboolean register_token
)
4618 klass
= obj
->vtable
->klass
;
4620 /* Check for user defined reflection objects */
4621 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4622 if (klass
->image
!= mono_defaults
.corlib
|| (strcmp (klass
->name
, "TypeDelegator") == 0))
4623 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4625 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4626 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4627 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4629 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
&& !mb
->generic_params
)
4630 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4632 token
= mono_image_get_methodbuilder_token (assembly
, mb
, create_methodspec
);
4633 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4634 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
4635 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
4636 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4638 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
)
4639 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4641 token
= mono_image_get_ctorbuilder_token (assembly
, mb
);
4642 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4643 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
4644 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
4645 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
4646 if (tb
->generic_params
) {
4647 token
= mono_image_get_generic_field_token (assembly
, fb
);
4649 token
= fb
->table_idx
| MONO_TOKEN_FIELD_DEF
;
4651 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
4652 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
4653 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
4654 } else if (strcmp (klass
->name
, "MonoType") == 0) {
4655 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4656 MonoClass
*mc
= mono_class_from_mono_type (tb
->type
);
4657 token
= mono_metadata_token_from_dor (
4658 mono_image_typedef_or_ref_full (assembly
, tb
->type
, mc
->generic_container
== NULL
));
4659 } else if (strcmp (klass
->name
, "GenericTypeParameterBuilder") == 0) {
4660 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4661 token
= mono_metadata_token_from_dor (
4662 mono_image_typedef_or_ref (assembly
, tb
->type
));
4663 } else if (strcmp (klass
->name
, "MonoGenericClass") == 0) {
4664 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4665 token
= mono_metadata_token_from_dor (
4666 mono_image_typedef_or_ref (assembly
, tb
->type
));
4667 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
4668 strcmp (klass
->name
, "MonoMethod") == 0 ||
4669 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
4670 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
4671 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
4672 if (m
->method
->is_inflated
) {
4673 if (create_methodspec
)
4674 token
= mono_image_get_methodspec_token (assembly
, m
->method
);
4676 token
= mono_image_get_inflated_method_token (assembly
, m
->method
);
4677 } else if ((m
->method
->klass
->image
== &assembly
->image
) &&
4678 !m
->method
->klass
->generic_class
) {
4679 static guint32 method_table_idx
= 0xffffff;
4680 if (m
->method
->klass
->wastypebuilder
) {
4681 /* we use the same token as the one that was assigned
4682 * to the Methodbuilder.
4683 * FIXME: do the equivalent for Fields.
4685 token
= m
->method
->token
;
4688 * Each token should have a unique index, but the indexes are
4689 * assigned by managed code, so we don't know about them. An
4690 * easy solution is to count backwards...
4692 method_table_idx
--;
4693 token
= MONO_TOKEN_METHOD_DEF
| method_table_idx
;
4696 token
= mono_image_get_methodref_token (assembly
, m
->method
, create_methodspec
);
4698 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4699 } else if (strcmp (klass
->name
, "MonoField") == 0) {
4700 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
4701 if ((f
->field
->parent
->image
== &assembly
->image
) && !is_field_on_inst (f
->field
)) {
4702 static guint32 field_table_idx
= 0xffffff;
4704 token
= MONO_TOKEN_FIELD_DEF
| field_table_idx
;
4706 token
= mono_image_get_fieldref_token (assembly
, f
);
4708 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4709 } else if (strcmp (klass
->name
, "MonoArrayMethod") == 0) {
4710 MonoReflectionArrayMethod
*m
= (MonoReflectionArrayMethod
*)obj
;
4711 token
= mono_image_get_array_token (assembly
, m
);
4712 } else if (strcmp (klass
->name
, "SignatureHelper") == 0) {
4713 MonoReflectionSigHelper
*s
= (MonoReflectionSigHelper
*)obj
;
4714 token
= MONO_TOKEN_SIGNATURE
| mono_image_get_sighelper_token (assembly
, s
);
4715 } else if (strcmp (klass
->name
, "EnumBuilder") == 0) {
4716 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4717 token
= mono_metadata_token_from_dor (
4718 mono_image_typedef_or_ref (assembly
, tb
->type
));
4719 } else if (strcmp (klass
->name
, "FieldOnTypeBuilderInst") == 0) {
4720 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
4721 token
= mono_image_get_field_on_inst_token (assembly
, f
);
4722 } else if (strcmp (klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
4723 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
4724 token
= mono_image_get_ctor_on_inst_token (assembly
, c
, create_methodspec
);
4725 } else if (strcmp (klass
->name
, "MethodOnTypeBuilderInst") == 0) {
4726 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
4727 token
= mono_image_get_method_on_inst_token (assembly
, m
, create_methodspec
);
4729 g_error ("requested token for %s\n", klass
->name
);
4733 mono_image_register_token (assembly
, token
, obj
);
4739 * mono_image_register_token:
4741 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4742 * the Module.ResolveXXXToken () methods to work.
4745 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
4747 MonoObject
*prev
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4749 /* There could be multiple MethodInfo objects with the same token */
4750 //g_assert (prev == obj);
4752 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), obj
);
4756 static MonoDynamicImage
*
4757 create_dynamic_mono_image (MonoDynamicAssembly
*assembly
, char *assembly_name
, char *module_name
)
4759 static const guchar entrycode
[16] = {0xff, 0x25, 0};
4760 MonoDynamicImage
*image
;
4763 const char *version
;
4765 if (!strcmp (mono_get_runtime_info ()->framework_version
, "2.1"))
4766 version
= "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4768 version
= mono_get_runtime_info ()->runtime_version
;
4771 image
= GC_MALLOC (sizeof (MonoDynamicImage
));
4773 image
= g_new0 (MonoDynamicImage
, 1);
4776 mono_profiler_module_event (&image
->image
, MONO_PROFILE_START_LOAD
);
4778 /*g_print ("created image %p\n", image);*/
4779 /* keep in sync with image.c */
4780 image
->image
.name
= assembly_name
;
4781 image
->image
.assembly_name
= image
->image
.name
; /* they may be different */
4782 image
->image
.module_name
= module_name
;
4783 image
->image
.version
= g_strdup (version
);
4784 image
->image
.md_version_major
= 1;
4785 image
->image
.md_version_minor
= 1;
4786 image
->image
.dynamic
= TRUE
;
4788 image
->image
.references
= g_new0 (MonoAssembly
*, 1);
4789 image
->image
.references
[0] = NULL
;
4791 mono_image_init (&image
->image
);
4793 image
->token_fixups
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
);
4794 image
->method_to_table_idx
= g_hash_table_new (NULL
, NULL
);
4795 image
->field_to_table_idx
= g_hash_table_new (NULL
, NULL
);
4796 image
->method_aux_hash
= g_hash_table_new (NULL
, NULL
);
4797 image
->handleref
= g_hash_table_new (NULL
, NULL
);
4798 image
->tokens
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
4799 image
->generic_def_objects
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
4800 image
->methodspec
= mono_g_hash_table_new_type ((GHashFunc
)mono_object_hash
, NULL
, MONO_HASH_KEY_GC
);
4801 image
->typespec
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
4802 image
->typeref
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
4803 image
->blob_cache
= g_hash_table_new ((GHashFunc
)mono_blob_entry_hash
, (GCompareFunc
)mono_blob_entry_equal
);
4804 image
->gen_params
= g_ptr_array_new ();
4806 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4807 string_heap_init (&image
->sheap
);
4808 mono_image_add_stream_data (&image
->us
, "", 1);
4809 add_to_blob_cached (image
, (char*) "", 1, NULL
, 0);
4810 /* import tables... */
4811 mono_image_add_stream_data (&image
->code
, (char*)entrycode
, sizeof (entrycode
));
4812 image
->iat_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two IAT entries */
4813 image
->idt_offset
= mono_image_add_stream_zero (&image
->code
, 2 * sizeof (MonoIDT
)); /* two IDT entries */
4814 image
->imp_names_offset
= mono_image_add_stream_zero (&image
->code
, 2); /* flags for name entry */
4815 mono_image_add_stream_data (&image
->code
, "_CorExeMain", 12);
4816 mono_image_add_stream_data (&image
->code
, "mscoree.dll", 12);
4817 image
->ilt_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two ILT entries */
4818 stream_data_align (&image
->code
);
4820 image
->cli_header_offset
= mono_image_add_stream_zero (&image
->code
, sizeof (MonoCLIHeader
));
4822 for (i
=0; i
< MONO_TABLE_NUM
; ++i
) {
4823 image
->tables
[i
].next_idx
= 1;
4824 image
->tables
[i
].columns
= table_sizes
[i
];
4827 image
->image
.assembly
= (MonoAssembly
*)assembly
;
4828 image
->run
= assembly
->run
;
4829 image
->save
= assembly
->save
;
4830 image
->pe_kind
= 0x1; /* ILOnly */
4831 image
->machine
= 0x14c; /* I386 */
4833 mono_profiler_module_loaded (&image
->image
, MONO_PROFILE_OK
);
4840 free_blob_cache_entry (gpointer key
, gpointer val
, gpointer user_data
)
4846 mono_dynamic_image_free (MonoDynamicImage
*image
)
4848 MonoDynamicImage
*di
= image
;
4853 mono_g_hash_table_destroy (di
->methodspec
);
4855 g_hash_table_destroy (di
->typespec
);
4857 g_hash_table_destroy (di
->typeref
);
4859 g_hash_table_destroy (di
->handleref
);
4861 mono_g_hash_table_destroy (di
->tokens
);
4862 if (di
->generic_def_objects
)
4863 mono_g_hash_table_destroy (di
->generic_def_objects
);
4864 if (di
->blob_cache
) {
4865 g_hash_table_foreach (di
->blob_cache
, free_blob_cache_entry
, NULL
);
4866 g_hash_table_destroy (di
->blob_cache
);
4868 if (di
->standalonesig_cache
)
4869 g_hash_table_destroy (di
->standalonesig_cache
);
4870 for (list
= di
->array_methods
; list
; list
= list
->next
) {
4871 ArrayMethod
*am
= (ArrayMethod
*)list
->data
;
4876 g_list_free (di
->array_methods
);
4877 if (di
->gen_params
) {
4878 for (i
= 0; i
< di
->gen_params
->len
; i
++) {
4879 GenericParamTableEntry
*entry
= g_ptr_array_index (di
->gen_params
, i
);
4880 if (entry
->gparam
->type
.type
) {
4881 MonoGenericParam
*param
= entry
->gparam
->type
.type
->data
.generic_param
;
4882 g_free ((char*)mono_generic_param_info (param
)->name
);
4887 g_ptr_array_free (di
->gen_params
, TRUE
);
4889 if (di
->token_fixups
)
4890 mono_g_hash_table_destroy (di
->token_fixups
);
4891 if (di
->method_to_table_idx
)
4892 g_hash_table_destroy (di
->method_to_table_idx
);
4893 if (di
->field_to_table_idx
)
4894 g_hash_table_destroy (di
->field_to_table_idx
);
4895 if (di
->method_aux_hash
)
4896 g_hash_table_destroy (di
->method_aux_hash
);
4897 g_free (di
->strong_name
);
4898 g_free (di
->win32_res
);
4900 g_free (di
->public_key
);
4902 /*g_print ("string heap destroy for image %p\n", di);*/
4903 mono_dynamic_stream_reset (&di
->sheap
);
4904 mono_dynamic_stream_reset (&di
->code
);
4905 mono_dynamic_stream_reset (&di
->resources
);
4906 mono_dynamic_stream_reset (&di
->us
);
4907 mono_dynamic_stream_reset (&di
->blob
);
4908 mono_dynamic_stream_reset (&di
->tstream
);
4909 mono_dynamic_stream_reset (&di
->guid
);
4910 for (i
= 0; i
< MONO_TABLE_NUM
; ++i
) {
4911 g_free (di
->tables
[i
].values
);
4915 #ifndef DISABLE_REFLECTION_EMIT
4918 * mono_image_basic_init:
4919 * @assembly: an assembly builder object
4921 * Create the MonoImage that represents the assembly builder and setup some
4922 * of the helper hash table and the basic metadata streams.
4925 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
4927 MonoDynamicAssembly
*assembly
;
4928 MonoDynamicImage
*image
;
4929 MonoDomain
*domain
= mono_object_domain (assemblyb
);
4931 MONO_ARCH_SAVE_REGS
;
4933 if (assemblyb
->dynamic_assembly
)
4937 assembly
= assemblyb
->dynamic_assembly
= GC_MALLOC (sizeof (MonoDynamicAssembly
));
4939 assembly
= assemblyb
->dynamic_assembly
= g_new0 (MonoDynamicAssembly
, 1);
4942 mono_profiler_assembly_event (&assembly
->assembly
, MONO_PROFILE_START_LOAD
);
4944 assembly
->assembly
.ref_count
= 1;
4945 assembly
->assembly
.dynamic
= TRUE
;
4946 assembly
->assembly
.corlib_internal
= assemblyb
->corlib_internal
;
4947 assemblyb
->assembly
.assembly
= (MonoAssembly
*)assembly
;
4948 assembly
->assembly
.basedir
= mono_string_to_utf8 (assemblyb
->dir
);
4949 if (assemblyb
->culture
)
4950 assembly
->assembly
.aname
.culture
= mono_string_to_utf8 (assemblyb
->culture
);
4952 assembly
->assembly
.aname
.culture
= g_strdup ("");
4954 if (assemblyb
->version
) {
4955 char *vstr
= mono_string_to_utf8 (assemblyb
->version
);
4956 char **version
= g_strsplit (vstr
, ".", 4);
4957 char **parts
= version
;
4958 assembly
->assembly
.aname
.major
= atoi (*parts
++);
4959 assembly
->assembly
.aname
.minor
= atoi (*parts
++);
4960 assembly
->assembly
.aname
.build
= *parts
!= NULL
? atoi (*parts
++) : 0;
4961 assembly
->assembly
.aname
.revision
= *parts
!= NULL
? atoi (*parts
) : 0;
4963 g_strfreev (version
);
4966 assembly
->assembly
.aname
.major
= 0;
4967 assembly
->assembly
.aname
.minor
= 0;
4968 assembly
->assembly
.aname
.build
= 0;
4969 assembly
->assembly
.aname
.revision
= 0;
4972 assembly
->run
= assemblyb
->access
!= 2;
4973 assembly
->save
= assemblyb
->access
!= 1;
4975 image
= create_dynamic_mono_image (assembly
, mono_string_to_utf8 (assemblyb
->name
), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4976 image
->initial_image
= TRUE
;
4977 assembly
->assembly
.aname
.name
= image
->image
.name
;
4978 assembly
->assembly
.image
= &image
->image
;
4980 mono_domain_assemblies_lock (domain
);
4981 domain
->domain_assemblies
= g_slist_prepend (domain
->domain_assemblies
, assembly
);
4982 mono_domain_assemblies_unlock (domain
);
4984 register_assembly (mono_object_domain (assemblyb
), &assemblyb
->assembly
, &assembly
->assembly
);
4986 mono_profiler_assembly_loaded (&assembly
->assembly
, MONO_PROFILE_OK
);
4988 mono_assembly_invoke_load_hook ((MonoAssembly
*)assembly
);
4991 #endif /* !DISABLE_REFLECTION_EMIT */
4993 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4996 calc_section_size (MonoDynamicImage
*assembly
)
5000 /* alignment constraints */
5001 mono_image_add_stream_zero (&assembly
->code
, 4 - (assembly
->code
.index
% 4));
5002 g_assert ((assembly
->code
.index
% 4) == 0);
5003 assembly
->meta_size
+= 3;
5004 assembly
->meta_size
&= ~3;
5005 mono_image_add_stream_zero (&assembly
->resources
, 4 - (assembly
->resources
.index
% 4));
5006 g_assert ((assembly
->resources
.index
% 4) == 0);
5008 assembly
->sections
[MONO_SECTION_TEXT
].size
= assembly
->meta_size
+ assembly
->code
.index
+ assembly
->resources
.index
+ assembly
->strong_name_size
;
5009 assembly
->sections
[MONO_SECTION_TEXT
].attrs
= SECT_FLAGS_HAS_CODE
| SECT_FLAGS_MEM_EXECUTE
| SECT_FLAGS_MEM_READ
;
5012 if (assembly
->win32_res
) {
5013 guint32 res_size
= (assembly
->win32_res_size
+ 3) & ~3;
5015 assembly
->sections
[MONO_SECTION_RSRC
].size
= res_size
;
5016 assembly
->sections
[MONO_SECTION_RSRC
].attrs
= SECT_FLAGS_HAS_INITIALIZED_DATA
| SECT_FLAGS_MEM_READ
;
5020 assembly
->sections
[MONO_SECTION_RELOC
].size
= 12;
5021 assembly
->sections
[MONO_SECTION_RELOC
].attrs
= SECT_FLAGS_MEM_READ
| SECT_FLAGS_MEM_DISCARDABLE
| SECT_FLAGS_HAS_INITIALIZED_DATA
;
5031 MonoReflectionWin32Resource
*win32_res
; /* Only for leaf nodes */
5035 resource_tree_compare_by_id (gconstpointer a
, gconstpointer b
)
5037 ResTreeNode
*t1
= (ResTreeNode
*)a
;
5038 ResTreeNode
*t2
= (ResTreeNode
*)b
;
5040 return t1
->id
- t2
->id
;
5044 * resource_tree_create:
5046 * Organize the resources into a resource tree.
5048 static ResTreeNode
*
5049 resource_tree_create (MonoArray
*win32_resources
)
5051 ResTreeNode
*tree
, *res_node
, *type_node
, *lang_node
;
5055 tree
= g_new0 (ResTreeNode
, 1);
5057 for (i
= 0; i
< mono_array_length (win32_resources
); ++i
) {
5058 MonoReflectionWin32Resource
*win32_res
=
5059 (MonoReflectionWin32Resource
*)mono_array_addr (win32_resources
, MonoReflectionWin32Resource
, i
);
5063 /* FIXME: BUG: this stores managed references in unmanaged memory */
5064 lang_node
= g_new0 (ResTreeNode
, 1);
5065 lang_node
->id
= win32_res
->lang_id
;
5066 lang_node
->win32_res
= win32_res
;
5068 /* Create type node if neccesary */
5070 for (l
= tree
->children
; l
; l
= l
->next
)
5071 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_type
) {
5072 type_node
= (ResTreeNode
*)l
->data
;
5077 type_node
= g_new0 (ResTreeNode
, 1);
5078 type_node
->id
= win32_res
->res_type
;
5081 * The resource types have to be sorted otherwise
5082 * Windows Explorer can't display the version information.
5084 tree
->children
= g_slist_insert_sorted (tree
->children
,
5085 type_node
, resource_tree_compare_by_id
);
5088 /* Create res node if neccesary */
5090 for (l
= type_node
->children
; l
; l
= l
->next
)
5091 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_id
) {
5092 res_node
= (ResTreeNode
*)l
->data
;
5097 res_node
= g_new0 (ResTreeNode
, 1);
5098 res_node
->id
= win32_res
->res_id
;
5099 type_node
->children
= g_slist_append (type_node
->children
, res_node
);
5102 res_node
->children
= g_slist_append (res_node
->children
, lang_node
);
5109 * resource_tree_encode:
5111 * Encode the resource tree into the format used in the PE file.
5114 resource_tree_encode (ResTreeNode
*node
, char *begin
, char *p
, char **endbuf
)
5117 MonoPEResourceDir dir
;
5118 MonoPEResourceDirEntry dir_entry
;
5119 MonoPEResourceDataEntry data_entry
;
5121 guint32 res_id_entries
;
5124 * For the format of the resource directory, see the article
5125 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5129 memset (&dir
, 0, sizeof (dir
));
5130 memset (&dir_entry
, 0, sizeof (dir_entry
));
5131 memset (&data_entry
, 0, sizeof (data_entry
));
5133 g_assert (sizeof (dir
) == 16);
5134 g_assert (sizeof (dir_entry
) == 8);
5135 g_assert (sizeof (data_entry
) == 16);
5137 node
->offset
= p
- begin
;
5139 /* IMAGE_RESOURCE_DIRECTORY */
5140 res_id_entries
= g_slist_length (node
->children
);
5141 dir
.res_id_entries
= GUINT16_TO_LE (res_id_entries
);
5143 memcpy (p
, &dir
, sizeof (dir
));
5146 /* Reserve space for entries */
5148 p
+= sizeof (dir_entry
) * res_id_entries
;
5150 /* Write children */
5151 for (l
= node
->children
; l
; l
= l
->next
) {
5152 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5154 if (child
->win32_res
) {
5157 child
->offset
= p
- begin
;
5159 /* IMAGE_RESOURCE_DATA_ENTRY */
5160 data_entry
.rde_data_offset
= GUINT32_TO_LE (p
- begin
+ sizeof (data_entry
));
5161 size
= mono_array_length (child
->win32_res
->res_data
);
5162 data_entry
.rde_size
= GUINT32_TO_LE (size
);
5164 memcpy (p
, &data_entry
, sizeof (data_entry
));
5165 p
+= sizeof (data_entry
);
5167 memcpy (p
, mono_array_addr (child
->win32_res
->res_data
, char, 0), size
);
5170 resource_tree_encode (child
, begin
, p
, &p
);
5174 /* IMAGE_RESOURCE_ENTRY */
5175 for (l
= node
->children
; l
; l
= l
->next
) {
5176 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5178 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry
, FALSE
, child
->id
);
5179 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry
, !child
->win32_res
, child
->offset
);
5181 memcpy (entries
, &dir_entry
, sizeof (dir_entry
));
5182 entries
+= sizeof (dir_entry
);
5189 resource_tree_free (ResTreeNode
* node
)
5192 for (list
= node
->children
; list
; list
= list
->next
)
5193 resource_tree_free ((ResTreeNode
*)list
->data
);
5194 g_slist_free(node
->children
);
5199 assembly_add_win32_resources (MonoDynamicImage
*assembly
, MonoReflectionAssemblyBuilder
*assemblyb
)
5204 MonoReflectionWin32Resource
*win32_res
;
5207 if (!assemblyb
->win32_resources
)
5211 * Resources are stored in a three level tree inside the PE file.
5212 * - level one contains a node for each type of resource
5213 * - level two contains a node for each resource
5214 * - level three contains a node for each instance of a resource for a
5215 * specific language.
5218 tree
= resource_tree_create (assemblyb
->win32_resources
);
5220 /* Estimate the size of the encoded tree */
5222 for (i
= 0; i
< mono_array_length (assemblyb
->win32_resources
); ++i
) {
5223 win32_res
= (MonoReflectionWin32Resource
*)mono_array_addr (assemblyb
->win32_resources
, MonoReflectionWin32Resource
, i
);
5224 size
+= mono_array_length (win32_res
->res_data
);
5226 /* Directory structure */
5227 size
+= mono_array_length (assemblyb
->win32_resources
) * 256;
5228 p
= buf
= g_malloc (size
);
5230 resource_tree_encode (tree
, p
, p
, &p
);
5232 g_assert (p
- buf
<= size
);
5234 assembly
->win32_res
= g_malloc (p
- buf
);
5235 assembly
->win32_res_size
= p
- buf
;
5236 memcpy (assembly
->win32_res
, buf
, p
- buf
);
5239 resource_tree_free (tree
);
5243 fixup_resource_directory (char *res_section
, char *p
, guint32 rva
)
5245 MonoPEResourceDir
*dir
= (MonoPEResourceDir
*)p
;
5248 p
+= sizeof (MonoPEResourceDir
);
5249 for (i
= 0; i
< GUINT16_FROM_LE (dir
->res_named_entries
) + GUINT16_FROM_LE (dir
->res_id_entries
); ++i
) {
5250 MonoPEResourceDirEntry
*dir_entry
= (MonoPEResourceDirEntry
*)p
;
5251 char *child
= res_section
+ MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry
);
5252 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry
)) {
5253 fixup_resource_directory (res_section
, child
, rva
);
5255 MonoPEResourceDataEntry
*data_entry
= (MonoPEResourceDataEntry
*)child
;
5256 data_entry
->rde_data_offset
= GUINT32_TO_LE (GUINT32_FROM_LE (data_entry
->rde_data_offset
) + rva
);
5259 p
+= sizeof (MonoPEResourceDirEntry
);
5264 checked_write_file (HANDLE f
, gconstpointer buffer
, guint32 numbytes
)
5267 if (!WriteFile (f
, buffer
, numbytes
, &dummy
, NULL
))
5268 g_error ("WriteFile returned %d\n", GetLastError ());
5272 * mono_image_create_pefile:
5273 * @mb: a module builder object
5275 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5276 * assembly->pefile where it can be easily retrieved later in chunks.
5279 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5281 MonoMSDOSHeader
*msdos
;
5282 MonoDotNetHeader
*header
;
5283 MonoSectionTable
*section
;
5284 MonoCLIHeader
*cli_header
;
5285 guint32 size
, image_size
, virtual_base
, text_offset
;
5286 guint32 header_start
, section_start
, file_offset
, virtual_offset
;
5287 MonoDynamicImage
*assembly
;
5288 MonoReflectionAssemblyBuilder
*assemblyb
;
5289 MonoDynamicStream pefile_stream
= {0};
5290 MonoDynamicStream
*pefile
= &pefile_stream
;
5292 guint32
*rva
, value
;
5294 static const unsigned char msheader
[] = {
5295 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5296 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5299 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5300 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5301 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5302 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5305 assemblyb
= mb
->assemblyb
;
5307 mono_image_basic_init (assemblyb
);
5308 assembly
= mb
->dynamic_image
;
5310 assembly
->pe_kind
= assemblyb
->pe_kind
;
5311 assembly
->machine
= assemblyb
->machine
;
5312 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->pe_kind
= assemblyb
->pe_kind
;
5313 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->machine
= assemblyb
->machine
;
5315 mono_image_build_metadata (mb
);
5317 if (mb
->is_main
&& assemblyb
->resources
) {
5318 int len
= mono_array_length (assemblyb
->resources
);
5319 for (i
= 0; i
< len
; ++i
)
5320 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (assemblyb
->resources
, MonoReflectionResource
, i
));
5323 if (mb
->resources
) {
5324 int len
= mono_array_length (mb
->resources
);
5325 for (i
= 0; i
< len
; ++i
)
5326 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (mb
->resources
, MonoReflectionResource
, i
));
5329 build_compressed_metadata (assembly
);
5332 assembly_add_win32_resources (assembly
, assemblyb
);
5334 nsections
= calc_section_size (assembly
);
5336 /* The DOS header and stub */
5337 g_assert (sizeof (MonoMSDOSHeader
) == sizeof (msheader
));
5338 mono_image_add_stream_data (pefile
, (char*)msheader
, sizeof (msheader
));
5340 /* the dotnet header */
5341 header_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoDotNetHeader
));
5343 /* the section tables */
5344 section_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoSectionTable
) * nsections
);
5346 file_offset
= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5347 virtual_offset
= VIRT_ALIGN
;
5350 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5351 if (!assembly
->sections
[i
].size
)
5354 file_offset
+= FILE_ALIGN
- 1;
5355 file_offset
&= ~(FILE_ALIGN
- 1);
5356 virtual_offset
+= VIRT_ALIGN
- 1;
5357 virtual_offset
&= ~(VIRT_ALIGN
- 1);
5359 assembly
->sections
[i
].offset
= file_offset
;
5360 assembly
->sections
[i
].rva
= virtual_offset
;
5362 file_offset
+= assembly
->sections
[i
].size
;
5363 virtual_offset
+= assembly
->sections
[i
].size
;
5364 image_size
+= (assembly
->sections
[i
].size
+ VIRT_ALIGN
- 1) & ~(VIRT_ALIGN
- 1);
5367 file_offset
+= FILE_ALIGN
- 1;
5368 file_offset
&= ~(FILE_ALIGN
- 1);
5370 image_size
+= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5372 /* back-patch info */
5373 msdos
= (MonoMSDOSHeader
*)pefile
->data
;
5374 msdos
->pe_offset
= GUINT32_FROM_LE (sizeof (MonoMSDOSHeader
));
5376 header
= (MonoDotNetHeader
*)(pefile
->data
+ header_start
);
5377 header
->pesig
[0] = 'P';
5378 header
->pesig
[1] = 'E';
5380 header
->coff
.coff_machine
= GUINT16_FROM_LE (assemblyb
->machine
);
5381 header
->coff
.coff_sections
= GUINT16_FROM_LE (nsections
);
5382 header
->coff
.coff_time
= GUINT32_FROM_LE (time (NULL
));
5383 header
->coff
.coff_opt_header_size
= GUINT16_FROM_LE (sizeof (MonoDotNetHeader
) - sizeof (MonoCOFFHeader
) - 4);
5384 if (assemblyb
->pekind
== 1) {
5386 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x210e);
5389 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x010e);
5392 virtual_base
= 0x400000; /* FIXME: 0x10000000 if a DLL */
5394 header
->pe
.pe_magic
= GUINT16_FROM_LE (0x10B);
5395 header
->pe
.pe_major
= 6;
5396 header
->pe
.pe_minor
= 0;
5397 size
= assembly
->sections
[MONO_SECTION_TEXT
].size
;
5398 size
+= FILE_ALIGN
- 1;
5399 size
&= ~(FILE_ALIGN
- 1);
5400 header
->pe
.pe_code_size
= GUINT32_FROM_LE(size
);
5401 size
= assembly
->sections
[MONO_SECTION_RSRC
].size
;
5402 size
+= FILE_ALIGN
- 1;
5403 size
&= ~(FILE_ALIGN
- 1);
5404 header
->pe
.pe_data_size
= GUINT32_FROM_LE(size
);
5405 g_assert (START_TEXT_RVA
== assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5406 header
->pe
.pe_rva_code_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5407 header
->pe
.pe_rva_data_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5408 /* pe_rva_entry_point always at the beginning of the text section */
5409 header
->pe
.pe_rva_entry_point
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5411 header
->nt
.pe_image_base
= GUINT32_FROM_LE (virtual_base
);
5412 header
->nt
.pe_section_align
= GUINT32_FROM_LE (VIRT_ALIGN
);
5413 header
->nt
.pe_file_alignment
= GUINT32_FROM_LE (FILE_ALIGN
);
5414 header
->nt
.pe_os_major
= GUINT16_FROM_LE (4);
5415 header
->nt
.pe_os_minor
= GUINT16_FROM_LE (0);
5416 header
->nt
.pe_subsys_major
= GUINT16_FROM_LE (4);
5417 size
= section_start
;
5418 size
+= FILE_ALIGN
- 1;
5419 size
&= ~(FILE_ALIGN
- 1);
5420 header
->nt
.pe_header_size
= GUINT32_FROM_LE (size
);
5422 size
+= VIRT_ALIGN
- 1;
5423 size
&= ~(VIRT_ALIGN
- 1);
5424 header
->nt
.pe_image_size
= GUINT32_FROM_LE (size
);
5427 // Translate the PEFileKind value to the value expected by the Windows loader
5433 // PEFileKinds.Dll == 1
5434 // PEFileKinds.ConsoleApplication == 2
5435 // PEFileKinds.WindowApplication == 3
5438 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5439 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5441 if (assemblyb
->pekind
== 3)
5446 header
->nt
.pe_subsys_required
= GUINT16_FROM_LE (kind
);
5448 header
->nt
.pe_stack_reserve
= GUINT32_FROM_LE (0x00100000);
5449 header
->nt
.pe_stack_commit
= GUINT32_FROM_LE (0x00001000);
5450 header
->nt
.pe_heap_reserve
= GUINT32_FROM_LE (0x00100000);
5451 header
->nt
.pe_heap_commit
= GUINT32_FROM_LE (0x00001000);
5452 header
->nt
.pe_loader_flags
= GUINT32_FROM_LE (0);
5453 header
->nt
.pe_data_dir_count
= GUINT32_FROM_LE (16);
5455 /* fill data directory entries */
5457 header
->datadir
.pe_resource_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].size
);
5458 header
->datadir
.pe_resource_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5460 header
->datadir
.pe_reloc_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].size
);
5461 header
->datadir
.pe_reloc_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].rva
);
5463 header
->datadir
.pe_cli_header
.size
= GUINT32_FROM_LE (72);
5464 header
->datadir
.pe_cli_header
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->cli_header_offset
);
5465 header
->datadir
.pe_iat
.size
= GUINT32_FROM_LE (8);
5466 header
->datadir
.pe_iat
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5467 /* patch entrypoint name */
5468 if (assemblyb
->pekind
== 1)
5469 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorDllMain", 12);
5471 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorExeMain", 12);
5472 /* patch imported function RVA name */
5473 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->iat_offset
);
5474 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
);
5476 /* the import table */
5477 header
->datadir
.pe_import_table
.size
= GUINT32_FROM_LE (79); /* FIXME: magic number? */
5478 header
->datadir
.pe_import_table
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->idt_offset
);
5479 /* patch imported dll RVA name and other entries in the dir */
5480 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, name_rva
));
5481 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
+ 14); /* 14 is hint+strlen+1 of func name */
5482 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_address_table_rva
));
5483 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5484 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_lookup_table
));
5485 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->ilt_offset
);
5487 p
= (guchar
*)(assembly
->code
.data
+ assembly
->ilt_offset
);
5488 value
= (assembly
->text_rva
+ assembly
->imp_names_offset
);
5489 *p
++ = (value
) & 0xff;
5490 *p
++ = (value
>> 8) & (0xff);
5491 *p
++ = (value
>> 16) & (0xff);
5492 *p
++ = (value
>> 24) & (0xff);
5494 /* the CLI header info */
5495 cli_header
= (MonoCLIHeader
*)(assembly
->code
.data
+ assembly
->cli_header_offset
);
5496 cli_header
->ch_size
= GUINT32_FROM_LE (72);
5497 cli_header
->ch_runtime_major
= GUINT16_FROM_LE (2);
5498 if (mono_framework_version () > 1)
5499 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (5);
5501 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (0);
5502 cli_header
->ch_flags
= GUINT32_FROM_LE (assemblyb
->pe_kind
);
5503 if (assemblyb
->entry_point
) {
5504 guint32 table_idx
= 0;
5505 if (!strcmp (assemblyb
->entry_point
->object
.vtable
->klass
->name
, "MethodBuilder")) {
5506 MonoReflectionMethodBuilder
*methodb
= (MonoReflectionMethodBuilder
*)assemblyb
->entry_point
;
5507 table_idx
= methodb
->table_idx
;
5509 table_idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, assemblyb
->entry_point
->method
));
5511 cli_header
->ch_entry_point
= GUINT32_FROM_LE (table_idx
| MONO_TOKEN_METHOD_DEF
);
5513 cli_header
->ch_entry_point
= GUINT32_FROM_LE (0);
5515 /* The embedded managed resources */
5516 text_offset
= assembly
->text_rva
+ assembly
->code
.index
;
5517 cli_header
->ch_resources
.rva
= GUINT32_FROM_LE (text_offset
);
5518 cli_header
->ch_resources
.size
= GUINT32_FROM_LE (assembly
->resources
.index
);
5519 text_offset
+= assembly
->resources
.index
;
5520 cli_header
->ch_metadata
.rva
= GUINT32_FROM_LE (text_offset
);
5521 cli_header
->ch_metadata
.size
= GUINT32_FROM_LE (assembly
->meta_size
);
5522 text_offset
+= assembly
->meta_size
;
5523 if (assembly
->strong_name_size
) {
5524 cli_header
->ch_strong_name
.rva
= GUINT32_FROM_LE (text_offset
);
5525 cli_header
->ch_strong_name
.size
= GUINT32_FROM_LE (assembly
->strong_name_size
);
5526 text_offset
+= assembly
->strong_name_size
;
5529 /* write the section tables and section content */
5530 section
= (MonoSectionTable
*)(pefile
->data
+ section_start
);
5531 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5532 static const char section_names
[][7] = {
5533 ".text", ".rsrc", ".reloc"
5535 if (!assembly
->sections
[i
].size
)
5537 strcpy (section
->st_name
, section_names
[i
]);
5538 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5539 section
->st_virtual_address
= GUINT32_FROM_LE (assembly
->sections
[i
].rva
);
5540 section
->st_virtual_size
= GUINT32_FROM_LE (assembly
->sections
[i
].size
);
5541 section
->st_raw_data_size
= GUINT32_FROM_LE (GUINT32_TO_LE (section
->st_virtual_size
) + (FILE_ALIGN
- 1));
5542 section
->st_raw_data_size
&= GUINT32_FROM_LE (~(FILE_ALIGN
- 1));
5543 section
->st_raw_data_ptr
= GUINT32_FROM_LE (assembly
->sections
[i
].offset
);
5544 section
->st_flags
= GUINT32_FROM_LE (assembly
->sections
[i
].attrs
);
5548 checked_write_file (file
, pefile
->data
, pefile
->index
);
5550 mono_dynamic_stream_reset (pefile
);
5552 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5553 if (!assembly
->sections
[i
].size
)
5556 if (SetFilePointer (file
, assembly
->sections
[i
].offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5557 g_error ("SetFilePointer returned %d\n", GetLastError ());
5560 case MONO_SECTION_TEXT
:
5561 /* patch entry point */
5562 p
= (guchar
*)(assembly
->code
.data
+ 2);
5563 value
= (virtual_base
+ assembly
->text_rva
+ assembly
->iat_offset
);
5564 *p
++ = (value
) & 0xff;
5565 *p
++ = (value
>> 8) & 0xff;
5566 *p
++ = (value
>> 16) & 0xff;
5567 *p
++ = (value
>> 24) & 0xff;
5569 checked_write_file (file
, assembly
->code
.data
, assembly
->code
.index
);
5570 checked_write_file (file
, assembly
->resources
.data
, assembly
->resources
.index
);
5571 checked_write_file (file
, assembly
->image
.raw_metadata
, assembly
->meta_size
);
5572 checked_write_file (file
, assembly
->strong_name
, assembly
->strong_name_size
);
5575 g_free (assembly
->image
.raw_metadata
);
5577 case MONO_SECTION_RELOC
: {
5581 guint16 type_and_offset
;
5585 g_assert (sizeof (reloc
) == 12);
5587 reloc
.page_rva
= GUINT32_FROM_LE (assembly
->text_rva
);
5588 reloc
.block_size
= GUINT32_FROM_LE (12);
5591 * the entrypoint is always at the start of the text section
5592 * 3 is IMAGE_REL_BASED_HIGHLOW
5593 * 2 is patch_size_rva - text_rva
5595 reloc
.type_and_offset
= GUINT16_FROM_LE ((3 << 12) + (2));
5598 checked_write_file (file
, &reloc
, sizeof (reloc
));
5602 case MONO_SECTION_RSRC
:
5603 if (assembly
->win32_res
) {
5605 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5606 fixup_resource_directory (assembly
->win32_res
, assembly
->win32_res
, assembly
->sections
[i
].rva
);
5607 checked_write_file (file
, assembly
->win32_res
, assembly
->win32_res_size
);
5611 g_assert_not_reached ();
5615 /* check that the file is properly padded */
5616 if (SetFilePointer (file
, file_offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5617 g_error ("SetFilePointer returned %d\n", GetLastError ());
5618 if (! SetEndOfFile (file
))
5619 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5621 mono_dynamic_stream_reset (&assembly
->code
);
5622 mono_dynamic_stream_reset (&assembly
->us
);
5623 mono_dynamic_stream_reset (&assembly
->blob
);
5624 mono_dynamic_stream_reset (&assembly
->guid
);
5625 mono_dynamic_stream_reset (&assembly
->sheap
);
5627 g_hash_table_foreach (assembly
->blob_cache
, (GHFunc
)g_free
, NULL
);
5628 g_hash_table_destroy (assembly
->blob_cache
);
5629 assembly
->blob_cache
= NULL
;
5632 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5635 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5637 g_assert_not_reached ();
5640 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5642 #ifndef DISABLE_REFLECTION_EMIT
5644 MonoReflectionModule
*
5645 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
5649 MonoImageOpenStatus status
;
5650 MonoDynamicAssembly
*assembly
;
5651 guint32 module_count
;
5652 MonoImage
**new_modules
;
5653 gboolean
*new_modules_loaded
;
5655 name
= mono_string_to_utf8 (fileName
);
5657 image
= mono_image_open (name
, &status
);
5660 if (status
== MONO_IMAGE_ERROR_ERRNO
)
5661 exc
= mono_get_exception_file_not_found (fileName
);
5663 exc
= mono_get_exception_bad_image_format (name
);
5665 mono_raise_exception (exc
);
5670 assembly
= ab
->dynamic_assembly
;
5671 image
->assembly
= (MonoAssembly
*)assembly
;
5673 module_count
= image
->assembly
->image
->module_count
;
5674 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5675 new_modules_loaded
= g_new0 (gboolean
, module_count
+ 1);
5677 if (image
->assembly
->image
->modules
)
5678 memcpy (new_modules
, image
->assembly
->image
->modules
, module_count
* sizeof (MonoImage
*));
5679 if (image
->assembly
->image
->modules_loaded
)
5680 memcpy (new_modules_loaded
, image
->assembly
->image
->modules_loaded
, module_count
* sizeof (gboolean
));
5681 new_modules
[module_count
] = image
;
5682 new_modules_loaded
[module_count
] = TRUE
;
5683 mono_image_addref (image
);
5685 g_free (image
->assembly
->image
->modules
);
5686 image
->assembly
->image
->modules
= new_modules
;
5687 image
->assembly
->image
->modules_loaded
= new_modules_loaded
;
5688 image
->assembly
->image
->module_count
++;
5690 mono_assembly_load_references (image
, &status
);
5692 mono_image_close (image
);
5693 mono_raise_exception (mono_get_exception_file_not_found (fileName
));
5696 return mono_module_get_object (mono_domain_get (), image
);
5699 #endif /* DISABLE_REFLECTION_EMIT */
5702 * We need to return always the same object for MethodInfo, FieldInfo etc..
5703 * but we need to consider the reflected type.
5704 * type uses a different hash, since it uses custom hash/equal functions.
5709 MonoClass
*refclass
;
5713 reflected_equal (gconstpointer a
, gconstpointer b
) {
5714 const ReflectedEntry
*ea
= a
;
5715 const ReflectedEntry
*eb
= b
;
5717 return (ea
->item
== eb
->item
) && (ea
->refclass
== eb
->refclass
);
5721 reflected_hash (gconstpointer a
) {
5722 const ReflectedEntry
*ea
= a
;
5723 return mono_aligned_addr_hash (ea
->item
);
5726 #define CHECK_OBJECT(t,p,k) \
5732 mono_domain_lock (domain); \
5733 if (!domain->refobject_hash) \
5734 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5735 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5736 mono_domain_unlock (domain); \
5739 mono_domain_unlock (domain); \
5742 #ifdef HAVE_BOEHM_GC
5743 /* ReflectedEntry doesn't need to be GC tracked */
5744 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5745 #define FREE_REFENTRY(entry) g_free ((entry))
5746 #define REFENTRY_REQUIRES_CLEANUP
5748 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5750 #define FREE_REFENTRY(entry)
5753 #define CACHE_OBJECT(t,p,o,k) \
5756 ReflectedEntry pe; \
5758 pe.refclass = (k); \
5759 mono_domain_lock (domain); \
5760 if (!domain->refobject_hash) \
5761 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5762 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5764 ReflectedEntry *e = ALLOC_REFENTRY; \
5766 e->refclass = (k); \
5767 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5770 mono_domain_unlock (domain); \
5775 clear_cached_object (MonoDomain
*domain
, gpointer o
, MonoClass
*klass
)
5777 mono_domain_lock (domain
);
5778 if (domain
->refobject_hash
) {
5780 gpointer orig_pe
, orig_value
;
5783 pe
.refclass
= klass
;
5784 if (mono_g_hash_table_lookup_extended (domain
->refobject_hash
, &pe
, &orig_pe
, &orig_value
)) {
5785 mono_g_hash_table_remove (domain
->refobject_hash
, &pe
);
5786 FREE_REFENTRY (orig_pe
);
5789 mono_domain_unlock (domain
);
5792 #ifdef REFENTRY_REQUIRES_CLEANUP
5794 cleanup_refobject_hash (gpointer key
, gpointer value
, gpointer user_data
)
5796 FREE_REFENTRY (key
);
5801 mono_reflection_cleanup_domain (MonoDomain
*domain
)
5803 if (domain
->refobject_hash
) {
5804 /*let's avoid scanning the whole hashtable if not needed*/
5805 #ifdef REFENTRY_REQUIRES_CLEANUP
5806 mono_g_hash_table_foreach (domain
->refobject_hash
, cleanup_refobject_hash
, NULL
);
5808 mono_g_hash_table_destroy (domain
->refobject_hash
);
5809 domain
->refobject_hash
= NULL
;
5813 #ifndef DISABLE_REFLECTION_EMIT
5815 register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
)
5817 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
5821 register_module (MonoDomain
*domain
, MonoReflectionModuleBuilder
*res
, MonoDynamicImage
*module
)
5823 CACHE_OBJECT (MonoReflectionModuleBuilder
*, module
, res
, NULL
);
5827 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
5829 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
5830 MonoReflectionAssemblyBuilder
*ab
= moduleb
->assemblyb
;
5833 MonoImage
**new_modules
;
5836 * FIXME: we already created an image in mono_image_basic_init (), but
5837 * we don't know which module it belongs to, since that is only
5838 * determined at assembly save time.
5840 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5841 image
= create_dynamic_mono_image (ab
->dynamic_assembly
, mono_string_to_utf8 (ab
->name
), mono_string_to_utf8 (moduleb
->module
.fqname
));
5843 moduleb
->module
.image
= &image
->image
;
5844 moduleb
->dynamic_image
= image
;
5845 register_module (mono_object_domain (moduleb
), moduleb
, image
);
5847 /* register the module with the assembly */
5848 ass
= ab
->dynamic_assembly
->assembly
.image
;
5849 module_count
= ass
->module_count
;
5850 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5853 memcpy (new_modules
, ass
->modules
, module_count
* sizeof (MonoImage
*));
5854 new_modules
[module_count
] = &image
->image
;
5855 mono_image_addref (&image
->image
);
5857 g_free (ass
->modules
);
5858 ass
->modules
= new_modules
;
5859 ass
->module_count
++;
5866 * mono_assembly_get_object:
5867 * @domain: an app domain
5868 * @assembly: an assembly
5870 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5872 MonoReflectionAssembly
*
5873 mono_assembly_get_object (MonoDomain
*domain
, MonoAssembly
*assembly
)
5875 static MonoClass
*System_Reflection_Assembly
;
5876 MonoReflectionAssembly
*res
;
5878 CHECK_OBJECT (MonoReflectionAssembly
*, assembly
, NULL
);
5879 if (!System_Reflection_Assembly
)
5880 System_Reflection_Assembly
= mono_class_from_name (
5881 mono_defaults
.corlib
, "System.Reflection", "Assembly");
5882 res
= (MonoReflectionAssembly
*)mono_object_new (domain
, System_Reflection_Assembly
);
5883 res
->assembly
= assembly
;
5885 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
5890 MonoReflectionModule
*
5891 mono_module_get_object (MonoDomain
*domain
, MonoImage
*image
)
5893 static MonoClass
*System_Reflection_Module
;
5894 MonoReflectionModule
*res
;
5897 CHECK_OBJECT (MonoReflectionModule
*, image
, NULL
);
5898 if (!System_Reflection_Module
)
5899 System_Reflection_Module
= mono_class_from_name (
5900 mono_defaults
.corlib
, "System.Reflection", "Module");
5901 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
5904 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
5906 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, image
->name
));
5907 basename
= g_path_get_basename (image
->name
);
5908 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, basename
));
5909 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, image
->module_name
));
5913 if (image
->assembly
->image
== image
) {
5914 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULE
, 1);
5918 if (image
->assembly
->image
->modules
) {
5919 for (i
= 0; i
< image
->assembly
->image
->module_count
; i
++) {
5920 if (image
->assembly
->image
->modules
[i
] == image
)
5921 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULEREF
, i
+ 1);
5923 g_assert (res
->token
);
5927 CACHE_OBJECT (MonoReflectionModule
*, image
, res
, NULL
);
5930 MonoReflectionModule
*
5931 mono_module_file_get_object (MonoDomain
*domain
, MonoImage
*image
, int table_index
)
5933 static MonoClass
*System_Reflection_Module
;
5934 MonoReflectionModule
*res
;
5935 MonoTableInfo
*table
;
5936 guint32 cols
[MONO_FILE_SIZE
];
5938 guint32 i
, name_idx
;
5941 if (!System_Reflection_Module
)
5942 System_Reflection_Module
= mono_class_from_name (
5943 mono_defaults
.corlib
, "System.Reflection", "Module");
5944 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
5946 table
= &image
->tables
[MONO_TABLE_FILE
];
5947 g_assert (table_index
< table
->rows
);
5948 mono_metadata_decode_row (table
, table_index
, cols
, MONO_FILE_SIZE
);
5951 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
5952 name
= mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]);
5954 /* Check whenever the row has a corresponding row in the moduleref table */
5955 table
= &image
->tables
[MONO_TABLE_MODULEREF
];
5956 for (i
= 0; i
< table
->rows
; ++i
) {
5957 name_idx
= mono_metadata_decode_row_col (table
, i
, MONO_MODULEREF_NAME
);
5958 val
= mono_metadata_string_heap (image
, name_idx
);
5959 if (strcmp (val
, name
) == 0)
5960 res
->image
= image
->modules
[i
];
5963 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, name
));
5964 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, name
));
5965 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, name
));
5966 res
->is_resource
= cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
;
5967 res
->token
= mono_metadata_make_token (MONO_TABLE_FILE
, table_index
+ 1);
5973 mymono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
5975 if ((t1
->type
!= t2
->type
) ||
5976 (t1
->byref
!= t2
->byref
))
5980 case MONO_TYPE_VOID
:
5981 case MONO_TYPE_BOOLEAN
:
5982 case MONO_TYPE_CHAR
:
5993 case MONO_TYPE_STRING
:
5996 case MONO_TYPE_OBJECT
:
5997 case MONO_TYPE_TYPEDBYREF
:
5999 case MONO_TYPE_VALUETYPE
:
6000 case MONO_TYPE_CLASS
:
6001 case MONO_TYPE_SZARRAY
:
6002 return t1
->data
.klass
== t2
->data
.klass
;
6004 return mymono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
);
6005 case MONO_TYPE_ARRAY
:
6006 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
6008 return t1
->data
.array
->eklass
== t2
->data
.array
->eklass
;
6009 case MONO_TYPE_GENERICINST
: {
6011 MonoGenericInst
*i1
= t1
->data
.generic_class
->context
.class_inst
;
6012 MonoGenericInst
*i2
= t2
->data
.generic_class
->context
.class_inst
;
6013 if (i1
->type_argc
!= i2
->type_argc
)
6015 if (!mono_metadata_type_equal (&t1
->data
.generic_class
->container_class
->byval_arg
,
6016 &t2
->data
.generic_class
->container_class
->byval_arg
))
6018 /* FIXME: we should probably just compare the instance pointers directly. */
6019 for (i
= 0; i
< i1
->type_argc
; ++i
) {
6020 if (!mono_metadata_type_equal (i1
->type_argv
[i
], i2
->type_argv
[i
]))
6026 case MONO_TYPE_MVAR
:
6027 return t1
->data
.generic_param
== t2
->data
.generic_param
;
6029 g_error ("implement type compare for %0x!", t1
->type
);
6037 mymono_metadata_type_hash (MonoType
*t1
)
6043 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
6045 case MONO_TYPE_VALUETYPE
:
6046 case MONO_TYPE_CLASS
:
6047 case MONO_TYPE_SZARRAY
:
6048 /* check if the distribution is good enough */
6049 return ((hash
<< 5) - hash
) ^ g_str_hash (t1
->data
.klass
->name
);
6051 return ((hash
<< 5) - hash
) ^ mymono_metadata_type_hash (t1
->data
.type
);
6052 case MONO_TYPE_GENERICINST
: {
6054 MonoGenericInst
*inst
= t1
->data
.generic_class
->context
.class_inst
;
6055 hash
+= g_str_hash (t1
->data
.generic_class
->container_class
->name
);
6057 for (i
= 0; i
< inst
->type_argc
; ++i
) {
6058 hash
+= mymono_metadata_type_hash (inst
->type_argv
[i
]);
6067 static MonoReflectionGenericClass
*
6068 mono_generic_class_get_object (MonoDomain
*domain
, MonoType
*geninst
)
6070 static MonoClass
*System_Reflection_MonoGenericClass
;
6071 MonoReflectionGenericClass
*res
;
6072 MonoClass
*klass
, *gklass
;
6074 if (!System_Reflection_MonoGenericClass
) {
6075 System_Reflection_MonoGenericClass
= mono_class_from_name (
6076 mono_defaults
.corlib
, "System.Reflection", "MonoGenericClass");
6077 g_assert (System_Reflection_MonoGenericClass
);
6080 klass
= mono_class_from_mono_type (geninst
);
6081 gklass
= klass
->generic_class
->container_class
;
6083 mono_class_init (klass
);
6086 res
= (MonoReflectionGenericClass
*) mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, System_Reflection_MonoGenericClass
), mono_class_instance_size (System_Reflection_MonoGenericClass
));
6088 res
= (MonoReflectionGenericClass
*) mono_object_new (domain
, System_Reflection_MonoGenericClass
);
6091 res
->type
.type
= geninst
;
6092 g_assert (gklass
->reflection_info
);
6093 g_assert (!strcmp (((MonoObject
*)gklass
->reflection_info
)->vtable
->klass
->name
, "TypeBuilder"));
6094 MONO_OBJECT_SETREF (res
, generic_type
, gklass
->reflection_info
);
6100 verify_safe_for_managed_space (MonoType
*type
)
6102 switch (type
->type
) {
6104 case MONO_TYPE_ARRAY
:
6105 return verify_safe_for_managed_space (&type
->data
.array
->eklass
->byval_arg
);
6107 return verify_safe_for_managed_space (type
->data
.type
);
6108 case MONO_TYPE_SZARRAY
:
6109 return verify_safe_for_managed_space (&type
->data
.klass
->byval_arg
);
6110 case MONO_TYPE_GENERICINST
: {
6111 MonoGenericInst
*inst
= type
->data
.generic_class
->inst
;
6115 for (i
= 0; i
< inst
->type_argc
; ++i
)
6116 if (!verify_safe_for_managed_space (inst
->type_argv
[i
]))
6122 case MONO_TYPE_MVAR
:
6129 * mono_type_get_object:
6130 * @domain: an app domain
6133 * Return an System.MonoType object representing the type @type.
6136 mono_type_get_object (MonoDomain
*domain
, MonoType
*type
)
6138 MonoReflectionType
*res
;
6139 MonoClass
*klass
= mono_class_from_mono_type (type
);
6141 /*we must avoid using @type as it might have come
6142 * from a mono_metadata_type_dup and the caller
6143 * expects that is can be freed.
6144 * Using the right type from
6146 type
= klass
->byval_arg
.byref
== type
->byref
? &klass
->byval_arg
: &klass
->this_arg
;
6148 /* void is very common */
6149 if (type
->type
== MONO_TYPE_VOID
&& domain
->typeof_void
)
6150 return (MonoReflectionType
*)domain
->typeof_void
;
6153 * If the vtable of the given class was already created, we can use
6154 * the MonoType from there and avoid all locking and hash table lookups.
6156 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6157 * that the resulting object is diferent.
6159 if (type
== &klass
->byval_arg
&& !klass
->image
->dynamic
) {
6160 MonoVTable
*vtable
= mono_class_try_get_vtable (domain
, klass
);
6161 if (vtable
&& vtable
->type
)
6162 return vtable
->type
;
6165 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6166 mono_domain_lock (domain
);
6167 if (!domain
->type_hash
)
6168 domain
->type_hash
= mono_g_hash_table_new_type ((GHashFunc
)mymono_metadata_type_hash
,
6169 (GCompareFunc
)mymono_metadata_type_equal
, MONO_HASH_VALUE_GC
);
6170 if ((res
= mono_g_hash_table_lookup (domain
->type_hash
, type
))) {
6171 mono_domain_unlock (domain
);
6172 mono_loader_unlock ();
6175 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6176 if ((type
->type
== MONO_TYPE_GENERICINST
) && type
->data
.generic_class
->is_dynamic
&& !type
->data
.generic_class
->container_class
->wastypebuilder
) {
6177 res
= (MonoReflectionType
*)mono_generic_class_get_object (domain
, type
);
6178 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6179 mono_domain_unlock (domain
);
6180 mono_loader_unlock ();
6184 if (!verify_safe_for_managed_space (type
)) {
6185 mono_domain_unlock (domain
);
6186 mono_loader_unlock ();
6187 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6190 if (klass
->reflection_info
&& !klass
->wastypebuilder
) {
6191 /* g_assert_not_reached (); */
6192 /* should this be considered an error condition? */
6194 mono_domain_unlock (domain
);
6195 mono_loader_unlock ();
6196 return klass
->reflection_info
;
6199 // FIXME: Get rid of this, do it in the icalls for Type
6200 mono_class_init (klass
);
6202 res
= (MonoReflectionType
*)mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, mono_defaults
.monotype_class
), mono_class_instance_size (mono_defaults
.monotype_class
));
6204 res
= (MonoReflectionType
*)mono_object_new (domain
, mono_defaults
.monotype_class
);
6207 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6209 if (type
->type
== MONO_TYPE_VOID
)
6210 MONO_OBJECT_SETREF (domain
, typeof_void
, res
);
6212 mono_domain_unlock (domain
);
6213 mono_loader_unlock ();
6218 * mono_method_get_object:
6219 * @domain: an app domain
6221 * @refclass: the reflected type (can be NULL)
6223 * Return an System.Reflection.MonoMethod object representing the method @method.
6225 MonoReflectionMethod
*
6226 mono_method_get_object (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
6229 * We use the same C representation for methods and constructors, but the type
6230 * name in C# is different.
6232 static MonoClass
*System_Reflection_MonoMethod
= NULL
;
6233 static MonoClass
*System_Reflection_MonoCMethod
= NULL
;
6234 static MonoClass
*System_Reflection_MonoGenericMethod
= NULL
;
6235 static MonoClass
*System_Reflection_MonoGenericCMethod
= NULL
;
6237 MonoReflectionMethod
*ret
;
6239 if (method
->is_inflated
) {
6240 MonoReflectionGenericMethod
*gret
;
6242 refclass
= method
->klass
;
6243 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6244 if ((*method
->name
== '.') && (!strcmp (method
->name
, ".ctor") || !strcmp (method
->name
, ".cctor"))) {
6245 if (!System_Reflection_MonoGenericCMethod
)
6246 System_Reflection_MonoGenericCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericCMethod");
6247 klass
= System_Reflection_MonoGenericCMethod
;
6249 if (!System_Reflection_MonoGenericMethod
)
6250 System_Reflection_MonoGenericMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericMethod");
6251 klass
= System_Reflection_MonoGenericMethod
;
6253 gret
= (MonoReflectionGenericMethod
*)mono_object_new (domain
, klass
);
6254 gret
->method
.method
= method
;
6255 MONO_OBJECT_SETREF (gret
, method
.name
, mono_string_new (domain
, method
->name
));
6256 MONO_OBJECT_SETREF (gret
, method
.reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6257 CACHE_OBJECT (MonoReflectionMethod
*, method
, (MonoReflectionMethod
*)gret
, refclass
);
6261 refclass
= method
->klass
;
6263 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6264 if (*method
->name
== '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0)) {
6265 if (!System_Reflection_MonoCMethod
)
6266 System_Reflection_MonoCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoCMethod");
6267 klass
= System_Reflection_MonoCMethod
;
6270 if (!System_Reflection_MonoMethod
)
6271 System_Reflection_MonoMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoMethod");
6272 klass
= System_Reflection_MonoMethod
;
6274 ret
= (MonoReflectionMethod
*)mono_object_new (domain
, klass
);
6275 ret
->method
= method
;
6276 MONO_OBJECT_SETREF (ret
, reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6277 CACHE_OBJECT (MonoReflectionMethod
*, method
, ret
, refclass
);
6281 * mono_method_clear_object:
6283 * Clear the cached reflection objects for the dynamic method METHOD.
6286 mono_method_clear_object (MonoDomain
*domain
, MonoMethod
*method
)
6288 g_assert (method
->dynamic
);
6290 clear_cached_object (domain
, method
, method
->klass
);
6291 /* Added by mono_param_get_objects () */
6292 clear_cached_object (domain
, &(method
->signature
), NULL
);
6296 * mono_field_get_object:
6297 * @domain: an app domain
6301 * Return an System.Reflection.MonoField object representing the field @field
6304 MonoReflectionField
*
6305 mono_field_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
)
6307 MonoReflectionField
*res
;
6308 static MonoClass
*monofield_klass
;
6310 CHECK_OBJECT (MonoReflectionField
*, field
, klass
);
6311 if (!monofield_klass
)
6312 monofield_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoField");
6313 res
= (MonoReflectionField
*)mono_object_new (domain
, monofield_klass
);
6316 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, mono_field_get_name (field
)));
6317 if (is_field_on_inst (field
))
6318 res
->attrs
= get_field_on_inst_generic_type (field
)->attrs
;
6320 res
->attrs
= field
->type
->attrs
;
6321 MONO_OBJECT_SETREF (res
, type
, mono_type_get_object (domain
, field
->type
));
6322 CACHE_OBJECT (MonoReflectionField
*, field
, res
, klass
);
6326 * mono_property_get_object:
6327 * @domain: an app domain
6329 * @property: a property
6331 * Return an System.Reflection.MonoProperty object representing the property @property
6334 MonoReflectionProperty
*
6335 mono_property_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
)
6337 MonoReflectionProperty
*res
;
6338 static MonoClass
*monoproperty_klass
;
6340 CHECK_OBJECT (MonoReflectionProperty
*, property
, klass
);
6341 if (!monoproperty_klass
)
6342 monoproperty_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoProperty");
6343 res
= (MonoReflectionProperty
*)mono_object_new (domain
, monoproperty_klass
);
6345 res
->property
= property
;
6346 CACHE_OBJECT (MonoReflectionProperty
*, property
, res
, klass
);
6350 * mono_event_get_object:
6351 * @domain: an app domain
6355 * Return an System.Reflection.MonoEvent object representing the event @event
6358 MonoReflectionEvent
*
6359 mono_event_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
)
6361 MonoReflectionEvent
*res
;
6362 MonoReflectionMonoEvent
*mono_event
;
6363 static MonoClass
*monoevent_klass
;
6365 CHECK_OBJECT (MonoReflectionEvent
*, event
, klass
);
6366 if (!monoevent_klass
)
6367 monoevent_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoEvent");
6368 mono_event
= (MonoReflectionMonoEvent
*)mono_object_new (domain
, monoevent_klass
);
6369 mono_event
->klass
= klass
;
6370 mono_event
->event
= event
;
6371 res
= (MonoReflectionEvent
*)mono_event
;
6372 CACHE_OBJECT (MonoReflectionEvent
*, event
, res
, klass
);
6376 * mono_get_reflection_missing_object:
6377 * @domain: Domain where the object lives
6379 * Returns the System.Reflection.Missing.Value singleton object
6380 * (of type System.Reflection.Missing).
6382 * Used as the value for ParameterInfo.DefaultValue when Optional
6386 mono_get_reflection_missing_object (MonoDomain
*domain
)
6389 static MonoClassField
*missing_value_field
= NULL
;
6391 if (!missing_value_field
) {
6392 MonoClass
*missing_klass
;
6393 missing_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Missing");
6394 mono_class_init (missing_klass
);
6395 missing_value_field
= mono_class_get_field_from_name (missing_klass
, "Value");
6396 g_assert (missing_value_field
);
6398 obj
= mono_field_get_value_object (domain
, missing_value_field
, NULL
);
6404 get_dbnull (MonoDomain
*domain
, MonoObject
**dbnull
)
6407 *dbnull
= mono_get_dbnull_object (domain
);
6412 get_reflection_missing (MonoDomain
*domain
, MonoObject
**reflection_missing
)
6414 if (!*reflection_missing
)
6415 *reflection_missing
= mono_get_reflection_missing_object (domain
);
6416 return *reflection_missing
;
6420 * mono_param_get_objects:
6421 * @domain: an app domain
6424 * Return an System.Reflection.ParameterInfo array object representing the parameters
6425 * in the method @method.
6428 mono_param_get_objects_internal (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
6430 static MonoClass
*System_Reflection_ParameterInfo
;
6431 static MonoClass
*System_Reflection_ParameterInfo_array
;
6432 MonoArray
*res
= NULL
;
6433 MonoReflectionMethod
*member
= NULL
;
6434 MonoReflectionParameter
*param
= NULL
;
6435 char **names
, **blobs
= NULL
;
6436 guint32
*types
= NULL
;
6437 MonoType
*type
= NULL
;
6438 MonoObject
*dbnull
= NULL
;
6439 MonoObject
*missing
= NULL
;
6440 MonoMarshalSpec
**mspecs
;
6441 MonoMethodSignature
*sig
;
6442 MonoVTable
*pinfo_vtable
;
6445 if (!System_Reflection_ParameterInfo_array
) {
6448 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ParameterInfo");
6449 mono_memory_barrier ();
6450 System_Reflection_ParameterInfo
= klass
;
6452 klass
= mono_array_class_get (klass
, 1);
6453 mono_memory_barrier ();
6454 System_Reflection_ParameterInfo_array
= klass
;
6457 if (!mono_method_signature (method
)->param_count
)
6458 return mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), 0);
6460 /* Note: the cache is based on the address of the signature into the method
6461 * since we already cache MethodInfos with the method as keys.
6463 CHECK_OBJECT (MonoArray
*, &(method
->signature
), refclass
);
6465 sig
= mono_method_signature (method
);
6466 member
= mono_method_get_object (domain
, method
, refclass
);
6467 names
= g_new (char *, sig
->param_count
);
6468 mono_method_get_param_names (method
, (const char **) names
);
6470 mspecs
= g_new (MonoMarshalSpec
*, sig
->param_count
+ 1);
6471 mono_method_get_marshal_info (method
, mspecs
);
6473 res
= mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), sig
->param_count
);
6474 pinfo_vtable
= mono_class_vtable (domain
, System_Reflection_ParameterInfo
);
6475 for (i
= 0; i
< sig
->param_count
; ++i
) {
6476 param
= (MonoReflectionParameter
*)mono_object_new_specific (pinfo_vtable
);
6477 MONO_OBJECT_SETREF (param
, ClassImpl
, mono_type_get_object (domain
, sig
->params
[i
]));
6478 MONO_OBJECT_SETREF (param
, MemberImpl
, (MonoObject
*)member
);
6479 MONO_OBJECT_SETREF (param
, NameImpl
, mono_string_new (domain
, names
[i
]));
6480 param
->PositionImpl
= i
;
6481 param
->AttrsImpl
= sig
->params
[i
]->attrs
;
6483 if (!(param
->AttrsImpl
& PARAM_ATTRIBUTE_HAS_DEFAULT
)) {
6484 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6485 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6487 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6491 blobs
= g_new0 (char *, sig
->param_count
);
6492 types
= g_new0 (guint32
, sig
->param_count
);
6493 get_default_param_value_blobs (method
, blobs
, types
);
6496 /* Build MonoType for the type from the Constant Table */
6498 type
= g_new0 (MonoType
, 1);
6499 type
->type
= types
[i
];
6500 type
->data
.klass
= NULL
;
6501 if (types
[i
] == MONO_TYPE_CLASS
)
6502 type
->data
.klass
= mono_defaults
.object_class
;
6503 else if ((sig
->params
[i
]->type
== MONO_TYPE_VALUETYPE
) && sig
->params
[i
]->data
.klass
->enumtype
) {
6504 /* For enums, types [i] contains the base type */
6506 type
->type
= MONO_TYPE_VALUETYPE
;
6507 type
->data
.klass
= mono_class_from_mono_type (sig
->params
[i
]);
6509 type
->data
.klass
= mono_class_from_mono_type (type
);
6511 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, mono_get_object_from_blob (domain
, type
, blobs
[i
]));
6513 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6514 if (types
[i
] != MONO_TYPE_CLASS
&& !param
->DefaultValueImpl
) {
6515 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6516 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6518 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6524 MONO_OBJECT_SETREF (param
, MarshalAsImpl
, (MonoObject
*)mono_reflection_marshal_from_marshal_spec (domain
, method
->klass
, mspecs
[i
+ 1]));
6526 mono_array_setref (res
, i
, param
);
6533 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
6535 mono_metadata_free_marshal_spec (mspecs
[i
]);
6538 CACHE_OBJECT (MonoArray
*, &(method
->signature
), res
, refclass
);
6542 mono_param_get_objects (MonoDomain
*domain
, MonoMethod
*method
)
6544 return mono_param_get_objects_internal (domain
, method
, NULL
);
6548 * mono_method_body_get_object:
6549 * @domain: an app domain
6552 * Return an System.Reflection.MethodBody object representing the method @method.
6554 MonoReflectionMethodBody
*
6555 mono_method_body_get_object (MonoDomain
*domain
, MonoMethod
*method
)
6557 static MonoClass
*System_Reflection_MethodBody
= NULL
;
6558 static MonoClass
*System_Reflection_LocalVariableInfo
= NULL
;
6559 static MonoClass
*System_Reflection_ExceptionHandlingClause
= NULL
;
6560 MonoReflectionMethodBody
*ret
;
6561 MonoMethodNormal
*mn
;
6562 MonoMethodHeader
*header
;
6563 guint32 method_rva
, local_var_sig_token
;
6565 unsigned char format
, flags
;
6568 if (!System_Reflection_MethodBody
)
6569 System_Reflection_MethodBody
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MethodBody");
6570 if (!System_Reflection_LocalVariableInfo
)
6571 System_Reflection_LocalVariableInfo
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "LocalVariableInfo");
6572 if (!System_Reflection_ExceptionHandlingClause
)
6573 System_Reflection_ExceptionHandlingClause
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ExceptionHandlingClause");
6575 CHECK_OBJECT (MonoReflectionMethodBody
*, method
, NULL
);
6577 if ((method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
6578 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
6579 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
6580 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
))
6582 mn
= (MonoMethodNormal
*)method
;
6583 header
= mono_method_get_header (method
);
6585 /* Obtain local vars signature token */
6586 method_rva
= mono_metadata_decode_row_col (&method
->klass
->image
->tables
[MONO_TABLE_METHOD
], mono_metadata_token_index (method
->token
) - 1, MONO_METHOD_RVA
);
6587 ptr
= mono_image_rva_map (method
->klass
->image
, method_rva
);
6588 flags
= *(const unsigned char *) ptr
;
6589 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
6591 case METHOD_HEADER_TINY_FORMAT
:
6592 case METHOD_HEADER_TINY_FORMAT1
:
6593 local_var_sig_token
= 0;
6595 case METHOD_HEADER_FAT_FORMAT
:
6599 local_var_sig_token
= read32 (ptr
);
6602 g_assert_not_reached ();
6605 ret
= (MonoReflectionMethodBody
*)mono_object_new (domain
, System_Reflection_MethodBody
);
6607 ret
->init_locals
= header
->init_locals
;
6608 ret
->max_stack
= header
->max_stack
;
6609 ret
->local_var_sig_token
= local_var_sig_token
;
6610 MONO_OBJECT_SETREF (ret
, il
, mono_array_new_cached (domain
, mono_defaults
.byte_class
, header
->code_size
));
6611 memcpy (mono_array_addr (ret
->il
, guint8
, 0), header
->code
, header
->code_size
);
6614 MONO_OBJECT_SETREF (ret
, locals
, mono_array_new_cached (domain
, System_Reflection_LocalVariableInfo
, header
->num_locals
));
6615 for (i
= 0; i
< header
->num_locals
; ++i
) {
6616 MonoReflectionLocalVariableInfo
*info
= (MonoReflectionLocalVariableInfo
*)mono_object_new (domain
, System_Reflection_LocalVariableInfo
);
6617 MONO_OBJECT_SETREF (info
, local_type
, mono_type_get_object (domain
, header
->locals
[i
]));
6618 info
->is_pinned
= header
->locals
[i
]->pinned
;
6619 info
->local_index
= i
;
6620 mono_array_setref (ret
->locals
, i
, info
);
6624 MONO_OBJECT_SETREF (ret
, clauses
, mono_array_new_cached (domain
, System_Reflection_ExceptionHandlingClause
, header
->num_clauses
));
6625 for (i
= 0; i
< header
->num_clauses
; ++i
) {
6626 MonoReflectionExceptionHandlingClause
*info
= (MonoReflectionExceptionHandlingClause
*)mono_object_new (domain
, System_Reflection_ExceptionHandlingClause
);
6627 MonoExceptionClause
*clause
= &header
->clauses
[i
];
6629 info
->flags
= clause
->flags
;
6630 info
->try_offset
= clause
->try_offset
;
6631 info
->try_length
= clause
->try_len
;
6632 info
->handler_offset
= clause
->handler_offset
;
6633 info
->handler_length
= clause
->handler_len
;
6634 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)
6635 info
->filter_offset
= clause
->data
.filter_offset
;
6636 else if (clause
->data
.catch_class
)
6637 MONO_OBJECT_SETREF (info
, catch_type
, mono_type_get_object (mono_domain_get (), &clause
->data
.catch_class
->byval_arg
));
6639 mono_array_setref (ret
->clauses
, i
, info
);
6642 CACHE_OBJECT (MonoReflectionMethodBody
*, method
, ret
, NULL
);
6647 * mono_get_dbnull_object:
6648 * @domain: Domain where the object lives
6650 * Returns the System.DBNull.Value singleton object
6652 * Used as the value for ParameterInfo.DefaultValue
6655 mono_get_dbnull_object (MonoDomain
*domain
)
6658 static MonoClassField
*dbnull_value_field
= NULL
;
6660 if (!dbnull_value_field
) {
6661 MonoClass
*dbnull_klass
;
6662 dbnull_klass
= mono_class_from_name (mono_defaults
.corlib
, "System", "DBNull");
6663 mono_class_init (dbnull_klass
);
6664 dbnull_value_field
= mono_class_get_field_from_name (dbnull_klass
, "Value");
6665 g_assert (dbnull_value_field
);
6667 obj
= mono_field_get_value_object (domain
, dbnull_value_field
, NULL
);
6673 get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
)
6675 guint32 param_index
, i
, lastp
, crow
= 0;
6676 guint32 param_cols
[MONO_PARAM_SIZE
], const_cols
[MONO_CONSTANT_SIZE
];
6679 MonoClass
*klass
= method
->klass
;
6680 MonoImage
*image
= klass
->image
;
6681 MonoMethodSignature
*methodsig
= mono_method_signature (method
);
6683 MonoTableInfo
*constt
;
6684 MonoTableInfo
*methodt
;
6685 MonoTableInfo
*paramt
;
6687 if (!methodsig
->param_count
)
6690 mono_class_init (klass
);
6692 if (klass
->image
->dynamic
) {
6693 MonoReflectionMethodAux
*aux
;
6694 if (method
->is_inflated
)
6695 method
= ((MonoMethodInflated
*)method
)->declaring
;
6696 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
6697 if (aux
&& aux
->param_defaults
) {
6698 memcpy (blobs
, &(aux
->param_defaults
[1]), methodsig
->param_count
* sizeof (char*));
6699 memcpy (types
, &(aux
->param_default_types
[1]), methodsig
->param_count
* sizeof (guint32
));
6704 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
6705 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
6706 constt
= &image
->tables
[MONO_TABLE_CONSTANT
];
6708 idx
= mono_method_get_index (method
) - 1;
6709 g_assert (idx
!= -1);
6711 param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
6712 if (idx
+ 1 < methodt
->rows
)
6713 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
6715 lastp
= paramt
->rows
+ 1;
6717 for (i
= param_index
; i
< lastp
; ++i
) {
6720 mono_metadata_decode_row (paramt
, i
- 1, param_cols
, MONO_PARAM_SIZE
);
6721 paramseq
= param_cols
[MONO_PARAM_SEQUENCE
];
6723 if (!param_cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_DEFAULT
)
6726 crow
= mono_metadata_get_constant_index (image
, MONO_TOKEN_PARAM_DEF
| i
, crow
+ 1);
6731 mono_metadata_decode_row (constt
, crow
- 1, const_cols
, MONO_CONSTANT_SIZE
);
6732 blobs
[paramseq
- 1] = (gpointer
) mono_metadata_blob_heap (image
, const_cols
[MONO_CONSTANT_VALUE
]);
6733 types
[paramseq
- 1] = const_cols
[MONO_CONSTANT_TYPE
];
6740 mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
)
6745 MonoType
*basetype
= type
;
6750 klass
= mono_class_from_mono_type (type
);
6751 if (klass
->valuetype
) {
6752 object
= mono_object_new (domain
, klass
);
6753 retval
= ((gchar
*) object
+ sizeof (MonoObject
));
6754 if (klass
->enumtype
)
6755 basetype
= mono_class_enum_basetype (klass
);
6760 if (!mono_get_constant_value_from_blob (domain
, basetype
->type
, blob
, retval
))
6767 assembly_name_to_aname (MonoAssemblyName
*assembly
, char *p
) {
6771 memset (assembly
, 0, sizeof (MonoAssemblyName
));
6773 assembly
->culture
= "";
6774 memset (assembly
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
6776 while (*p
&& (isalnum (*p
) || *p
== '.' || *p
== '-' || *p
== '_' || *p
== '$' || *p
== '@'))
6779 while (g_ascii_isspace (*p
) || *p
== ',') {
6788 if (*p
== 'V' && g_ascii_strncasecmp (p
, "Version=", 8) == 0) {
6790 assembly
->major
= strtoul (p
, &s
, 10);
6791 if (s
== p
|| *s
!= '.')
6794 assembly
->minor
= strtoul (p
, &s
, 10);
6795 if (s
== p
|| *s
!= '.')
6798 assembly
->build
= strtoul (p
, &s
, 10);
6799 if (s
== p
|| *s
!= '.')
6802 assembly
->revision
= strtoul (p
, &s
, 10);
6806 } else if (*p
== 'C' && g_ascii_strncasecmp (p
, "Culture=", 8) == 0) {
6808 if (g_ascii_strncasecmp (p
, "neutral", 7) == 0) {
6809 assembly
->culture
= "";
6812 assembly
->culture
= p
;
6813 while (*p
&& *p
!= ',') {
6817 } else if (*p
== 'P' && g_ascii_strncasecmp (p
, "PublicKeyToken=", 15) == 0) {
6819 if (strncmp (p
, "null", 4) == 0) {
6824 while (*p
&& *p
!= ',') {
6827 len
= (p
- start
+ 1);
6828 if (len
> MONO_PUBLIC_KEY_TOKEN_LENGTH
)
6829 len
= MONO_PUBLIC_KEY_TOKEN_LENGTH
;
6830 g_strlcpy ((char*)assembly
->public_key_token
, start
, len
);
6833 while (*p
&& *p
!= ',')
6837 while (g_ascii_isspace (*p
) || *p
== ',') {
6851 * mono_reflection_parse_type:
6854 * Parse a type name as accepted by the GetType () method and output the info
6855 * extracted in the info structure.
6856 * the name param will be mangled, so, make a copy before passing it to this function.
6857 * The fields in info will be valid until the memory pointed to by name is valid.
6859 * See also mono_type_get_name () below.
6861 * Returns: 0 on parse error.
6864 _mono_reflection_parse_type (char *name
, char **endptr
, gboolean is_recursed
,
6865 MonoTypeNameParse
*info
)
6867 char *start
, *p
, *w
, *temp
, *last_point
, *startn
;
6868 int in_modifiers
= 0;
6869 int isbyref
= 0, rank
, arity
= 0, i
;
6871 start
= p
= w
= name
;
6873 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6874 memset (&info
->assembly
, 0, sizeof (MonoAssemblyName
));
6875 info
->name
= info
->name_space
= NULL
;
6876 info
->nested
= NULL
;
6877 info
->modifiers
= NULL
;
6878 info
->type_arguments
= NULL
;
6880 /* last_point separates the namespace from the name */
6883 while (*p
== ' ') p
++, start
++, w
++, name
++;
6888 *p
= 0; /* NULL terminate the name */
6890 info
->nested
= g_list_append (info
->nested
, startn
);
6891 /* we have parsed the nesting namespace + name */
6895 info
->name_space
= start
;
6897 info
->name
= last_point
+ 1;
6899 info
->name_space
= (char *)"";
6918 i
= strtol (p
, &temp
, 10);
6935 info
->name_space
= start
;
6937 info
->name
= last_point
+ 1;
6939 info
->name_space
= (char *)"";
6946 if (isbyref
) /* only one level allowed by the spec */
6949 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (0));
6953 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-1));
6959 info
->type_arguments
= g_ptr_array_new ();
6960 for (i
= 0; i
< arity
; i
++) {
6961 MonoTypeNameParse
*subinfo
= g_new0 (MonoTypeNameParse
, 1);
6962 gboolean fqname
= FALSE
;
6964 g_ptr_array_add (info
->type_arguments
, subinfo
);
6971 if (!_mono_reflection_parse_type (p
, &p
, TRUE
, subinfo
))
6982 while (*p
&& (*p
!= ']'))
6990 if (g_ascii_isspace (*aname
)) {
6997 !assembly_name_to_aname (&subinfo
->assembly
, aname
))
7001 if (i
+ 1 < arity
) {
7021 else if (*p
== '*') /* '*' means unknown lower bound */
7022 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-2));
7029 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (rank
));
7040 if (g_ascii_isspace (*p
)) {
7047 return 0; /* missing assembly name */
7048 if (!assembly_name_to_aname (&info
->assembly
, p
))
7054 if (info
->assembly
.name
)
7057 // *w = 0; /* terminate class name */
7059 if (!info
->name
|| !*info
->name
)
7063 /* add other consistency checks */
7068 mono_reflection_parse_type (char *name
, MonoTypeNameParse
*info
)
7070 return _mono_reflection_parse_type (name
, NULL
, FALSE
, info
);
7074 _mono_reflection_get_type_from_info (MonoTypeNameParse
*info
, MonoImage
*image
, gboolean ignorecase
)
7076 gboolean type_resolve
= FALSE
;
7078 MonoImage
*rootimage
= image
;
7080 if (info
->assembly
.name
) {
7081 MonoAssembly
*assembly
= mono_assembly_loaded (&info
->assembly
);
7082 if (!assembly
&& image
&& image
->assembly
&& mono_assembly_names_equal (&info
->assembly
, &image
->assembly
->aname
))
7084 * This could happen in the AOT compiler case when the search hook is not
7087 assembly
= image
->assembly
;
7089 /* then we must load the assembly ourselve - see #60439 */
7090 assembly
= mono_assembly_load (&info
->assembly
, NULL
, NULL
);
7094 image
= assembly
->image
;
7095 } else if (!image
) {
7096 image
= mono_defaults
.corlib
;
7099 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7100 if (type
== NULL
&& !info
->assembly
.name
&& image
!= mono_defaults
.corlib
) {
7101 image
= mono_defaults
.corlib
;
7102 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7109 mono_reflection_get_type_internal (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7114 gboolean bounded
= FALSE
;
7117 image
= mono_defaults
.corlib
;
7120 klass
= mono_class_from_name_case (image
, info
->name_space
, info
->name
);
7122 klass
= mono_class_from_name (image
, info
->name_space
, info
->name
);
7125 for (mod
= info
->nested
; mod
; mod
= mod
->next
) {
7126 gpointer iter
= NULL
;
7130 mono_class_init (parent
);
7132 while ((klass
= mono_class_get_nested_types (parent
, &iter
))) {
7134 if (g_strcasecmp (klass
->name
, mod
->data
) == 0)
7137 if (strcmp (klass
->name
, mod
->data
) == 0)
7146 mono_class_init (klass
);
7148 if (info
->type_arguments
) {
7149 MonoType
**type_args
= g_new0 (MonoType
*, info
->type_arguments
->len
);
7150 MonoReflectionType
*the_type
;
7154 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7155 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7157 type_args
[i
] = _mono_reflection_get_type_from_info (subinfo
, rootimage
, ignorecase
);
7158 if (!type_args
[i
]) {
7164 the_type
= mono_type_get_object (mono_domain_get (), &klass
->byval_arg
);
7166 instance
= mono_reflection_bind_generic_parameters (
7167 the_type
, info
->type_arguments
->len
, type_args
);
7173 klass
= mono_class_from_mono_type (instance
);
7176 for (mod
= info
->modifiers
; mod
; mod
= mod
->next
) {
7177 modval
= GPOINTER_TO_UINT (mod
->data
);
7178 if (!modval
) { /* byref: must be last modifier */
7179 return &klass
->this_arg
;
7180 } else if (modval
== -1) {
7181 klass
= mono_ptr_class_get (&klass
->byval_arg
);
7182 } else if (modval
== -2) {
7184 } else { /* array rank */
7185 klass
= mono_bounded_array_class_get (klass
, modval
, bounded
);
7187 mono_class_init (klass
);
7190 return &klass
->byval_arg
;
7194 * mono_reflection_get_type:
7195 * @image: a metadata context
7196 * @info: type description structure
7197 * @ignorecase: flag for case-insensitive string compares
7198 * @type_resolve: whenever type resolve was already tried
7200 * Build a MonoType from the type description in @info.
7205 mono_reflection_get_type (MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
) {
7206 return mono_reflection_get_type_with_rootimage(image
, image
, info
, ignorecase
, type_resolve
);
7210 mono_reflection_get_type_internal_dynamic (MonoImage
*rootimage
, MonoAssembly
*assembly
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7212 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)mono_assembly_get_object (mono_domain_get (), assembly
);
7216 g_assert (assembly
->dynamic
);
7218 /* Enumerate all modules */
7221 if (abuilder
->modules
) {
7222 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
7223 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
7224 type
= mono_reflection_get_type_internal (rootimage
, &mb
->dynamic_image
->image
, info
, ignorecase
);
7230 if (!type
&& abuilder
->loaded_modules
) {
7231 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
7232 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
7233 type
= mono_reflection_get_type_internal (rootimage
, mod
->image
, info
, ignorecase
);
7243 mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
)
7246 MonoReflectionAssembly
*assembly
;
7250 if (image
&& image
->dynamic
)
7251 type
= mono_reflection_get_type_internal_dynamic (rootimage
, image
->assembly
, info
, ignorecase
);
7253 type
= mono_reflection_get_type_internal (rootimage
, image
, info
, ignorecase
);
7256 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7263 *type_resolve
= TRUE
;
7266 /* Reconstruct the type name */
7267 fullName
= g_string_new ("");
7268 if (info
->name_space
&& (info
->name_space
[0] != '\0'))
7269 g_string_printf (fullName
, "%s.%s", info
->name_space
, info
->name
);
7271 g_string_printf (fullName
, info
->name
);
7272 for (mod
= info
->nested
; mod
; mod
= mod
->next
)
7273 g_string_append_printf (fullName
, "+%s", (char*)mod
->data
);
7275 assembly
= mono_domain_try_type_resolve ( mono_domain_get (), fullName
->str
, NULL
);
7277 if (assembly
->assembly
->dynamic
)
7278 type
= mono_reflection_get_type_internal_dynamic (rootimage
, assembly
->assembly
, info
, ignorecase
);
7280 type
= mono_reflection_get_type_internal (rootimage
, assembly
->assembly
->image
,
7283 g_string_free (fullName
, TRUE
);
7288 mono_reflection_free_type_info (MonoTypeNameParse
*info
)
7290 g_list_free (info
->modifiers
);
7291 g_list_free (info
->nested
);
7293 if (info
->type_arguments
) {
7296 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7297 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7299 mono_reflection_free_type_info (subinfo
);
7300 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7304 g_ptr_array_free (info
->type_arguments
, TRUE
);
7309 * mono_reflection_type_from_name:
7311 * @image: a metadata context (can be NULL).
7313 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7314 * it defaults to get the type from @image or, if @image is NULL or loading
7315 * from it fails, uses corlib.
7319 mono_reflection_type_from_name (char *name
, MonoImage
*image
)
7321 MonoType
*type
= NULL
;
7322 MonoTypeNameParse info
;
7325 /* Make a copy since parse_type modifies its argument */
7326 tmp
= g_strdup (name
);
7328 /*g_print ("requested type %s\n", str);*/
7329 if (mono_reflection_parse_type (tmp
, &info
)) {
7330 type
= _mono_reflection_get_type_from_info (&info
, image
, FALSE
);
7334 mono_reflection_free_type_info (&info
);
7339 * mono_reflection_get_token:
7341 * Return the metadata token of OBJ which should be an object
7342 * representing a metadata element.
7345 mono_reflection_get_token (MonoObject
*obj
)
7350 klass
= obj
->vtable
->klass
;
7352 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
7353 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
7355 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7356 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
7357 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
7359 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7360 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
7361 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
7363 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7364 token
= mono_image_create_token (((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
, obj
, FALSE
, TRUE
);
7365 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
7366 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
7367 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
7368 } else if (strcmp (klass
->name
, "MonoType") == 0) {
7369 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
7370 token
= mono_class_from_mono_type (tb
->type
)->type_token
;
7371 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
7372 strcmp (klass
->name
, "MonoMethod") == 0 ||
7373 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
7374 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
7375 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
7376 if (m
->method
->is_inflated
) {
7377 MonoMethodInflated
*inflated
= (MonoMethodInflated
*) m
->method
;
7378 return inflated
->declaring
->token
;
7380 token
= m
->method
->token
;
7382 } else if (strcmp (klass
->name
, "MonoField") == 0) {
7383 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
7385 if (is_field_on_inst (f
->field
)) {
7386 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)f
->field
->parent
->generic_class
;
7387 int field_index
= f
->field
- dgclass
->fields
;
7390 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
7391 obj
= dgclass
->field_objects
[field_index
];
7392 return mono_reflection_get_token (obj
);
7394 token
= mono_class_get_field_token (f
->field
);
7395 } else if (strcmp (klass
->name
, "MonoProperty") == 0) {
7396 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)obj
;
7398 token
= mono_class_get_property_token (p
->property
);
7399 } else if (strcmp (klass
->name
, "MonoEvent") == 0) {
7400 MonoReflectionMonoEvent
*p
= (MonoReflectionMonoEvent
*)obj
;
7402 token
= mono_class_get_event_token (p
->event
);
7403 } else if (strcmp (klass
->name
, "ParameterInfo") == 0) {
7404 MonoReflectionParameter
*p
= (MonoReflectionParameter
*)obj
;
7406 token
= mono_method_get_param_token (((MonoReflectionMethod
*)p
->MemberImpl
)->method
, p
->PositionImpl
);
7407 } else if (strcmp (klass
->name
, "Module") == 0) {
7408 MonoReflectionModule
*m
= (MonoReflectionModule
*)obj
;
7411 } else if (strcmp (klass
->name
, "Assembly") == 0) {
7412 token
= mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1);
7414 gchar
*msg
= g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass
->name_space
, klass
->name
);
7415 MonoException
*ex
= mono_get_exception_not_implemented (msg
);
7417 mono_raise_exception (ex
);
7424 load_cattr_value (MonoImage
*image
, MonoType
*t
, const char *p
, const char **end
)
7426 int slen
, type
= t
->type
;
7427 MonoClass
*tklass
= t
->data
.klass
;
7433 case MONO_TYPE_BOOLEAN
: {
7434 MonoBoolean
*bval
= g_malloc (sizeof (MonoBoolean
));
7439 case MONO_TYPE_CHAR
:
7441 case MONO_TYPE_I2
: {
7442 guint16
*val
= g_malloc (sizeof (guint16
));
7447 #if SIZEOF_VOID_P == 4
7453 case MONO_TYPE_I4
: {
7454 guint32
*val
= g_malloc (sizeof (guint32
));
7459 #if SIZEOF_VOID_P == 8
7460 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
7464 case MONO_TYPE_I8
: {
7465 guint64
*val
= g_malloc (sizeof (guint64
));
7470 case MONO_TYPE_R8
: {
7471 double *val
= g_malloc (sizeof (double));
7476 case MONO_TYPE_VALUETYPE
:
7477 if (t
->data
.klass
->enumtype
) {
7478 type
= mono_class_enum_basetype (t
->data
.klass
)->type
;
7481 g_error ("generic valutype %s not handled in custom attr value decoding", t
->data
.klass
->name
);
7484 case MONO_TYPE_STRING
:
7485 if (*p
== (char)0xFF) {
7489 slen
= mono_metadata_decode_value (p
, &p
);
7491 return mono_string_new_len (mono_domain_get (), p
, slen
);
7492 case MONO_TYPE_CLASS
: {
7495 if (*p
== (char)0xFF) {
7500 slen
= mono_metadata_decode_value (p
, &p
);
7501 n
= g_memdup (p
, slen
+ 1);
7503 t
= mono_reflection_type_from_name (n
, image
);
7505 g_warning ("Cannot load type '%s'", n
);
7509 return mono_type_get_object (mono_domain_get (), t
);
7513 case MONO_TYPE_OBJECT
: {
7516 MonoClass
*subc
= NULL
;
7521 } else if (subt
== 0x0E) {
7522 type
= MONO_TYPE_STRING
;
7524 } else if (subt
== 0x1D) {
7525 MonoType simple_type
= {{0}};
7530 /* See Partition II, Appendix B3 */
7531 etype
= MONO_TYPE_OBJECT
;
7532 type
= MONO_TYPE_SZARRAY
;
7533 simple_type
.type
= etype
;
7534 tklass
= mono_class_from_mono_type (&simple_type
);
7536 } else if (subt
== 0x55) {
7539 slen
= mono_metadata_decode_value (p
, &p
);
7540 n
= g_memdup (p
, slen
+ 1);
7542 t
= mono_reflection_type_from_name (n
, image
);
7544 g_error ("Cannot load type '%s'", n
);
7547 subc
= mono_class_from_mono_type (t
);
7548 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
7549 MonoType simple_type
= {{0}};
7550 simple_type
.type
= subt
;
7551 subc
= mono_class_from_mono_type (&simple_type
);
7553 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
7555 val
= load_cattr_value (image
, &subc
->byval_arg
, p
, end
);
7556 obj
= mono_object_new (mono_domain_get (), subc
);
7557 memcpy ((char*)obj
+ sizeof (MonoObject
), val
, mono_class_value_size (subc
, NULL
));
7561 case MONO_TYPE_SZARRAY
: {
7563 guint32 i
, alen
, basetype
;
7566 if (alen
== 0xffffffff) {
7570 arr
= mono_array_new (mono_domain_get(), tklass
, alen
);
7571 basetype
= tklass
->byval_arg
.type
;
7572 if (basetype
== MONO_TYPE_VALUETYPE
&& tklass
->enumtype
)
7573 basetype
= mono_class_enum_basetype (tklass
)->type
;
7578 case MONO_TYPE_BOOLEAN
:
7579 for (i
= 0; i
< alen
; i
++) {
7580 MonoBoolean val
= *p
++;
7581 mono_array_set (arr
, MonoBoolean
, i
, val
);
7584 case MONO_TYPE_CHAR
:
7587 for (i
= 0; i
< alen
; i
++) {
7588 guint16 val
= read16 (p
);
7589 mono_array_set (arr
, guint16
, i
, val
);
7596 for (i
= 0; i
< alen
; i
++) {
7597 guint32 val
= read32 (p
);
7598 mono_array_set (arr
, guint32
, i
, val
);
7603 for (i
= 0; i
< alen
; i
++) {
7606 mono_array_set (arr
, double, i
, val
);
7612 for (i
= 0; i
< alen
; i
++) {
7613 guint64 val
= read64 (p
);
7614 mono_array_set (arr
, guint64
, i
, val
);
7618 case MONO_TYPE_CLASS
:
7619 case MONO_TYPE_OBJECT
:
7620 case MONO_TYPE_STRING
:
7621 for (i
= 0; i
< alen
; i
++) {
7622 MonoObject
*item
= load_cattr_value (image
, &tklass
->byval_arg
, p
, &p
);
7623 mono_array_setref (arr
, i
, item
);
7627 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
7633 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
7639 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
)
7641 static MonoClass
*klass
;
7642 static MonoMethod
*ctor
;
7644 void *params
[2], *unboxed
;
7647 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeTypedArgument");
7649 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7651 params
[0] = mono_type_get_object (mono_domain_get (), t
);
7653 retval
= mono_object_new (mono_domain_get (), klass
);
7654 unboxed
= mono_object_unbox (retval
);
7655 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7661 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
)
7663 static MonoClass
*klass
;
7664 static MonoMethod
*ctor
;
7666 void *unboxed
, *params
[2];
7669 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeNamedArgument");
7671 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7674 params
[1] = typedarg
;
7675 retval
= mono_object_new (mono_domain_get (), klass
);
7676 unboxed
= mono_object_unbox (retval
);
7677 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7683 type_is_reference (MonoType
*type
)
7685 switch (type
->type
) {
7686 case MONO_TYPE_BOOLEAN
:
7687 case MONO_TYPE_CHAR
:
7700 case MONO_TYPE_VALUETYPE
:
7708 free_param_data (MonoMethodSignature
*sig
, void **params
) {
7710 for (i
= 0; i
< sig
->param_count
; ++i
) {
7711 if (!type_is_reference (sig
->params
[i
]))
7712 g_free (params
[i
]);
7717 * Find the field index in the metadata FieldDef table.
7720 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
7723 for (i
= 0; i
< klass
->field
.count
; ++i
) {
7724 if (field
== &klass
->fields
[i
])
7725 return klass
->field
.first
+ 1 + i
;
7731 * Find the property index in the metadata Property table.
7734 find_property_index (MonoClass
*klass
, MonoProperty
*property
) {
7737 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
7738 if (property
== &klass
->ext
->properties
[i
])
7739 return klass
->ext
->property
.first
+ 1 + i
;
7745 * Find the event index in the metadata Event table.
7748 find_event_index (MonoClass
*klass
, MonoEvent
*event
) {
7751 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
7752 if (event
== &klass
->ext
->events
[i
])
7753 return klass
->ext
->event
.first
+ 1 + i
;
7759 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
7761 const char *p
= (const char*)data
;
7763 guint32 i
, j
, num_named
;
7765 void *params_buf
[32];
7767 MonoMethodSignature
*sig
;
7769 mono_class_init (method
->klass
);
7772 attr
= mono_object_new (mono_domain_get (), method
->klass
);
7773 mono_runtime_invoke (method
, attr
, NULL
, NULL
);
7777 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
7780 /*g_print ("got attr %s\n", method->klass->name);*/
7782 sig
= mono_method_signature (method
);
7783 if (sig
->param_count
< 32)
7784 params
= params_buf
;
7786 /* Allocate using GC so it gets GC tracking */
7787 params
= mono_gc_alloc_fixed (sig
->param_count
* sizeof (void*), NULL
);
7791 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
7792 params
[i
] = load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
7796 attr
= mono_object_new (mono_domain_get (), method
->klass
);
7797 mono_runtime_invoke (method
, attr
, params
, NULL
);
7798 free_param_data (method
->signature
, params
);
7799 num_named
= read16 (named
);
7801 for (j
= 0; j
< num_named
; j
++) {
7803 char *name
, named_type
, data_type
;
7804 named_type
= *named
++;
7805 data_type
= *named
++; /* type of data */
7806 if (data_type
== MONO_TYPE_SZARRAY
)
7807 data_type
= *named
++;
7808 if (data_type
== MONO_TYPE_ENUM
) {
7811 type_len
= mono_metadata_decode_blob_size (named
, &named
);
7812 type_name
= g_malloc (type_len
+ 1);
7813 memcpy (type_name
, named
, type_len
);
7814 type_name
[type_len
] = 0;
7816 /* FIXME: lookup the type and check type consistency */
7819 name_len
= mono_metadata_decode_blob_size (named
, &named
);
7820 name
= g_malloc (name_len
+ 1);
7821 memcpy (name
, named
, name_len
);
7822 name
[name_len
] = 0;
7824 if (named_type
== 0x53) {
7825 MonoClassField
*field
= mono_class_get_field_from_name (mono_object_class (attr
), name
);
7826 void *val
= load_cattr_value (image
, field
->type
, named
, &named
);
7827 mono_field_set_value (attr
, field
, val
);
7828 if (!type_is_reference (field
->type
))
7830 } else if (named_type
== 0x54) {
7833 MonoType
*prop_type
;
7835 prop
= mono_class_get_property_from_name (mono_object_class (attr
), name
);
7836 /* can we have more that 1 arg in a custom attr named property? */
7837 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
7838 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
7839 pparams
[0] = load_cattr_value (image
, prop_type
, named
, &named
);
7840 mono_property_set_value (prop
, attr
, pparams
, NULL
);
7841 if (!type_is_reference (prop_type
))
7842 g_free (pparams
[0]);
7847 if (params
!= params_buf
)
7848 mono_gc_free_fixed (params
);
7854 create_custom_attr_data (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
7856 MonoArray
*typedargs
, *namedargs
;
7857 MonoClass
*attrklass
;
7858 static MonoMethod
*ctor
;
7861 const char *p
= (const char*)data
;
7863 guint32 i
, j
, num_named
;
7866 mono_class_init (method
->klass
);
7869 ctor
= mono_class_get_method_from_name (mono_defaults
.customattribute_data_class
, ".ctor", 3);
7871 domain
= mono_domain_get ();
7873 /* This is for Attributes with no parameters */
7874 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
7875 params
[0] = mono_method_get_object (domain
, method
, NULL
);
7876 params
[1] = params
[2] = NULL
;
7877 mono_runtime_invoke (method
, attr
, params
, NULL
);
7881 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
7884 typedargs
= mono_array_new (domain
, mono_get_object_class (), mono_method_signature (method
)->param_count
);
7888 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
7889 MonoObject
*obj
, *typedarg
;
7892 val
= load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
7893 obj
= type_is_reference (mono_method_signature (method
)->params
[i
]) ?
7894 val
: mono_value_box (domain
, mono_class_from_mono_type (mono_method_signature (method
)->params
[i
]), val
);
7895 typedarg
= create_cattr_typed_arg (mono_method_signature (method
)->params
[i
], obj
);
7896 mono_array_setref (typedargs
, i
, typedarg
);
7898 if (!type_is_reference (mono_method_signature (method
)->params
[i
]))
7903 num_named
= read16 (named
);
7904 namedargs
= mono_array_new (domain
, mono_get_object_class (), num_named
);
7906 attrklass
= method
->klass
;
7907 for (j
= 0; j
< num_named
; j
++) {
7909 char *name
, named_type
, data_type
;
7910 named_type
= *named
++;
7911 data_type
= *named
++; /* type of data */
7912 if (data_type
== MONO_TYPE_SZARRAY
)
7913 data_type
= *named
++;
7914 if (data_type
== MONO_TYPE_ENUM
) {
7917 type_len
= mono_metadata_decode_blob_size (named
, &named
);
7918 type_name
= g_malloc (type_len
+ 1);
7919 memcpy (type_name
, named
, type_len
);
7920 type_name
[type_len
] = 0;
7922 /* FIXME: lookup the type and check type consistency */
7925 name_len
= mono_metadata_decode_blob_size (named
, &named
);
7926 name
= g_malloc (name_len
+ 1);
7927 memcpy (name
, named
, name_len
);
7928 name
[name_len
] = 0;
7930 if (named_type
== 0x53) {
7931 MonoObject
*obj
, *typedarg
, *namedarg
;
7932 MonoClassField
*field
= mono_class_get_field_from_name (attrklass
, name
);
7933 void *minfo
, *val
= load_cattr_value (image
, field
->type
, named
, &named
);
7935 minfo
= mono_field_get_object (domain
, NULL
, field
);
7936 obj
= type_is_reference (field
->type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (field
->type
), val
);
7937 typedarg
= create_cattr_typed_arg (field
->type
, obj
);
7938 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
7939 mono_array_setref (namedargs
, j
, namedarg
);
7940 if (!type_is_reference (field
->type
))
7942 } else if (named_type
== 0x54) {
7943 MonoObject
*obj
, *typedarg
, *namedarg
;
7944 MonoType
*prop_type
;
7946 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
7948 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
7949 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
7950 minfo
= mono_property_get_object (domain
, NULL
, prop
);
7951 val
= load_cattr_value (image
, prop_type
, named
, &named
);
7952 obj
= type_is_reference (prop_type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (prop_type
), val
);
7953 typedarg
= create_cattr_typed_arg (prop_type
, obj
);
7954 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
7955 mono_array_setref (namedargs
, j
, namedarg
);
7956 if (!type_is_reference (prop_type
))
7961 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
7962 params
[0] = mono_method_get_object (domain
, method
, NULL
);
7963 params
[1] = typedargs
;
7964 params
[2] = namedargs
;
7965 mono_runtime_invoke (ctor
, attr
, params
, NULL
);
7970 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
7976 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, cinfo
->num_attrs
);
7977 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7978 if (!cinfo
->attrs
[i
].ctor
)
7979 /* The cattr type is not finished yet */
7980 /* We should include the type name but cinfo doesn't contain it */
7981 mono_raise_exception (mono_get_exception_type_load (NULL
, NULL
));
7982 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
7983 mono_array_setref (result
, i
, attr
);
7989 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
)
7996 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7997 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
))
8001 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, n
);
8003 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8004 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
)) {
8005 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
8006 mono_array_setref (result
, n
, attr
);
8014 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
)
8020 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, cinfo
->num_attrs
);
8021 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
8022 attr
= create_custom_attr_data (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
8023 mono_array_setref (result
, i
, attr
);
8029 * mono_custom_attrs_from_index:
8031 * Returns: NULL if no attributes are found or if a loading error occurs.
8034 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
8036 guint32 mtoken
, i
, len
;
8037 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
8039 MonoCustomAttrInfo
*ainfo
;
8040 GList
*tmp
, *list
= NULL
;
8043 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
8045 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
8049 while (i
< ca
->rows
) {
8050 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
8052 list
= g_list_prepend (list
, GUINT_TO_POINTER (i
));
8055 len
= g_list_length (list
);
8058 ainfo
= g_malloc0 (sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (len
- MONO_ZERO_LEN_ARRAY
));
8059 ainfo
->num_attrs
= len
;
8060 ainfo
->image
= image
;
8061 for (i
= 0, tmp
= list
; i
< len
; ++i
, tmp
= tmp
->next
) {
8062 mono_metadata_decode_row (ca
, GPOINTER_TO_UINT (tmp
->data
), cols
, MONO_CUSTOM_ATTR_SIZE
);
8063 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
8064 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
8065 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
8066 mtoken
|= MONO_TOKEN_METHOD_DEF
;
8068 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
8069 mtoken
|= MONO_TOKEN_MEMBER_REF
;
8072 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
8075 ainfo
->attrs
[i
].ctor
= mono_get_method (image
, mtoken
, NULL
);
8076 if (!ainfo
->attrs
[i
].ctor
) {
8077 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image
->name
, mtoken
);
8082 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
8083 ainfo
->attrs
[i
].data_size
= mono_metadata_decode_value (data
, &data
);
8084 ainfo
->attrs
[i
].data
= (guchar
*)data
;
8092 mono_custom_attrs_from_method (MonoMethod
*method
)
8097 * An instantiated method has the same cattrs as the generic method definition.
8099 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8100 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8102 if (method
->is_inflated
)
8103 method
= ((MonoMethodInflated
*) method
)->declaring
;
8105 if (method
->dynamic
|| method
->klass
->image
->dynamic
)
8106 return lookup_custom_attr (method
->klass
->image
, method
);
8109 /* Synthetic methods */
8112 idx
= mono_method_get_index (method
);
8113 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8114 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
8115 return mono_custom_attrs_from_index (method
->klass
->image
, idx
);
8119 mono_custom_attrs_from_class (MonoClass
*klass
)
8123 if (klass
->generic_class
)
8124 klass
= klass
->generic_class
->container_class
;
8126 if (klass
->image
->dynamic
)
8127 return lookup_custom_attr (klass
->image
, klass
);
8129 if (klass
->byval_arg
.type
== MONO_TYPE_VAR
|| klass
->byval_arg
.type
== MONO_TYPE_MVAR
) {
8130 idx
= mono_metadata_token_index (klass
->sizes
.generic_param_token
);
8131 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8132 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
8134 idx
= mono_metadata_token_index (klass
->type_token
);
8135 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8136 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
8138 return mono_custom_attrs_from_index (klass
->image
, idx
);
8142 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
8146 if (assembly
->image
->dynamic
)
8147 return lookup_custom_attr (assembly
->image
, assembly
);
8148 idx
= 1; /* there is only one assembly */
8149 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8150 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
8151 return mono_custom_attrs_from_index (assembly
->image
, idx
);
8154 static MonoCustomAttrInfo
*
8155 mono_custom_attrs_from_module (MonoImage
*image
)
8160 return lookup_custom_attr (image
, image
);
8161 idx
= 1; /* there is only one module */
8162 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8163 idx
|= MONO_CUSTOM_ATTR_MODULE
;
8164 return mono_custom_attrs_from_index (image
, idx
);
8168 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
8172 if (klass
->image
->dynamic
) {
8173 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
8174 return lookup_custom_attr (klass
->image
, property
);
8176 idx
= find_property_index (klass
, property
);
8177 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8178 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
8179 return mono_custom_attrs_from_index (klass
->image
, idx
);
8183 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
8187 if (klass
->image
->dynamic
) {
8188 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
8189 return lookup_custom_attr (klass
->image
, event
);
8191 idx
= find_event_index (klass
, event
);
8192 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8193 idx
|= MONO_CUSTOM_ATTR_EVENT
;
8194 return mono_custom_attrs_from_index (klass
->image
, idx
);
8198 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
8201 if (klass
->image
->dynamic
) {
8202 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
8203 return lookup_custom_attr (klass
->image
, field
);
8205 idx
= find_field_index (klass
, field
);
8206 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8207 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
8208 return mono_custom_attrs_from_index (klass
->image
, idx
);
8212 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
8215 guint32 i
, idx
, method_index
;
8216 guint32 param_list
, param_last
, param_pos
, found
;
8218 MonoReflectionMethodAux
*aux
;
8221 * An instantiated method has the same cattrs as the generic method definition.
8223 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8224 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8226 if (method
->is_inflated
)
8227 method
= ((MonoMethodInflated
*) method
)->declaring
;
8229 if (method
->klass
->image
->dynamic
) {
8230 MonoCustomAttrInfo
*res
, *ainfo
;
8233 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
8234 if (!aux
|| !aux
->param_cattr
)
8237 /* Need to copy since it will be freed later */
8238 ainfo
= aux
->param_cattr
[param
];
8239 size
= sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (ainfo
->num_attrs
- MONO_ZERO_LEN_ARRAY
);
8240 res
= g_malloc0 (size
);
8241 memcpy (res
, ainfo
, size
);
8245 image
= method
->klass
->image
;
8246 method_index
= mono_method_get_index (method
);
8247 ca
= &image
->tables
[MONO_TABLE_METHOD
];
8249 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
8250 if (method_index
== ca
->rows
) {
8251 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8252 param_last
= ca
->rows
+ 1;
8254 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
8255 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8258 for (i
= param_list
; i
< param_last
; ++i
) {
8259 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
8260 if (param_pos
== param
) {
8268 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8269 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
8270 return mono_custom_attrs_from_index (image
, idx
);
8274 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8278 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8279 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8280 if (mono_class_has_parent (klass
, attr_klass
) || (MONO_CLASS_IS_INTERFACE (attr_klass
) && mono_class_is_assignable_from (attr_klass
, klass
)))
8287 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8294 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8295 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8296 if (mono_class_has_parent (klass
, attr_klass
)) {
8301 if (attr_index
== -1)
8304 attrs
= mono_custom_attrs_construct (ainfo
);
8306 return mono_array_get (attrs
, MonoObject
*, attr_index
);
8312 * mono_reflection_get_custom_attrs_info:
8313 * @obj: a reflection object handle
8315 * Return the custom attribute info for attributes defined for the
8316 * reflection handle @obj. The objects.
8318 * FIXME this function leaks like a sieve for SRE objects.
8321 mono_reflection_get_custom_attrs_info (MonoObject
*obj
)
8324 MonoCustomAttrInfo
*cinfo
= NULL
;
8326 klass
= obj
->vtable
->klass
;
8327 if (klass
== mono_defaults
.monotype_class
) {
8328 MonoReflectionType
*rtype
= (MonoReflectionType
*)obj
;
8329 klass
= mono_class_from_mono_type (rtype
->type
);
8330 cinfo
= mono_custom_attrs_from_class (klass
);
8331 } else if (strcmp ("Assembly", klass
->name
) == 0) {
8332 MonoReflectionAssembly
*rassembly
= (MonoReflectionAssembly
*)obj
;
8333 cinfo
= mono_custom_attrs_from_assembly (rassembly
->assembly
);
8334 } else if (strcmp ("Module", klass
->name
) == 0) {
8335 MonoReflectionModule
*module
= (MonoReflectionModule
*)obj
;
8336 cinfo
= mono_custom_attrs_from_module (module
->image
);
8337 } else if (strcmp ("MonoProperty", klass
->name
) == 0) {
8338 MonoReflectionProperty
*rprop
= (MonoReflectionProperty
*)obj
;
8339 cinfo
= mono_custom_attrs_from_property (rprop
->property
->parent
, rprop
->property
);
8340 } else if (strcmp ("MonoEvent", klass
->name
) == 0) {
8341 MonoReflectionMonoEvent
*revent
= (MonoReflectionMonoEvent
*)obj
;
8342 cinfo
= mono_custom_attrs_from_event (revent
->event
->parent
, revent
->event
);
8343 } else if (strcmp ("MonoField", klass
->name
) == 0) {
8344 MonoReflectionField
*rfield
= (MonoReflectionField
*)obj
;
8345 cinfo
= mono_custom_attrs_from_field (rfield
->field
->parent
, rfield
->field
);
8346 } else if ((strcmp ("MonoMethod", klass
->name
) == 0) || (strcmp ("MonoCMethod", klass
->name
) == 0)) {
8347 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8348 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8349 } else if ((strcmp ("MonoGenericMethod", klass
->name
) == 0) || (strcmp ("MonoGenericCMethod", klass
->name
) == 0)) {
8350 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8351 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8352 } else if (strcmp ("ParameterInfo", klass
->name
) == 0) {
8353 MonoReflectionParameter
*param
= (MonoReflectionParameter
*)obj
;
8354 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
8355 cinfo
= mono_custom_attrs_from_param (rmethod
->method
, param
->PositionImpl
+ 1);
8356 } else if (strcmp ("AssemblyBuilder", klass
->name
) == 0) {
8357 MonoReflectionAssemblyBuilder
*assemblyb
= (MonoReflectionAssemblyBuilder
*)obj
;
8358 cinfo
= mono_custom_attrs_from_builders (NULL
, assemblyb
->assembly
.assembly
->image
, assemblyb
->cattrs
);
8359 } else if (strcmp ("TypeBuilder", klass
->name
) == 0) {
8360 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
8361 cinfo
= mono_custom_attrs_from_builders (NULL
, &tb
->module
->dynamic_image
->image
, tb
->cattrs
);
8362 } else if (strcmp ("ModuleBuilder", klass
->name
) == 0) {
8363 MonoReflectionModuleBuilder
*mb
= (MonoReflectionModuleBuilder
*)obj
;
8364 cinfo
= mono_custom_attrs_from_builders (NULL
, &mb
->dynamic_image
->image
, mb
->cattrs
);
8365 } else if (strcmp ("ConstructorBuilder", klass
->name
) == 0) {
8366 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
8367 cinfo
= mono_custom_attrs_from_builders (NULL
, cb
->mhandle
->klass
->image
, cb
->cattrs
);
8368 } else if (strcmp ("MethodBuilder", klass
->name
) == 0) {
8369 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
8370 cinfo
= mono_custom_attrs_from_builders (NULL
, mb
->mhandle
->klass
->image
, mb
->cattrs
);
8371 } else if (strcmp ("FieldBuilder", klass
->name
) == 0) {
8372 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
8373 cinfo
= mono_custom_attrs_from_builders (NULL
, &((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
->image
, fb
->cattrs
);
8374 } else if (strcmp ("MonoGenericClass", klass
->name
) == 0) {
8375 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)obj
;
8376 cinfo
= mono_reflection_get_custom_attrs_info ((MonoObject
*)gclass
->generic_type
);
8377 } else { /* handle other types here... */
8378 g_error ("get custom attrs not yet supported for %s", klass
->name
);
8385 * mono_reflection_get_custom_attrs_by_type:
8386 * @obj: a reflection object handle
8388 * Return an array with all the custom attributes defined of the
8389 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8390 * of that type are returned. The objects are fully build. Return NULL if a loading error
8394 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj
, MonoClass
*attr_klass
)
8397 MonoCustomAttrInfo
*cinfo
;
8399 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8402 result
= mono_custom_attrs_construct_by_type (cinfo
, attr_klass
);
8404 result
= mono_custom_attrs_construct (cinfo
);
8406 mono_custom_attrs_free (cinfo
);
8408 if (mono_loader_get_last_error ())
8410 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, 0);
8417 * mono_reflection_get_custom_attrs:
8418 * @obj: a reflection object handle
8420 * Return an array with all the custom attributes defined of the
8421 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8425 mono_reflection_get_custom_attrs (MonoObject
*obj
)
8427 return mono_reflection_get_custom_attrs_by_type (obj
, NULL
);
8431 * mono_reflection_get_custom_attrs_data:
8432 * @obj: a reflection obj handle
8434 * Returns an array of System.Reflection.CustomAttributeData,
8435 * which include information about attributes reflected on
8436 * types loaded using the Reflection Only methods
8439 mono_reflection_get_custom_attrs_data (MonoObject
*obj
)
8442 MonoCustomAttrInfo
*cinfo
;
8444 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8446 result
= mono_custom_attrs_data_construct (cinfo
);
8448 mono_custom_attrs_free (cinfo
);
8450 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, 0);
8455 static MonoReflectionType
*
8456 mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
)
8458 MonoMethod
*method_get_underlying_system_type
;
8460 method_get_underlying_system_type
= mono_object_get_virtual_method ((MonoObject
*) t
,
8461 mono_class_get_method_from_name (mono_object_class (t
),
8462 "get_UnderlyingSystemType",
8464 return (MonoReflectionType
*) mono_runtime_invoke (method_get_underlying_system_type
, t
, NULL
, NULL
);
8467 #ifndef DISABLE_REFLECTION_EMIT
8469 mono_reflection_type_get_handle (MonoReflectionType
* t
)
8474 t
= mono_reflection_type_get_underlying_system_type (t
);
8482 * LOCKING: Assumes the loader lock is held.
8484 static MonoMethodSignature
*
8485 parameters_to_signature (MonoImage
*image
, MonoArray
*parameters
) {
8486 MonoMethodSignature
*sig
;
8489 count
= parameters
? mono_array_length (parameters
): 0;
8491 sig
= image_g_malloc0 (image
, sizeof (MonoMethodSignature
) + sizeof (MonoType
*) * count
);
8492 sig
->param_count
= count
;
8493 sig
->sentinelpos
= -1; /* FIXME */
8494 for (i
= 0; i
< count
; ++i
) {
8495 MonoReflectionType
*pt
= mono_type_array_get (parameters
, i
);
8496 sig
->params
[i
] = mono_reflection_type_get_handle (pt
);
8502 * LOCKING: Assumes the loader lock is held.
8504 static MonoMethodSignature
*
8505 ctor_builder_to_signature (MonoImage
*image
, MonoReflectionCtorBuilder
*ctor
) {
8506 MonoMethodSignature
*sig
;
8508 sig
= parameters_to_signature (image
, ctor
->parameters
);
8509 sig
->hasthis
= ctor
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8510 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
8515 * LOCKING: Assumes the loader lock is held.
8517 static MonoMethodSignature
*
8518 method_builder_to_signature (MonoImage
*image
, MonoReflectionMethodBuilder
*method
) {
8519 MonoMethodSignature
*sig
;
8521 sig
= parameters_to_signature (image
, method
->parameters
);
8522 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8523 sig
->ret
= method
->rtype
? monotype_cast (method
->rtype
)->type
: &mono_defaults
.void_class
->byval_arg
;
8524 sig
->generic_param_count
= method
->generic_params
? mono_array_length (method
->generic_params
) : 0;
8528 static MonoMethodSignature
*
8529 dynamic_method_to_signature (MonoReflectionDynamicMethod
*method
) {
8530 MonoMethodSignature
*sig
;
8532 sig
= parameters_to_signature (NULL
, method
->parameters
);
8533 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8534 sig
->ret
= method
->rtype
? method
->rtype
->type
: &mono_defaults
.void_class
->byval_arg
;
8535 sig
->generic_param_count
= 0;
8540 get_prop_name_and_type (MonoObject
*prop
, char **name
, MonoType
**type
)
8542 MonoClass
*klass
= mono_object_class (prop
);
8543 if (strcmp (klass
->name
, "PropertyBuilder") == 0) {
8544 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*)prop
;
8545 *name
= mono_string_to_utf8 (pb
->name
);
8546 *type
= monotype_cast (pb
->type
)->type
;
8548 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)prop
;
8549 *name
= g_strdup (p
->property
->name
);
8550 if (p
->property
->get
)
8551 *type
= mono_method_signature (p
->property
->get
)->ret
;
8553 *type
= mono_method_signature (p
->property
->set
)->params
[mono_method_signature (p
->property
->set
)->param_count
- 1];
8558 get_field_name_and_type (MonoObject
*field
, char **name
, MonoType
**type
)
8560 MonoClass
*klass
= mono_object_class (field
);
8561 if (strcmp (klass
->name
, "FieldBuilder") == 0) {
8562 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)field
;
8563 *name
= mono_string_to_utf8 (fb
->name
);
8564 *type
= monotype_cast (fb
->type
)->type
;
8566 MonoReflectionField
*f
= (MonoReflectionField
*)field
;
8567 *name
= g_strdup (mono_field_get_name (f
->field
));
8568 *type
= f
->field
->type
;
8571 #endif /* !DISABLE_REFLECTION_EMIT */
8574 * Encode a value in a custom attribute stream of bytes.
8575 * The value to encode is either supplied as an object in argument val
8576 * (valuetypes are boxed), or as a pointer to the data in the
8578 * @type represents the type of the value
8579 * @buffer is the start of the buffer
8580 * @p the current position in the buffer
8581 * @buflen contains the size of the buffer and is used to return the new buffer size
8582 * if this needs to be realloced.
8583 * @retbuffer and @retp return the start and the position of the buffer
8586 encode_cattr_value (MonoAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, MonoObject
*arg
, char *argval
)
8588 MonoTypeEnum simple_type
;
8590 if ((p
-buffer
) + 10 >= *buflen
) {
8593 newbuf
= g_realloc (buffer
, *buflen
);
8594 p
= newbuf
+ (p
-buffer
);
8598 argval
= ((char*)arg
+ sizeof (MonoObject
));
8599 simple_type
= type
->type
;
8601 switch (simple_type
) {
8602 case MONO_TYPE_BOOLEAN
:
8607 case MONO_TYPE_CHAR
:
8610 swap_with_size (p
, argval
, 2, 1);
8616 swap_with_size (p
, argval
, 4, 1);
8620 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8630 swap_with_size (p
, argval
, 8, 1);
8636 swap_with_size (p
, argval
, 8, 1);
8639 case MONO_TYPE_VALUETYPE
:
8640 if (type
->data
.klass
->enumtype
) {
8641 simple_type
= mono_class_enum_basetype (type
->data
.klass
)->type
;
8644 g_warning ("generic valutype %s not handled in custom attr value decoding", type
->data
.klass
->name
);
8647 case MONO_TYPE_STRING
: {
8654 str
= mono_string_to_utf8 ((MonoString
*)arg
);
8655 slen
= strlen (str
);
8656 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8660 newbuf
= g_realloc (buffer
, *buflen
);
8661 p
= newbuf
+ (p
-buffer
);
8664 mono_metadata_encode_value (slen
, p
, &p
);
8665 memcpy (p
, str
, slen
);
8670 case MONO_TYPE_CLASS
: {
8678 k
= mono_object_class (arg
);
8679 if (!mono_object_isinst (arg
, mono_defaults
.monotype_class
) &&
8680 (strcmp (k
->name
, "TypeBuilder") || strcmp (k
->name_space
, "System.Reflection.Emit"))) {
8681 MonoReflectionType
* rt
= mono_reflection_type_get_underlying_system_type ((MonoReflectionType
*) arg
);
8684 if (rt
&& (rtc
= mono_object_class (rt
)) &&
8685 (mono_object_isinst ((MonoObject
*) rt
, mono_defaults
.monotype_class
) ||
8686 !strcmp (rtc
->name
, "TypeBuilder") || !strcmp (rtc
->name_space
, "System.Reflection.Emit"))) {
8687 arg
= (MonoObject
*) rt
;
8690 g_error ("Only System.Type allowed, not %s.%s", k
->name_space
, k
->name
);
8693 str
= type_get_qualified_name (((MonoReflectionType
*)arg
)->type
, 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
);
8709 case MONO_TYPE_SZARRAY
: {
8711 MonoClass
*eclass
, *arg_eclass
;
8714 *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff;
8717 len
= mono_array_length ((MonoArray
*)arg
);
8719 *p
++ = (len
>> 8) & 0xff;
8720 *p
++ = (len
>> 16) & 0xff;
8721 *p
++ = (len
>> 24) & 0xff;
8723 *retbuffer
= buffer
;
8724 eclass
= type
->data
.klass
;
8725 arg_eclass
= mono_object_class (arg
)->element_class
;
8728 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8729 eclass
= mono_defaults
.object_class
;
8731 if (eclass
== mono_defaults
.object_class
&& arg_eclass
->valuetype
) {
8732 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
8733 int elsize
= mono_class_array_element_size (arg_eclass
);
8734 for (i
= 0; i
< len
; ++i
) {
8735 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &arg_eclass
->byval_arg
, NULL
, elptr
);
8738 } else if (eclass
->valuetype
&& arg_eclass
->valuetype
) {
8739 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
8740 int elsize
= mono_class_array_element_size (eclass
);
8741 for (i
= 0; i
< len
; ++i
) {
8742 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, NULL
, elptr
);
8746 for (i
= 0; i
< len
; ++i
) {
8747 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, mono_array_get ((MonoArray
*)arg
, MonoObject
*, i
), NULL
);
8752 case MONO_TYPE_OBJECT
: {
8758 * The parameter type is 'object' but the type of the actual
8759 * argument is not. So we have to add type information to the blob
8760 * too. This is completely undocumented in the spec.
8764 *p
++ = MONO_TYPE_STRING
; // It's same hack as MS uses
8769 klass
= mono_object_class (arg
);
8771 if (mono_object_isinst (arg
, mono_defaults
.systemtype_class
)) {
8774 } else if (klass
->enumtype
) {
8776 } else if (klass
== mono_defaults
.string_class
) {
8777 simple_type
= MONO_TYPE_STRING
;
8780 } else if (klass
->rank
== 1) {
8782 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_OBJECT
)
8783 /* See Partition II, Appendix B3 */
8786 *p
++ = klass
->element_class
->byval_arg
.type
;
8787 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &klass
->byval_arg
, arg
, NULL
);
8789 } else if (klass
->byval_arg
.type
>= MONO_TYPE_BOOLEAN
&& klass
->byval_arg
.type
<= MONO_TYPE_R8
) {
8790 *p
++ = simple_type
= klass
->byval_arg
.type
;
8793 g_error ("unhandled type in custom attr");
8795 str
= type_get_qualified_name (mono_class_get_type(klass
), NULL
);
8796 slen
= strlen (str
);
8797 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8801 newbuf
= g_realloc (buffer
, *buflen
);
8802 p
= newbuf
+ (p
-buffer
);
8805 mono_metadata_encode_value (slen
, p
, &p
);
8806 memcpy (p
, str
, slen
);
8809 simple_type
= mono_class_enum_basetype (klass
)->type
;
8813 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type
);
8816 *retbuffer
= buffer
;
8820 encode_field_or_prop_type (MonoType
*type
, char *p
, char **retp
)
8822 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
8823 char *str
= type_get_qualified_name (type
, NULL
);
8824 int slen
= strlen (str
);
8828 * This seems to be optional...
8831 mono_metadata_encode_value (slen
, p
, &p
);
8832 memcpy (p
, str
, slen
);
8835 } else if (type
->type
== MONO_TYPE_OBJECT
) {
8837 } else if (type
->type
== MONO_TYPE_CLASS
) {
8838 /* it should be a type: encode_cattr_value () has the check */
8841 mono_metadata_encode_value (type
->type
, p
, &p
);
8842 if (type
->type
== MONO_TYPE_SZARRAY
)
8843 /* See the examples in Partition VI, Annex B */
8844 encode_field_or_prop_type (&type
->data
.klass
->byval_arg
, p
, &p
);
8850 #ifndef DISABLE_REFLECTION_EMIT
8852 encode_named_val (MonoReflectionAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, char *name
, MonoObject
*value
)
8855 /* Preallocate a large enough buffer */
8856 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
8857 char *str
= type_get_qualified_name (type
, NULL
);
8860 } else if (type
->type
== MONO_TYPE_SZARRAY
&& type
->data
.klass
->enumtype
) {
8861 char *str
= type_get_qualified_name (&type
->data
.klass
->byval_arg
, NULL
);
8867 len
+= strlen (name
);
8869 if ((p
-buffer
) + 20 + len
>= *buflen
) {
8873 newbuf
= g_realloc (buffer
, *buflen
);
8874 p
= newbuf
+ (p
-buffer
);
8878 encode_field_or_prop_type (type
, p
, &p
);
8880 len
= strlen (name
);
8881 mono_metadata_encode_value (len
, p
, &p
);
8882 memcpy (p
, name
, len
);
8884 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, buflen
, type
, value
, NULL
);
8886 *retbuffer
= buffer
;
8890 * mono_reflection_get_custom_attrs_blob:
8891 * @ctor: custom attribute constructor
8892 * @ctorArgs: arguments o the constructor
8898 * Creates the blob of data that needs to be saved in the metadata and that represents
8899 * the custom attributed described by @ctor, @ctorArgs etc.
8900 * Returns: a Byte array representing the blob of data.
8903 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
8906 MonoMethodSignature
*sig
;
8911 MONO_ARCH_SAVE_REGS
;
8913 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
8914 /* sig is freed later so allocate it in the heap */
8915 sig
= ctor_builder_to_signature (NULL
, (MonoReflectionCtorBuilder
*)ctor
);
8917 sig
= mono_method_signature (((MonoReflectionMethod
*)ctor
)->method
);
8920 g_assert (mono_array_length (ctorArgs
) == sig
->param_count
);
8922 p
= buffer
= g_malloc (buflen
);
8923 /* write the prolog */
8926 for (i
= 0; i
< sig
->param_count
; ++i
) {
8927 arg
= mono_array_get (ctorArgs
, MonoObject
*, i
);
8928 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, &buflen
, sig
->params
[i
], arg
, NULL
);
8932 i
+= mono_array_length (properties
);
8934 i
+= mono_array_length (fields
);
8936 *p
++ = (i
>> 8) & 0xff;
8939 for (i
= 0; i
< mono_array_length (properties
); ++i
) {
8943 prop
= mono_array_get (properties
, gpointer
, i
);
8944 get_prop_name_and_type (prop
, &pname
, &ptype
);
8945 *p
++ = 0x54; /* PROPERTY signature */
8946 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ptype
, pname
, (MonoObject
*)mono_array_get (propValues
, gpointer
, i
));
8953 for (i
= 0; i
< mono_array_length (fields
); ++i
) {
8957 field
= mono_array_get (fields
, gpointer
, i
);
8958 get_field_name_and_type (field
, &fname
, &ftype
);
8959 *p
++ = 0x53; /* FIELD signature */
8960 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ftype
, fname
, (MonoObject
*)mono_array_get (fieldValues
, gpointer
, i
));
8965 g_assert (p
- buffer
<= buflen
);
8966 buflen
= p
- buffer
;
8967 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
8968 p
= mono_array_addr (result
, char, 0);
8969 memcpy (p
, buffer
, buflen
);
8971 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod"))
8977 * mono_reflection_setup_internal_class:
8978 * @tb: a TypeBuilder object
8980 * Creates a MonoClass that represents the TypeBuilder.
8981 * This is a trick that lets us simplify a lot of reflection code
8982 * (and will allow us to support Build and Run assemblies easier).
8985 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
8987 MonoClass
*klass
, *parent
;
8989 MONO_ARCH_SAVE_REGS
;
8991 CHECK_MONOTYPE (tb
->parent
);
8993 mono_loader_lock ();
8996 /* check so we can compile corlib correctly */
8997 if (strcmp (mono_object_class (tb
->parent
)->name
, "TypeBuilder") == 0) {
8998 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8999 parent
= monotype_cast (tb
->parent
)->type
->data
.klass
;
9001 parent
= mono_class_from_mono_type (monotype_cast (tb
->parent
)->type
);
9007 /* the type has already being created: it means we just have to change the parent */
9008 if (tb
->type
.type
) {
9009 klass
= mono_class_from_mono_type (tb
->type
.type
);
9010 klass
->parent
= NULL
;
9011 /* fool mono_class_setup_parent */
9012 klass
->supertypes
= NULL
;
9013 mono_class_setup_parent (klass
, parent
);
9014 mono_class_setup_mono_type (klass
);
9015 mono_loader_unlock ();
9019 klass
= mono_image_alloc0 (&tb
->module
->dynamic_image
->image
, sizeof (MonoClass
));
9021 klass
->image
= &tb
->module
->dynamic_image
->image
;
9023 klass
->inited
= 1; /* we lie to the runtime */
9024 klass
->name
= mono_string_to_utf8_image (klass
->image
, tb
->name
);
9025 klass
->name_space
= mono_string_to_utf8_image (klass
->image
, tb
->nspace
);
9026 klass
->type_token
= MONO_TOKEN_TYPE_DEF
| tb
->table_idx
;
9027 klass
->flags
= tb
->attrs
;
9029 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
9031 klass
->element_class
= klass
;
9033 MOVING_GC_REGISTER (&klass
->reflection_info
);
9034 klass
->reflection_info
= tb
;
9036 /* Put into cache so mono_class_get () will find it */
9037 mono_image_add_to_name_cache (klass
->image
, klass
->name_space
, klass
->name
, tb
->table_idx
);
9039 mono_g_hash_table_insert (tb
->module
->dynamic_image
->tokens
,
9040 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF
| tb
->table_idx
), tb
);
9042 if (parent
!= NULL
) {
9043 mono_class_setup_parent (klass
, parent
);
9044 } else if (strcmp (klass
->name
, "Object") == 0 && strcmp (klass
->name_space
, "System") == 0) {
9045 const char *old_n
= klass
->name
;
9046 /* trick to get relative numbering right when compiling corlib */
9047 klass
->name
= "BuildingObject";
9048 mono_class_setup_parent (klass
, mono_defaults
.object_class
);
9049 klass
->name
= old_n
;
9052 if ((!strcmp (klass
->name
, "ValueType") && !strcmp (klass
->name_space
, "System")) ||
9053 (!strcmp (klass
->name
, "Object") && !strcmp (klass
->name_space
, "System")) ||
9054 (!strcmp (klass
->name
, "Enum") && !strcmp (klass
->name_space
, "System"))) {
9055 klass
->instance_size
= sizeof (MonoObject
);
9056 klass
->size_inited
= 1;
9057 mono_class_setup_vtable_general (klass
, NULL
, 0);
9060 mono_class_setup_mono_type (klass
);
9062 mono_class_setup_supertypes (klass
);
9065 * FIXME: handle interfaces.
9068 tb
->type
.type
= &klass
->byval_arg
;
9070 if (tb
->nesting_type
) {
9071 g_assert (tb
->nesting_type
->type
);
9072 klass
->nested_in
= mono_class_from_mono_type (tb
->nesting_type
->type
);
9075 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9077 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
9079 mono_loader_unlock ();
9083 * mono_reflection_setup_generic_class:
9084 * @tb: a TypeBuilder object
9086 * Setup the generic class before adding the first generic parameter.
9089 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
9094 * mono_reflection_create_generic_class:
9095 * @tb: a TypeBuilder object
9097 * Creates the generic class after all generic parameters have been added.
9100 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
9105 MONO_ARCH_SAVE_REGS
;
9107 klass
= mono_class_from_mono_type (tb
->type
.type
);
9109 count
= tb
->generic_params
? mono_array_length (tb
->generic_params
) : 0;
9111 if (klass
->generic_container
|| (count
== 0))
9114 g_assert (tb
->generic_container
&& (tb
->generic_container
->owner
.klass
== klass
));
9116 klass
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
9118 klass
->generic_container
->owner
.klass
= klass
;
9119 klass
->generic_container
->type_argc
= count
;
9120 klass
->generic_container
->type_params
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericParamFull
) * count
);
9122 klass
->is_generic
= 1;
9124 for (i
= 0; i
< count
; i
++) {
9125 MonoReflectionGenericParam
*gparam
= mono_array_get (tb
->generic_params
, gpointer
, i
);
9126 MonoGenericParamFull
*param
= (MonoGenericParamFull
*) gparam
->type
.type
->data
.generic_param
;
9127 klass
->generic_container
->type_params
[i
] = *param
;
9128 /*Make sure we are a diferent type instance */
9129 klass
->generic_container
->type_params
[i
].param
.owner
= klass
->generic_container
;
9130 klass
->generic_container
->type_params
[i
].info
.pklass
= NULL
;
9132 g_assert (klass
->generic_container
->type_params
[i
].param
.owner
);
9135 klass
->generic_container
->context
.class_inst
= mono_get_shared_generic_inst (klass
->generic_container
);
9139 * mono_reflection_create_internal_class:
9140 * @tb: a TypeBuilder object
9142 * Actually create the MonoClass that is associated with the TypeBuilder.
9145 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
9149 MONO_ARCH_SAVE_REGS
;
9151 klass
= mono_class_from_mono_type (tb
->type
.type
);
9153 mono_loader_lock ();
9154 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) == NULL
) {
9155 MonoReflectionFieldBuilder
*fb
;
9157 MonoType
*enum_basetype
;
9159 g_assert (tb
->fields
!= NULL
);
9160 g_assert (mono_array_length (tb
->fields
) >= 1);
9162 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, 0);
9164 if (!mono_type_is_valid_enum_basetype (monotype_cast (fb
->type
)->type
)) {
9165 mono_loader_unlock ();
9169 enum_basetype
= monotype_cast (fb
->type
)->type
;
9170 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
9171 if (!klass
->element_class
)
9172 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
9175 * get the element_class from the current corlib.
9177 ec
= default_class_from_mono_type (enum_basetype
);
9178 klass
->instance_size
= ec
->instance_size
;
9179 klass
->size_inited
= 1;
9181 * this is almost safe to do with enums and it's needed to be able
9182 * to create objects of the enum type (for use in SetConstant).
9184 /* FIXME: Does this mean enums can't have method overrides ? */
9185 mono_class_setup_vtable_general (klass
, NULL
, 0);
9187 mono_loader_unlock ();
9190 static MonoMarshalSpec
*
9191 mono_marshal_spec_from_builder (MonoImage
*image
, MonoAssembly
*assembly
,
9192 MonoReflectionMarshal
*minfo
)
9194 MonoMarshalSpec
*res
;
9196 res
= image_g_new0 (image
, MonoMarshalSpec
, 1);
9197 res
->native
= minfo
->type
;
9199 switch (minfo
->type
) {
9200 case MONO_NATIVE_LPARRAY
:
9201 res
->data
.array_data
.elem_type
= minfo
->eltype
;
9202 if (minfo
->has_size
) {
9203 res
->data
.array_data
.param_num
= minfo
->param_num
;
9204 res
->data
.array_data
.num_elem
= minfo
->count
;
9205 res
->data
.array_data
.elem_mult
= minfo
->param_num
== -1 ? 0 : 1;
9208 res
->data
.array_data
.param_num
= -1;
9209 res
->data
.array_data
.num_elem
= -1;
9210 res
->data
.array_data
.elem_mult
= -1;
9214 case MONO_NATIVE_BYVALTSTR
:
9215 case MONO_NATIVE_BYVALARRAY
:
9216 res
->data
.array_data
.num_elem
= minfo
->count
;
9219 case MONO_NATIVE_CUSTOM
:
9220 if (minfo
->marshaltyperef
)
9221 res
->data
.custom_data
.custom_name
=
9222 type_get_fully_qualified_name (monotype_cast (minfo
->marshaltyperef
)->type
);
9224 res
->data
.custom_data
.cookie
= mono_string_to_utf8 (minfo
->mcookie
);
9233 #endif /* !DISABLE_REFLECTION_EMIT */
9235 MonoReflectionMarshal
*
9236 mono_reflection_marshal_from_marshal_spec (MonoDomain
*domain
, MonoClass
*klass
,
9237 MonoMarshalSpec
*spec
)
9239 static MonoClass
*System_Reflection_Emit_UnmanagedMarshalClass
;
9240 MonoReflectionMarshal
*minfo
;
9243 if (!System_Reflection_Emit_UnmanagedMarshalClass
) {
9244 System_Reflection_Emit_UnmanagedMarshalClass
= mono_class_from_name (
9245 mono_defaults
.corlib
, "System.Reflection.Emit", "UnmanagedMarshal");
9246 g_assert (System_Reflection_Emit_UnmanagedMarshalClass
);
9249 minfo
= (MonoReflectionMarshal
*)mono_object_new (domain
, System_Reflection_Emit_UnmanagedMarshalClass
);
9250 minfo
->type
= spec
->native
;
9252 switch (minfo
->type
) {
9253 case MONO_NATIVE_LPARRAY
:
9254 minfo
->eltype
= spec
->data
.array_data
.elem_type
;
9255 minfo
->count
= spec
->data
.array_data
.num_elem
;
9256 minfo
->param_num
= spec
->data
.array_data
.param_num
;
9259 case MONO_NATIVE_BYVALTSTR
:
9260 case MONO_NATIVE_BYVALARRAY
:
9261 minfo
->count
= spec
->data
.array_data
.num_elem
;
9264 case MONO_NATIVE_CUSTOM
:
9265 if (spec
->data
.custom_data
.custom_name
) {
9266 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, klass
->image
);
9268 MONO_OBJECT_SETREF (minfo
, marshaltyperef
, mono_type_get_object (domain
, mtype
));
9270 MONO_OBJECT_SETREF (minfo
, marshaltype
, mono_string_new (domain
, spec
->data
.custom_data
.custom_name
));
9272 if (spec
->data
.custom_data
.cookie
)
9273 MONO_OBJECT_SETREF (minfo
, mcookie
, mono_string_new (domain
, spec
->data
.custom_data
.cookie
));
9283 #ifndef DISABLE_REFLECTION_EMIT
9285 reflection_methodbuilder_to_mono_method (MonoClass
*klass
,
9286 ReflectionMethodBuilder
*rmb
,
9287 MonoMethodSignature
*sig
)
9290 MonoMethodNormal
*pm
;
9291 MonoMarshalSpec
**specs
;
9292 MonoReflectionMethodAux
*method_aux
;
9298 * Methods created using a MethodBuilder should have their memory allocated
9299 * inside the image mempool, while dynamic methods should have their memory
9302 dynamic
= rmb
->refs
!= NULL
;
9303 image
= dynamic
? NULL
: klass
->image
;
9306 g_assert (!klass
->generic_class
);
9308 mono_loader_lock ();
9310 if ((rmb
->attrs
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
9311 (rmb
->iattrs
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
))
9312 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodPInvoke
, 1);
9314 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodWrapper
, 1);
9316 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodNormal
, 1);
9318 pm
= (MonoMethodNormal
*)m
;
9320 m
->dynamic
= dynamic
;
9322 m
->flags
= rmb
->attrs
;
9323 m
->iflags
= rmb
->iattrs
;
9324 m
->name
= mono_string_to_utf8_image (image
, rmb
->name
);
9327 m
->skip_visibility
= rmb
->skip_visibility
;
9329 m
->token
= MONO_TOKEN_METHOD_DEF
| (*rmb
->table_idx
);
9331 if (m
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) {
9332 if (klass
== mono_defaults
.string_class
&& !strcmp (m
->name
, ".ctor"))
9335 m
->signature
->pinvoke
= 1;
9336 } else if (m
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
9337 m
->signature
->pinvoke
= 1;
9339 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9341 method_aux
->dllentry
= rmb
->dllentry
? mono_string_to_utf8_image (image
, rmb
->dllentry
) : image_strdup (image
, m
->name
);
9342 method_aux
->dll
= mono_string_to_utf8_image (image
, rmb
->dll
);
9344 ((MonoMethodPInvoke
*)m
)->piflags
= (rmb
->native_cc
<< 8) | (rmb
->charset
? (rmb
->charset
- 1) * 2 : 0) | rmb
->extra_flags
;
9346 if (klass
->image
->dynamic
)
9347 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
9349 mono_loader_unlock ();
9352 } else if (!(m
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) &&
9353 !(m
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
9354 MonoMethodHeader
*header
;
9356 gint32 max_stack
, i
;
9357 gint32 num_locals
= 0;
9358 gint32 num_clauses
= 0;
9362 code
= mono_array_addr (rmb
->ilgen
->code
, guint8
, 0);
9363 code_size
= rmb
->ilgen
->code_len
;
9364 max_stack
= rmb
->ilgen
->max_stack
;
9365 num_locals
= rmb
->ilgen
->locals
? mono_array_length (rmb
->ilgen
->locals
) : 0;
9366 if (rmb
->ilgen
->ex_handlers
)
9367 num_clauses
= method_count_clauses (rmb
->ilgen
);
9370 code
= mono_array_addr (rmb
->code
, guint8
, 0);
9371 code_size
= mono_array_length (rmb
->code
);
9372 /* we probably need to run a verifier on the code... */
9382 header
= image_g_malloc0 (image
, sizeof (MonoMethodHeader
) +
9383 (num_locals
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoType
*));
9384 header
->code_size
= code_size
;
9385 header
->code
= image_g_malloc (image
, code_size
);
9386 memcpy ((char*)header
->code
, code
, code_size
);
9387 header
->max_stack
= max_stack
;
9388 header
->init_locals
= rmb
->init_locals
;
9389 header
->num_locals
= num_locals
;
9391 for (i
= 0; i
< num_locals
; ++i
) {
9392 MonoReflectionLocalBuilder
*lb
=
9393 mono_array_get (rmb
->ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
9395 header
->locals
[i
] = image_g_new0 (image
, MonoType
, 1);
9396 memcpy (header
->locals
[i
], monotype_cast (lb
->type
)->type
, sizeof (MonoType
));
9399 header
->num_clauses
= num_clauses
;
9401 header
->clauses
= method_encode_clauses (image
, (MonoDynamicImage
*)klass
->image
,
9402 rmb
->ilgen
, num_clauses
);
9405 pm
->header
= header
;
9408 if (rmb
->generic_params
) {
9409 int count
= mono_array_length (rmb
->generic_params
);
9410 MonoGenericContainer
*container
;
9412 container
= rmb
->generic_container
;
9414 m
->is_generic
= TRUE
;
9415 mono_method_set_generic_container (m
, container
);
9417 container
->type_argc
= count
;
9418 container
->type_params
= image_g_new0 (image
, MonoGenericParamFull
, count
);
9419 container
->owner
.method
= m
;
9421 for (i
= 0; i
< count
; i
++) {
9422 MonoReflectionGenericParam
*gp
=
9423 mono_array_get (rmb
->generic_params
, MonoReflectionGenericParam
*, i
);
9424 MonoGenericParamFull
*param
= (MonoGenericParamFull
*) gp
->type
.type
->data
.generic_param
;
9425 container
->type_params
[i
] = *param
;
9428 if (klass
->generic_container
) {
9429 container
->parent
= klass
->generic_container
;
9430 container
->context
.class_inst
= klass
->generic_container
->context
.class_inst
;
9432 container
->context
.method_inst
= mono_get_shared_generic_inst (container
);
9436 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)m
;
9440 m
->wrapper_type
= MONO_WRAPPER_DYNAMIC_METHOD
;
9442 mw
->method_data
= data
= image_g_new (image
, gpointer
, rmb
->nrefs
+ 1);
9443 data
[0] = GUINT_TO_POINTER (rmb
->nrefs
);
9444 for (i
= 0; i
< rmb
->nrefs
; ++i
)
9445 data
[i
+ 1] = rmb
->refs
[i
];
9450 /* Parameter info */
9453 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9454 method_aux
->param_names
= image_g_new0 (image
, char *, mono_method_signature (m
)->param_count
+ 1);
9455 for (i
= 0; i
<= m
->signature
->param_count
; ++i
) {
9456 MonoReflectionParamBuilder
*pb
;
9457 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
9458 if ((i
> 0) && (pb
->attrs
)) {
9459 /* Make a copy since it might point to a shared type structure */
9460 m
->signature
->params
[i
- 1] = mono_metadata_type_dup (klass
->image
, m
->signature
->params
[i
- 1]);
9461 m
->signature
->params
[i
- 1]->attrs
= pb
->attrs
;
9464 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
9465 MonoDynamicImage
*assembly
;
9466 guint32 idx
, def_type
, len
;
9470 if (!method_aux
->param_defaults
) {
9471 method_aux
->param_defaults
= image_g_new0 (image
, guint8
*, m
->signature
->param_count
+ 1);
9472 method_aux
->param_default_types
= image_g_new0 (image
, guint32
, m
->signature
->param_count
+ 1);
9474 assembly
= (MonoDynamicImage
*)klass
->image
;
9475 idx
= encode_constant (assembly
, pb
->def_value
, &def_type
);
9476 /* Copy the data from the blob since it might get realloc-ed */
9477 p
= assembly
->blob
.data
+ idx
;
9478 len
= mono_metadata_decode_blob_size (p
, &p2
);
9480 method_aux
->param_defaults
[i
] = image_g_malloc (image
, len
);
9481 method_aux
->param_default_types
[i
] = def_type
;
9482 memcpy ((gpointer
)method_aux
->param_defaults
[i
], p
, len
);
9486 method_aux
->param_names
[i
] = mono_string_to_utf8_image (image
, pb
->name
);
9488 if (!method_aux
->param_cattr
)
9489 method_aux
->param_cattr
= image_g_new0 (image
, MonoCustomAttrInfo
*, m
->signature
->param_count
+ 1);
9490 method_aux
->param_cattr
[i
] = mono_custom_attrs_from_builders (image
, klass
->image
, pb
->cattrs
);
9496 /* Parameter marshalling */
9499 for (i
= 0; i
< mono_array_length (rmb
->pinfo
); ++i
) {
9500 MonoReflectionParamBuilder
*pb
;
9501 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
9502 if (pb
->marshal_info
) {
9504 specs
= image_g_new0 (image
, MonoMarshalSpec
*, sig
->param_count
+ 1);
9505 specs
[pb
->position
] =
9506 mono_marshal_spec_from_builder (image
, klass
->image
->assembly
, pb
->marshal_info
);
9510 if (specs
!= NULL
) {
9512 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9513 method_aux
->param_marshall
= specs
;
9516 if (klass
->image
->dynamic
&& method_aux
)
9517 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
9519 mono_loader_unlock ();
9525 ctorbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionCtorBuilder
* mb
)
9527 ReflectionMethodBuilder rmb
;
9528 MonoMethodSignature
*sig
;
9530 mono_loader_lock ();
9531 sig
= ctor_builder_to_signature (klass
->image
, mb
);
9532 mono_loader_unlock ();
9534 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
9536 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
9537 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
9539 /* If we are in a generic class, we might be called multiple times from inflate_method */
9540 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
9541 /* ilgen is no longer needed */
9549 methodbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionMethodBuilder
* mb
)
9551 ReflectionMethodBuilder rmb
;
9552 MonoMethodSignature
*sig
;
9554 mono_loader_lock ();
9555 sig
= method_builder_to_signature (klass
->image
, mb
);
9556 mono_loader_unlock ();
9558 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
9560 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
9561 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
9563 /* If we are in a generic class, we might be called multiple times from inflate_method */
9564 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
9565 /* ilgen is no longer needed */
9571 static MonoClassField
*
9572 fieldbuilder_to_mono_class_field (MonoClass
*klass
, MonoReflectionFieldBuilder
* fb
)
9574 MonoClassField
*field
;
9577 field
= g_new0 (MonoClassField
, 1);
9579 field
->name
= mono_string_to_utf8 (fb
->name
);
9580 if (fb
->attrs
|| fb
->modreq
|| fb
->modopt
) {
9581 field
->type
= mono_metadata_type_dup (NULL
, monotype_cast (fb
->type
)->type
);
9582 field
->type
->attrs
= fb
->attrs
;
9584 g_assert (klass
->image
->dynamic
);
9585 custom
= add_custom_modifiers ((MonoDynamicImage
*)klass
->image
, field
->type
, fb
->modreq
, fb
->modopt
);
9586 g_free (field
->type
);
9587 field
->type
= custom
;
9589 field
->type
= monotype_cast (fb
->type
)->type
;
9591 if (fb
->offset
!= -1)
9592 field
->offset
= fb
->offset
;
9593 field
->parent
= klass
;
9594 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
9596 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9603 mono_reflection_bind_generic_parameters (MonoReflectionType
*type
, int type_argc
, MonoType
**types
)
9606 MonoReflectionTypeBuilder
*tb
= NULL
;
9607 gboolean is_dynamic
= FALSE
;
9611 mono_loader_lock ();
9613 domain
= mono_object_domain (type
);
9615 if (!strcmp (((MonoObject
*) type
)->vtable
->klass
->name
, "TypeBuilder")) {
9616 tb
= (MonoReflectionTypeBuilder
*) type
;
9619 } else if (!strcmp (((MonoObject
*) type
)->vtable
->klass
->name
, "MonoGenericClass")) {
9620 MonoReflectionGenericClass
*rgi
= (MonoReflectionGenericClass
*) type
;
9622 tb
= rgi
->generic_type
;
9626 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9627 if (tb
&& tb
->generic_container
)
9628 mono_reflection_create_generic_class (tb
);
9630 klass
= mono_class_from_mono_type (type
->type
);
9631 if (!klass
->generic_container
) {
9632 mono_loader_unlock ();
9636 if (klass
->wastypebuilder
) {
9637 tb
= (MonoReflectionTypeBuilder
*) klass
->reflection_info
;
9642 mono_loader_unlock ();
9644 geninst
= mono_class_bind_generic_parameters (klass
, type_argc
, types
, is_dynamic
);
9646 return &geninst
->byval_arg
;
9650 mono_class_bind_generic_parameters (MonoClass
*klass
, int type_argc
, MonoType
**types
, gboolean is_dynamic
)
9652 MonoGenericClass
*gclass
;
9653 MonoGenericInst
*inst
;
9655 g_assert (klass
->generic_container
);
9657 inst
= mono_metadata_get_generic_inst (type_argc
, types
);
9658 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, is_dynamic
);
9660 return mono_generic_class_get_class (gclass
);
9663 MonoReflectionMethod
*
9664 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod
*rmethod
, MonoArray
*types
)
9667 MonoMethod
*method
, *inflated
;
9668 MonoMethodInflated
*imethod
;
9669 MonoGenericContext tmp_context
;
9670 MonoGenericInst
*ginst
;
9671 MonoType
**type_argv
;
9674 MONO_ARCH_SAVE_REGS
;
9676 if (!strcmp (rmethod
->object
.vtable
->klass
->name
, "MethodBuilder")) {
9677 #ifndef DISABLE_REFLECTION_EMIT
9678 MonoReflectionMethodBuilder
*mb
= NULL
;
9679 MonoReflectionTypeBuilder
*tb
;
9682 mb
= (MonoReflectionMethodBuilder
*) rmethod
;
9683 tb
= (MonoReflectionTypeBuilder
*) mb
->type
;
9684 klass
= mono_class_from_mono_type (tb
->type
.type
);
9686 method
= methodbuilder_to_mono_method (klass
, mb
);
9688 g_assert_not_reached ();
9692 method
= rmethod
->method
;
9695 klass
= method
->klass
;
9697 if (method
->is_inflated
)
9698 method
= ((MonoMethodInflated
*) method
)->declaring
;
9700 count
= mono_method_signature (method
)->generic_param_count
;
9701 if (count
!= mono_array_length (types
))
9704 type_argv
= g_new0 (MonoType
*, count
);
9705 for (i
= 0; i
< count
; i
++) {
9706 MonoReflectionType
*garg
= mono_array_get (types
, gpointer
, i
);
9707 type_argv
[i
] = garg
->type
;
9709 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
9712 tmp_context
.class_inst
= klass
->generic_class
? klass
->generic_class
->context
.class_inst
: NULL
;
9713 tmp_context
.method_inst
= ginst
;
9715 inflated
= mono_class_inflate_generic_method (method
, &tmp_context
);
9716 imethod
= (MonoMethodInflated
*) inflated
;
9718 if (method
->klass
->image
->dynamic
) {
9719 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
9721 * This table maps metadata structures representing inflated methods/fields
9722 * to the reflection objects representing their generic definitions.
9724 mono_loader_lock ();
9725 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, rmethod
);
9726 mono_loader_unlock ();
9729 return mono_method_get_object (mono_object_domain (rmethod
), inflated
, NULL
);
9732 #ifndef DISABLE_REFLECTION_EMIT
9735 inflate_mono_method (MonoClass
*klass
, MonoMethod
*method
, MonoObject
*obj
)
9737 MonoMethodInflated
*imethod
;
9738 MonoGenericContext
*context
;
9742 * With generic code sharing the klass might not be inflated.
9743 * This can happen because classes inflated with their own
9744 * type arguments are "normalized" to the uninflated class.
9746 if (!klass
->generic_class
)
9749 context
= mono_class_get_context (klass
);
9751 if (klass
->method
.count
) {
9752 /* Find the already created inflated method */
9753 for (i
= 0; i
< klass
->method
.count
; ++i
) {
9754 g_assert (klass
->methods
[i
]->is_inflated
);
9755 if (((MonoMethodInflated
*)klass
->methods
[i
])->declaring
== method
)
9758 g_assert (i
< klass
->method
.count
);
9759 imethod
= (MonoMethodInflated
*)klass
->methods
[i
];
9761 imethod
= (MonoMethodInflated
*) mono_class_inflate_generic_method_full (method
, klass
, context
);
9764 if (method
->is_generic
&& method
->klass
->image
->dynamic
) {
9765 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
9767 mono_loader_lock ();
9768 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, obj
);
9769 mono_loader_unlock ();
9771 return (MonoMethod
*) imethod
;
9775 inflate_method (MonoReflectionGenericClass
*type
, MonoObject
*obj
)
9780 gklass
= mono_class_from_mono_type (type
->generic_type
->type
.type
);
9782 if (!strcmp (obj
->vtable
->klass
->name
, "MethodBuilder"))
9783 if (((MonoReflectionMethodBuilder
*)obj
)->mhandle
)
9784 method
= ((MonoReflectionMethodBuilder
*)obj
)->mhandle
;
9786 method
= methodbuilder_to_mono_method (gklass
, (MonoReflectionMethodBuilder
*) obj
);
9787 else if (!strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder"))
9788 method
= ctorbuilder_to_mono_method (gklass
, (MonoReflectionCtorBuilder
*) obj
);
9789 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoMethod") || !strcmp (obj
->vtable
->klass
->name
, "MonoCMethod"))
9790 method
= ((MonoReflectionMethod
*) obj
)->method
;
9792 method
= NULL
; /* prevent compiler warning */
9793 g_assert_not_reached ();
9796 return inflate_mono_method (mono_class_from_mono_type (type
->type
.type
), method
, obj
);
9799 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9801 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
9802 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
9805 MonoGenericClass
*gclass
;
9806 MonoDynamicGenericClass
*dgclass
;
9807 MonoClass
*klass
, *gklass
;
9810 MONO_ARCH_SAVE_REGS
;
9812 klass
= mono_class_from_mono_type (type
->type
.type
);
9813 g_assert (type
->type
.type
->type
== MONO_TYPE_GENERICINST
);
9814 gclass
= type
->type
.type
->data
.generic_class
;
9816 g_assert (gclass
->is_dynamic
);
9817 dgclass
= (MonoDynamicGenericClass
*) gclass
;
9819 if (dgclass
->initialized
)
9822 gklass
= gclass
->container_class
;
9823 mono_class_init (gklass
);
9825 dgclass
->count_methods
= methods
? mono_array_length (methods
) : 0;
9826 dgclass
->count_ctors
= ctors
? mono_array_length (ctors
) : 0;
9827 dgclass
->count_fields
= fields
? mono_array_length (fields
) : 0;
9828 dgclass
->count_properties
= properties
? mono_array_length (properties
) : 0;
9829 dgclass
->count_events
= events
? mono_array_length (events
) : 0;
9831 dgclass
->methods
= g_new0 (MonoMethod
*, dgclass
->count_methods
);
9832 dgclass
->ctors
= g_new0 (MonoMethod
*, dgclass
->count_ctors
);
9833 dgclass
->fields
= g_new0 (MonoClassField
, dgclass
->count_fields
);
9834 dgclass
->properties
= g_new0 (MonoProperty
, dgclass
->count_properties
);
9835 dgclass
->events
= g_new0 (MonoEvent
, dgclass
->count_events
);
9836 dgclass
->field_objects
= g_new0 (MonoObject
*, dgclass
->count_fields
);
9837 dgclass
->field_generic_types
= g_new0 (MonoType
*, dgclass
->count_fields
);
9839 for (i
= 0; i
< dgclass
->count_methods
; i
++) {
9840 MonoObject
*obj
= mono_array_get (methods
, gpointer
, i
);
9842 dgclass
->methods
[i
] = inflate_method (type
, obj
);
9845 for (i
= 0; i
< dgclass
->count_ctors
; i
++) {
9846 MonoObject
*obj
= mono_array_get (ctors
, gpointer
, i
);
9848 dgclass
->ctors
[i
] = inflate_method (type
, obj
);
9851 for (i
= 0; i
< dgclass
->count_fields
; i
++) {
9852 MonoObject
*obj
= mono_array_get (fields
, gpointer
, i
);
9853 MonoClassField
*field
, *inflated_field
= NULL
;
9855 if (!strcmp (obj
->vtable
->klass
->name
, "FieldBuilder"))
9856 inflated_field
= field
= fieldbuilder_to_mono_class_field (klass
, (MonoReflectionFieldBuilder
*) obj
);
9857 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoField"))
9858 field
= ((MonoReflectionField
*) obj
)->field
;
9860 field
= NULL
; /* prevent compiler warning */
9861 g_assert_not_reached ();
9864 dgclass
->fields
[i
] = *field
;
9865 dgclass
->fields
[i
].parent
= klass
;
9866 dgclass
->fields
[i
].type
= mono_class_inflate_generic_type (
9867 field
->type
, mono_generic_class_get_context ((MonoGenericClass
*) dgclass
));
9868 dgclass
->field_generic_types
[i
] = field
->type
;
9869 MOVING_GC_REGISTER (&dgclass
->field_objects
[i
]);
9870 dgclass
->field_objects
[i
] = obj
;
9872 if (inflated_field
) {
9873 g_free (inflated_field
);
9875 dgclass
->fields
[i
].name
= g_strdup (dgclass
->fields
[i
].name
);
9879 for (i
= 0; i
< dgclass
->count_properties
; i
++) {
9880 MonoObject
*obj
= mono_array_get (properties
, gpointer
, i
);
9881 MonoProperty
*property
= &dgclass
->properties
[i
];
9883 if (!strcmp (obj
->vtable
->klass
->name
, "PropertyBuilder")) {
9884 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*) obj
;
9886 property
->parent
= klass
;
9887 property
->attrs
= pb
->attrs
;
9888 property
->name
= mono_string_to_utf8 (pb
->name
);
9890 property
->get
= inflate_method (type
, (MonoObject
*) pb
->get_method
);
9892 property
->set
= inflate_method (type
, (MonoObject
*) pb
->set_method
);
9893 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoProperty")) {
9894 *property
= *((MonoReflectionProperty
*) obj
)->property
;
9895 property
->name
= g_strdup (property
->name
);
9898 property
->get
= inflate_mono_method (klass
, property
->get
, NULL
);
9900 property
->set
= inflate_mono_method (klass
, property
->set
, NULL
);
9902 g_assert_not_reached ();
9905 for (i
= 0; i
< dgclass
->count_events
; i
++) {
9906 MonoObject
*obj
= mono_array_get (events
, gpointer
, i
);
9907 MonoEvent
*event
= &dgclass
->events
[i
];
9909 if (!strcmp (obj
->vtable
->klass
->name
, "EventBuilder")) {
9910 MonoReflectionEventBuilder
*eb
= (MonoReflectionEventBuilder
*) obj
;
9912 event
->parent
= klass
;
9913 event
->attrs
= eb
->attrs
;
9914 event
->name
= mono_string_to_utf8 (eb
->name
);
9916 event
->add
= inflate_method (type
, (MonoObject
*) eb
->add_method
);
9917 if (eb
->remove_method
)
9918 event
->remove
= inflate_method (type
, (MonoObject
*) eb
->remove_method
);
9919 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoEvent")) {
9920 *event
= *((MonoReflectionMonoEvent
*) obj
)->event
;
9921 event
->name
= g_strdup (event
->name
);
9924 event
->add
= inflate_mono_method (klass
, event
->add
, NULL
);
9926 event
->remove
= inflate_mono_method (klass
, event
->remove
, NULL
);
9928 g_assert_not_reached ();
9931 dgclass
->initialized
= TRUE
;
9935 ensure_generic_class_runtime_vtable (MonoClass
*klass
)
9937 MonoClass
*gklass
= klass
->generic_class
->container_class
;
9940 if (klass
->wastypebuilder
)
9943 ensure_runtime_vtable (gklass
);
9945 klass
->method
.count
= gklass
->method
.count
;
9946 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * (klass
->method
.count
+ 1));
9948 for (i
= 0; i
< klass
->method
.count
; i
++) {
9949 klass
->methods
[i
] = mono_class_inflate_generic_method_full (
9950 gklass
->methods
[i
], klass
, mono_class_get_context (klass
));
9953 klass
->interface_count
= gklass
->interface_count
;
9954 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
9955 for (i
= 0; i
< klass
->interface_count
; ++i
) {
9956 MonoType
*iface_type
= mono_class_inflate_generic_type (&gklass
->interfaces
[i
]->byval_arg
, mono_class_get_context (klass
));
9957 klass
->interfaces
[i
] = mono_class_from_mono_type (iface_type
);
9958 mono_metadata_free_type (iface_type
);
9960 ensure_runtime_vtable (klass
->interfaces
[i
]);
9962 klass
->interfaces_inited
= 1;
9964 /*We can only finish with this klass once it's parent has as well*/
9965 if (gklass
->wastypebuilder
)
9966 klass
->wastypebuilder
= TRUE
;
9971 ensure_runtime_vtable (MonoClass
*klass
)
9973 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
9976 if (!klass
->image
->dynamic
|| (!tb
&& !klass
->generic_class
) || klass
->wastypebuilder
)
9979 ensure_runtime_vtable (klass
->parent
);
9982 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
9983 num
+= tb
->num_methods
;
9984 klass
->method
.count
= num
;
9985 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * num
);
9986 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
9987 for (i
= 0; i
< num
; ++i
)
9988 klass
->methods
[i
] = ctorbuilder_to_mono_method (klass
, mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
));
9989 num
= tb
->num_methods
;
9991 for (i
= 0; i
< num
; ++i
)
9992 klass
->methods
[j
++] = methodbuilder_to_mono_method (klass
, mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
));
9994 if (tb
->interfaces
) {
9995 klass
->interface_count
= mono_array_length (tb
->interfaces
);
9996 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
9997 for (i
= 0; i
< klass
->interface_count
; ++i
) {
9998 MonoReflectionType
*iface
= mono_type_array_get (tb
->interfaces
, i
);
9999 klass
->interfaces
[i
] = mono_class_from_mono_type (iface
->type
);
10000 ensure_runtime_vtable (klass
->interfaces
[i
]);
10002 klass
->interfaces_inited
= 1;
10004 } else if (klass
->generic_class
){
10005 ensure_generic_class_runtime_vtable (klass
);
10008 if (klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
10009 for (i
= 0; i
< klass
->method
.count
; ++i
)
10010 klass
->methods
[i
]->slot
= i
;
10012 mono_class_setup_interface_offsets (klass
);
10013 mono_class_setup_interface_id (klass
);
10017 * The generic vtable is needed even if image->run is not set since some
10018 * runtime code like ves_icall_Type_GetMethodsByName depends on
10019 * method->slot being defined.
10023 * tb->methods could not be freed since it is used for determining
10024 * overrides during dynamic vtable construction.
10029 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
10031 MonoReflectionTypeBuilder
*tb
;
10035 *num_overrides
= 0;
10037 g_assert (klass
->image
->dynamic
);
10039 if (!klass
->reflection_info
)
10042 g_assert (strcmp (((MonoObject
*)klass
->reflection_info
)->vtable
->klass
->name
, "TypeBuilder") == 0);
10044 tb
= (MonoReflectionTypeBuilder
*)klass
->reflection_info
;
10048 for (i
= 0; i
< tb
->num_methods
; ++i
) {
10049 MonoReflectionMethodBuilder
*mb
=
10050 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
10051 if (mb
->override_method
)
10057 *overrides
= g_new0 (MonoMethod
*, onum
* 2);
10060 for (i
= 0; i
< tb
->num_methods
; ++i
) {
10061 MonoReflectionMethodBuilder
*mb
=
10062 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
10063 if (mb
->override_method
) {
10064 (*overrides
) [onum
* 2] =
10065 mb
->override_method
->method
;
10066 (*overrides
) [onum
* 2 + 1] =
10069 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10070 g_assert (mb
->override_method
->method
);
10071 g_assert (mb
->mhandle
);
10078 *num_overrides
= onum
;
10082 typebuilder_setup_fields (MonoClass
*klass
)
10084 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10085 MonoReflectionFieldBuilder
*fb
;
10086 MonoClassField
*field
;
10087 MonoImage
*image
= klass
->image
;
10088 const char *p
, *p2
;
10090 guint32 len
, idx
, real_size
= 0;
10092 klass
->field
.count
= tb
->num_fields
;
10093 klass
->field
.first
= 0;
10095 if (tb
->class_size
) {
10096 g_assert ((tb
->packing_size
& 0xfffffff0) == 0);
10097 klass
->packing_size
= tb
->packing_size
;
10098 real_size
= klass
->instance_size
+ tb
->class_size
;
10101 if (!klass
->field
.count
) {
10102 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10106 klass
->fields
= image_g_new0 (image
, MonoClassField
, klass
->field
.count
);
10107 mono_class_alloc_ext (klass
);
10108 klass
->ext
->field_def_values
= image_g_new0 (image
, MonoFieldDefaultValue
, klass
->field
.count
);
10110 for (i
= 0; i
< klass
->field
.count
; ++i
) {
10111 fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10112 field
= &klass
->fields
[i
];
10113 field
->name
= mono_string_to_utf8_image (image
, fb
->name
);
10115 field
->type
= mono_metadata_type_dup (klass
->image
, monotype_cast (fb
->type
)->type
);
10116 field
->type
->attrs
= fb
->attrs
;
10118 field
->type
= monotype_cast (fb
->type
)->type
;
10120 if ((fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) && fb
->rva_data
)
10121 klass
->ext
->field_def_values
[i
].data
= mono_array_addr (fb
->rva_data
, char, 0);
10122 if (fb
->offset
!= -1)
10123 field
->offset
= fb
->offset
;
10124 field
->parent
= klass
;
10125 fb
->handle
= field
;
10126 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
10128 if (fb
->def_value
) {
10129 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)klass
->image
;
10130 field
->type
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
10131 idx
= encode_constant (assembly
, fb
->def_value
, &klass
->ext
->field_def_values
[i
].def_type
);
10132 /* Copy the data from the blob since it might get realloc-ed */
10133 p
= assembly
->blob
.data
+ idx
;
10134 len
= mono_metadata_decode_blob_size (p
, &p2
);
10136 klass
->ext
->field_def_values
[i
].data
= mono_image_alloc (image
, len
);
10137 memcpy ((gpointer
)klass
->ext
->field_def_values
[i
].data
, p
, len
);
10141 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10142 mono_class_layout_fields (klass
);
10146 typebuilder_setup_properties (MonoClass
*klass
)
10148 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10149 MonoReflectionPropertyBuilder
*pb
;
10150 MonoImage
*image
= klass
->image
;
10151 MonoProperty
*properties
;
10155 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
10157 klass
->ext
->property
.count
= tb
->properties
? mono_array_length (tb
->properties
) : 0;
10158 klass
->ext
->property
.first
= 0;
10160 properties
= image_g_new0 (image
, MonoProperty
, klass
->ext
->property
.count
);
10161 klass
->ext
->properties
= properties
;
10162 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
10163 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
10164 properties
[i
].parent
= klass
;
10165 properties
[i
].attrs
= pb
->attrs
;
10166 properties
[i
].name
= mono_string_to_utf8_image (image
, pb
->name
);
10167 if (pb
->get_method
)
10168 properties
[i
].get
= pb
->get_method
->mhandle
;
10169 if (pb
->set_method
)
10170 properties
[i
].set
= pb
->set_method
->mhandle
;
10172 mono_save_custom_attrs (klass
->image
, &properties
[i
], pb
->cattrs
);
10176 MonoReflectionEvent
*
10177 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
10179 MonoEvent
*event
= g_new0 (MonoEvent
, 1);
10183 klass
= mono_class_from_mono_type (tb
->type
.type
);
10185 event
->parent
= klass
;
10186 event
->attrs
= eb
->attrs
;
10187 event
->name
= mono_string_to_utf8 (eb
->name
);
10188 if (eb
->add_method
)
10189 event
->add
= eb
->add_method
->mhandle
;
10190 if (eb
->remove_method
)
10191 event
->remove
= eb
->remove_method
->mhandle
;
10192 if (eb
->raise_method
)
10193 event
->raise
= eb
->raise_method
->mhandle
;
10195 if (eb
->other_methods
) {
10196 event
->other
= g_new0 (MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10197 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10198 MonoReflectionMethodBuilder
*mb
=
10199 mono_array_get (eb
->other_methods
,
10200 MonoReflectionMethodBuilder
*, j
);
10201 event
->other
[j
] = mb
->mhandle
;
10205 return mono_event_get_object (mono_object_domain (tb
), klass
, event
);
10209 typebuilder_setup_events (MonoClass
*klass
)
10211 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10212 MonoReflectionEventBuilder
*eb
;
10213 MonoImage
*image
= klass
->image
;
10218 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
10220 klass
->ext
->event
.count
= tb
->events
? mono_array_length (tb
->events
) : 0;
10221 klass
->ext
->event
.first
= 0;
10223 events
= image_g_new0 (image
, MonoEvent
, klass
->ext
->event
.count
);
10224 klass
->ext
->events
= events
;
10225 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
10226 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
10227 events
[i
].parent
= klass
;
10228 events
[i
].attrs
= eb
->attrs
;
10229 events
[i
].name
= mono_string_to_utf8_image (image
, eb
->name
);
10230 if (eb
->add_method
)
10231 events
[i
].add
= eb
->add_method
->mhandle
;
10232 if (eb
->remove_method
)
10233 events
[i
].remove
= eb
->remove_method
->mhandle
;
10234 if (eb
->raise_method
)
10235 events
[i
].raise
= eb
->raise_method
->mhandle
;
10237 if (eb
->other_methods
) {
10238 events
[i
].other
= image_g_new0 (image
, MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10239 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10240 MonoReflectionMethodBuilder
*mb
=
10241 mono_array_get (eb
->other_methods
,
10242 MonoReflectionMethodBuilder
*, j
);
10243 events
[i
].other
[j
] = mb
->mhandle
;
10246 mono_save_custom_attrs (klass
->image
, &events
[i
], eb
->cattrs
);
10251 remove_instantiations_of (gpointer key
,
10253 gpointer user_data
)
10255 MonoType
*type
= (MonoType
*)key
;
10256 MonoClass
*klass
= (MonoClass
*)user_data
;
10258 if ((type
->type
== MONO_TYPE_GENERICINST
) && (type
->data
.generic_class
->container_class
== klass
))
10265 check_array_for_usertypes (MonoArray
*arr
)
10272 for (i
= 0; i
< mono_array_length (arr
); ++i
)
10273 CHECK_MONOTYPE (mono_array_get (arr
, gpointer
, i
));
10276 MonoReflectionType
*
10277 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
10280 MonoDomain
* domain
;
10281 MonoReflectionType
* res
;
10284 MONO_ARCH_SAVE_REGS
;
10286 domain
= mono_object_domain (tb
);
10287 klass
= mono_class_from_mono_type (tb
->type
.type
);
10290 * Check for user defined Type subclasses.
10292 CHECK_MONOTYPE (tb
->parent
);
10293 check_array_for_usertypes (tb
->interfaces
);
10295 for (i
= 0; i
< mono_array_length (tb
->fields
); ++i
) {
10296 MonoReflectionFieldBuilder
*fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10298 CHECK_MONOTYPE (fb
->type
);
10299 check_array_for_usertypes (fb
->modreq
);
10300 check_array_for_usertypes (fb
->modopt
);
10301 if (fb
->marshal_info
&& fb
->marshal_info
->marshaltyperef
)
10302 CHECK_MONOTYPE (fb
->marshal_info
->marshaltyperef
);
10307 for (i
= 0; i
< mono_array_length (tb
->methods
); ++i
) {
10308 MonoReflectionMethodBuilder
*mb
= mono_array_get (tb
->methods
, gpointer
, i
);
10310 CHECK_MONOTYPE (mb
->rtype
);
10311 check_array_for_usertypes (mb
->return_modreq
);
10312 check_array_for_usertypes (mb
->return_modopt
);
10313 check_array_for_usertypes (mb
->parameters
);
10314 if (mb
->param_modreq
)
10315 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
)
10316 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
));
10317 if (mb
->param_modopt
)
10318 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
)
10319 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
));
10324 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
10325 MonoReflectionCtorBuilder
*mb
= mono_array_get (tb
->ctors
, gpointer
, i
);
10327 check_array_for_usertypes (mb
->parameters
);
10328 if (mb
->param_modreq
)
10329 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
)
10330 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
));
10331 if (mb
->param_modopt
)
10332 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
)
10333 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
));
10338 mono_save_custom_attrs (klass
->image
, klass
, tb
->cattrs
);
10341 * we need to lock the domain because the lock will be taken inside
10342 * So, we need to keep the locking order correct.
10344 mono_loader_lock ();
10345 mono_domain_lock (domain
);
10346 if (klass
->wastypebuilder
) {
10347 mono_domain_unlock (domain
);
10348 mono_loader_unlock ();
10349 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10352 * Fields to set in klass:
10353 * the various flags: delegate/unicode/contextbound etc.
10355 klass
->flags
= tb
->attrs
;
10356 klass
->has_cctor
= 1;
10357 klass
->has_finalize
= 1;
10360 if (!((MonoDynamicImage
*)klass
->image
)->run
) {
10361 if (klass
->generic_container
) {
10362 /* FIXME: The code below can't handle generic classes */
10363 klass
->wastypebuilder
= TRUE
;
10364 mono_loader_unlock ();
10365 mono_domain_unlock (domain
);
10366 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10371 /* enums are done right away */
10372 if (!klass
->enumtype
)
10373 ensure_runtime_vtable (klass
);
10375 if (tb
->subtypes
) {
10376 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
10377 MonoReflectionTypeBuilder
*subtb
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
10378 mono_class_alloc_ext (klass
);
10379 klass
->ext
->nested_classes
= g_list_prepend_image (klass
->image
, klass
->ext
->nested_classes
, mono_class_from_mono_type (subtb
->type
.type
));
10383 klass
->nested_classes_inited
= TRUE
;
10385 /* fields and object layout */
10386 if (klass
->parent
) {
10387 if (!klass
->parent
->size_inited
)
10388 mono_class_init (klass
->parent
);
10389 klass
->instance_size
= klass
->parent
->instance_size
;
10390 klass
->sizes
.class_size
= 0;
10391 klass
->min_align
= klass
->parent
->min_align
;
10392 /* if the type has no fields we won't call the field_setup
10393 * routine which sets up klass->has_references.
10395 klass
->has_references
|= klass
->parent
->has_references
;
10397 klass
->instance_size
= sizeof (MonoObject
);
10398 klass
->min_align
= 1;
10401 /* FIXME: handle packing_size and instance_size */
10402 typebuilder_setup_fields (klass
);
10404 typebuilder_setup_properties (klass
);
10406 typebuilder_setup_events (klass
);
10408 klass
->wastypebuilder
= TRUE
;
10411 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10412 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10413 * we want to return normal System.MonoType objects, so clear these out from the cache.
10415 if (domain
->type_hash
&& klass
->generic_container
)
10416 mono_g_hash_table_foreach_remove (domain
->type_hash
, remove_instantiations_of
, klass
);
10418 mono_domain_unlock (domain
);
10419 mono_loader_unlock ();
10421 if (klass
->enumtype
&& !mono_class_is_valid_enum (klass
)) {
10422 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
10423 mono_raise_exception (mono_get_exception_type_load (tb
->name
, NULL
));
10426 res
= mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10427 g_assert (res
!= (MonoReflectionType
*)tb
);
10433 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
10435 MonoGenericParamFull
*param
;
10439 MONO_ARCH_SAVE_REGS
;
10441 param
= g_new0 (MonoGenericParamFull
, 1);
10443 if (gparam
->mbuilder
) {
10444 if (!gparam
->mbuilder
->generic_container
) {
10445 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)gparam
->mbuilder
->type
;
10446 MonoClass
*klass
= mono_class_from_mono_type (tb
->type
.type
);
10447 gparam
->mbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
10448 gparam
->mbuilder
->generic_container
->is_method
= TRUE
;
10450 param
->param
.owner
= gparam
->mbuilder
->generic_container
;
10451 } else if (gparam
->tbuilder
) {
10452 if (!gparam
->tbuilder
->generic_container
) {
10453 MonoClass
*klass
= mono_class_from_mono_type (gparam
->tbuilder
->type
.type
);
10454 gparam
->tbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
10455 gparam
->tbuilder
->generic_container
->owner
.klass
= klass
;
10457 param
->param
.owner
= gparam
->tbuilder
->generic_container
;
10460 param
->info
.name
= mono_string_to_utf8 (gparam
->name
);
10461 param
->param
.num
= gparam
->index
;
10463 image
= &gparam
->tbuilder
->module
->dynamic_image
->image
;
10464 pklass
= mono_class_from_generic_parameter ((MonoGenericParam
*) param
, image
, gparam
->mbuilder
!= NULL
);
10466 gparam
->type
.type
= &pklass
->byval_arg
;
10468 MOVING_GC_REGISTER (&pklass
->reflection_info
);
10469 pklass
->reflection_info
= gparam
; /* FIXME: GC pin gparam */
10473 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
10475 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
10476 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
10481 check_array_for_usertypes (sig
->arguments
);
10483 sigbuffer_init (&buf
, 32);
10485 sigbuffer_add_value (&buf
, 0x07);
10486 sigbuffer_add_value (&buf
, na
);
10487 for (i
= 0; i
< na
; ++i
) {
10488 MonoReflectionType
*type
= mono_type_array_get (sig
->arguments
, i
);
10489 encode_reflection_type (assembly
, type
, &buf
);
10492 buflen
= buf
.p
- buf
.buf
;
10493 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
10494 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
10495 sigbuffer_free (&buf
);
10501 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
10503 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
10504 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
10509 check_array_for_usertypes (sig
->arguments
);
10511 sigbuffer_init (&buf
, 32);
10513 sigbuffer_add_value (&buf
, 0x06);
10514 for (i
= 0; i
< na
; ++i
) {
10515 MonoReflectionType
*type
= mono_type_array_get (sig
->arguments
, i
);
10516 encode_reflection_type (assembly
, type
, &buf
);
10519 buflen
= buf
.p
- buf
.buf
;
10520 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
10521 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
10522 sigbuffer_free (&buf
);
10528 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10530 ReflectionMethodBuilder rmb
;
10531 MonoMethodSignature
*sig
;
10536 sig
= dynamic_method_to_signature (mb
);
10538 reflection_methodbuilder_from_dynamic_method (&rmb
, mb
);
10541 * Resolve references.
10544 * Every second entry in the refs array is reserved for storing handle_class,
10545 * which is needed by the ldtoken implementation in the JIT.
10547 rmb
.nrefs
= mb
->nrefs
;
10548 rmb
.refs
= g_new0 (gpointer
, mb
->nrefs
+ 1);
10549 for (i
= 0; i
< mb
->nrefs
; i
+= 2) {
10550 MonoClass
*handle_class
;
10552 MonoObject
*obj
= mono_array_get (mb
->refs
, MonoObject
*, i
);
10554 if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
10555 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
10557 * The referenced DynamicMethod should already be created by the managed
10558 * code, except in the case of circular references. In that case, we store
10559 * method in the refs array, and fix it up later when the referenced
10560 * DynamicMethod is created.
10562 if (method
->mhandle
) {
10563 ref
= method
->mhandle
;
10565 /* FIXME: GC object stored in unmanaged memory */
10568 /* FIXME: GC object stored in unmanaged memory */
10569 method
->referenced_by
= g_slist_append (method
->referenced_by
, mb
);
10571 handle_class
= mono_defaults
.methodhandle_class
;
10573 MonoException
*ex
= NULL
;
10574 ref
= resolve_object (mb
->module
->image
, obj
, &handle_class
, NULL
);
10576 ex
= mono_get_exception_type_load (NULL
, NULL
);
10577 else if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
10578 ex
= mono_security_core_clr_ensure_dynamic_method_resolved_object (ref
, handle_class
);
10582 mono_raise_exception (ex
);
10587 rmb
.refs
[i
] = ref
; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10588 rmb
.refs
[i
+ 1] = handle_class
;
10591 klass
= mb
->owner
? mono_class_from_mono_type (mb
->owner
->type
) : mono_defaults
.object_class
;
10593 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
10595 /* Fix up refs entries pointing at us */
10596 for (l
= mb
->referenced_by
; l
; l
= l
->next
) {
10597 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)l
->data
;
10598 MonoMethodWrapper
*wrapper
= (MonoMethodWrapper
*)method
->mhandle
;
10601 g_assert (method
->mhandle
);
10603 data
= (gpointer
*)wrapper
->method_data
;
10604 for (i
= 0; i
< GPOINTER_TO_UINT (data
[0]); i
+= 2) {
10605 if ((data
[i
+ 1] == mb
) && (data
[i
+ 1 + 1] == mono_defaults
.methodhandle_class
))
10606 data
[i
+ 1] = mb
->mhandle
;
10609 g_slist_free (mb
->referenced_by
);
10613 /* ilgen is no longer needed */
10617 #endif /* DISABLE_REFLECTION_EMIT */
10620 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10625 mono_runtime_free_method (
10626 mono_object_get_domain ((MonoObject
*)mb
), mb
->mhandle
);
10631 * mono_reflection_is_valid_dynamic_token:
10633 * Returns TRUE if token is valid.
10637 mono_reflection_is_valid_dynamic_token (MonoDynamicImage
*image
, guint32 token
)
10639 return mono_g_hash_table_lookup (image
->tokens
, GUINT_TO_POINTER (token
)) != NULL
;
10642 #ifndef DISABLE_REFLECTION_EMIT
10645 * mono_reflection_lookup_dynamic_token:
10647 * Finish the Builder object pointed to by TOKEN and return the corresponding
10648 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10649 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10652 * LOCKING: Take the loader lock
10655 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10657 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)image
;
10661 mono_loader_lock ();
10662 obj
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
10663 mono_loader_unlock ();
10666 g_assert_not_reached ();
10672 handle_class
= &klass
;
10673 return resolve_object (image
, obj
, handle_class
, context
);
10677 * ensure_complete_type:
10679 * Ensure that KLASS is completed if it is a dynamic type, or references
10683 ensure_complete_type (MonoClass
*klass
)
10685 if (klass
->image
->dynamic
&& !klass
->wastypebuilder
) {
10686 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10688 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10690 // Asserting here could break a lot of code
10691 //g_assert (klass->wastypebuilder);
10694 if (klass
->generic_class
) {
10695 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
10698 for (i
= 0; i
< inst
->type_argc
; ++i
) {
10699 ensure_complete_type (mono_class_from_mono_type (inst
->type_argv
[i
]));
10705 resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10707 gpointer result
= NULL
;
10709 if (strcmp (obj
->vtable
->klass
->name
, "String") == 0) {
10710 result
= mono_string_intern ((MonoString
*)obj
);
10711 *handle_class
= NULL
;
10713 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoType") == 0) {
10714 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
10716 MonoType
*inflated
= mono_class_inflate_generic_type (tb
->type
, context
);
10717 result
= mono_class_from_mono_type (inflated
);
10718 mono_metadata_free_type (inflated
);
10720 result
= mono_class_from_mono_type (tb
->type
);
10722 *handle_class
= mono_defaults
.typehandle_class
;
10724 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoMethod") == 0 ||
10725 strcmp (obj
->vtable
->klass
->name
, "MonoCMethod") == 0 ||
10726 strcmp (obj
->vtable
->klass
->name
, "MonoGenericCMethod") == 0 ||
10727 strcmp (obj
->vtable
->klass
->name
, "MonoGenericMethod") == 0) {
10728 result
= ((MonoReflectionMethod
*)obj
)->method
;
10730 result
= mono_class_inflate_generic_method (result
, context
);
10731 *handle_class
= mono_defaults
.methodhandle_class
;
10733 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodBuilder") == 0) {
10734 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
10735 result
= mb
->mhandle
;
10737 /* Type is not yet created */
10738 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
10740 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10743 * Hopefully this has been filled in by calling CreateType() on the
10747 * TODO: This won't work if the application finishes another
10748 * TypeBuilder instance instead of this one.
10750 result
= mb
->mhandle
;
10753 result
= mono_class_inflate_generic_method (result
, context
);
10754 *handle_class
= mono_defaults
.methodhandle_class
;
10755 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder") == 0) {
10756 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
10758 result
= cb
->mhandle
;
10760 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)cb
->type
;
10762 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10763 result
= cb
->mhandle
;
10766 result
= mono_class_inflate_generic_method (result
, context
);
10767 *handle_class
= mono_defaults
.methodhandle_class
;
10768 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoField") == 0) {
10769 MonoClassField
*field
= ((MonoReflectionField
*)obj
)->field
;
10771 ensure_complete_type (field
->parent
);
10773 MonoType
*inflated
= mono_class_inflate_generic_type (&field
->parent
->byval_arg
, context
);
10774 MonoClass
*class = mono_class_from_mono_type (inflated
);
10775 MonoClassField
*inflated_field
;
10776 gpointer iter
= NULL
;
10777 mono_metadata_free_type (inflated
);
10778 while ((inflated_field
= mono_class_get_fields (class, &iter
))) {
10779 if (!strcmp (field
->name
, inflated_field
->name
))
10782 g_assert (inflated_field
&& !strcmp (field
->name
, inflated_field
->name
));
10783 result
= inflated_field
;
10787 *handle_class
= mono_defaults
.fieldhandle_class
;
10789 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldBuilder") == 0) {
10790 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
10791 result
= fb
->handle
;
10794 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
10796 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10797 result
= fb
->handle
;
10800 if (fb
->handle
&& fb
->handle
->parent
->generic_container
) {
10801 MonoClass
*klass
= fb
->handle
->parent
;
10802 MonoType
*type
= mono_class_inflate_generic_type (&klass
->byval_arg
, context
);
10803 MonoClass
*inflated
= mono_class_from_mono_type (type
);
10805 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (fb
->handle
));
10807 mono_metadata_free_type (type
);
10809 *handle_class
= mono_defaults
.fieldhandle_class
;
10810 } else if (strcmp (obj
->vtable
->klass
->name
, "TypeBuilder") == 0) {
10811 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
10814 klass
= tb
->type
.type
->data
.klass
;
10815 if (klass
->wastypebuilder
) {
10816 /* Already created */
10820 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10821 result
= tb
->type
.type
->data
.klass
;
10824 *handle_class
= mono_defaults
.typehandle_class
;
10825 } else if (strcmp (obj
->vtable
->klass
->name
, "SignatureHelper") == 0) {
10826 MonoReflectionSigHelper
*helper
= (MonoReflectionSigHelper
*)obj
;
10827 MonoMethodSignature
*sig
;
10830 if (helper
->arguments
)
10831 nargs
= mono_array_length (helper
->arguments
);
10835 sig
= mono_metadata_signature_alloc (image
, nargs
);
10836 sig
->explicit_this
= helper
->call_conv
& 64 ? 1 : 0;
10837 sig
->hasthis
= helper
->call_conv
& 32 ? 1 : 0;
10839 if (helper
->call_conv
== 0) /* unmanaged */
10840 sig
->call_convention
= helper
->unmanaged_call_conv
- 1;
10842 if (helper
->call_conv
& 0x02)
10843 sig
->call_convention
= MONO_CALL_VARARG
;
10845 sig
->call_convention
= MONO_CALL_DEFAULT
;
10847 sig
->param_count
= nargs
;
10848 /* TODO: Copy type ? */
10849 sig
->ret
= helper
->return_type
->type
;
10850 for (i
= 0; i
< nargs
; ++i
) {
10851 MonoReflectionType
*rt
= mono_type_array_get (helper
->arguments
, i
);
10852 sig
->params
[i
] = rt
->type
;
10856 *handle_class
= NULL
;
10857 } else if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
10858 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
10859 /* Already created by the managed code */
10860 g_assert (method
->mhandle
);
10861 result
= method
->mhandle
;
10862 *handle_class
= mono_defaults
.methodhandle_class
;
10863 } else if (strcmp (obj
->vtable
->klass
->name
, "GenericTypeParameterBuilder") == 0) {
10864 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
10865 MonoType
*type
= mono_class_inflate_generic_type (tb
->type
, context
);
10866 result
= mono_class_from_mono_type (type
);
10867 *handle_class
= mono_defaults
.typehandle_class
;
10869 mono_metadata_free_type (type
);
10870 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoGenericClass") == 0) {
10871 MonoReflectionGenericClass
*ref
= (MonoReflectionGenericClass
*)obj
;
10872 MonoType
*type
= mono_class_inflate_generic_type (ref
->type
.type
, context
);
10873 result
= mono_class_from_mono_type (type
);
10874 *handle_class
= mono_defaults
.typehandle_class
;
10876 mono_metadata_free_type (type
);
10877 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldOnTypeBuilderInst") == 0) {
10878 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
10879 MonoClass
*inflated
;
10882 type
= mono_class_inflate_generic_type (f
->inst
->type
.type
, context
);
10883 inflated
= mono_class_from_mono_type (type
);
10885 g_assert (f
->fb
->handle
);
10886 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (f
->fb
->handle
));
10888 mono_metadata_free_type (type
);
10889 *handle_class
= mono_defaults
.fieldhandle_class
;
10890 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
10891 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
10892 MonoType
*type
= mono_class_inflate_generic_type (c
->inst
->type
.type
, context
);
10893 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
10894 g_assert (c
->cb
->mhandle
);
10895 result
= inflate_mono_method (inflated_klass
, c
->cb
->mhandle
, (MonoObject
*)c
->cb
);
10896 *handle_class
= mono_defaults
.methodhandle_class
;
10897 mono_metadata_free_type (type
);
10898 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodOnTypeBuilderInst") == 0) {
10899 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
10900 MonoType
*type
= mono_class_inflate_generic_type (m
->inst
->type
.type
, context
);
10901 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
10902 g_assert (m
->mb
->mhandle
);
10903 result
= inflate_mono_method (inflated_klass
, m
->mb
->mhandle
, (MonoObject
*)m
->mb
);
10904 *handle_class
= mono_defaults
.methodhandle_class
;
10905 mono_metadata_free_type (type
);
10907 g_print (obj
->vtable
->klass
->name
);
10908 g_assert_not_reached ();
10913 #else /* DISABLE_REFLECTION_EMIT */
10916 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
10918 g_assert_not_reached ();
10923 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
10925 g_assert_not_reached ();
10929 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
10931 g_assert_not_reached ();
10935 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
10937 g_assert_not_reached ();
10941 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
10943 g_assert_not_reached ();
10947 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
10949 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10953 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
10955 g_assert_not_reached ();
10958 MonoReflectionModule
*
10959 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
10961 g_assert_not_reached ();
10966 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
10968 g_assert_not_reached ();
10973 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
10975 g_assert_not_reached ();
10980 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
10981 gboolean create_methodspec
, gboolean register_token
)
10983 g_assert_not_reached ();
10988 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
10993 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
10994 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
10997 g_assert_not_reached ();
11001 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
11004 *num_overrides
= 0;
11007 MonoReflectionEvent
*
11008 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
11010 g_assert_not_reached ();
11014 MonoReflectionType
*
11015 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
11017 g_assert_not_reached ();
11022 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
11024 g_assert_not_reached ();
11028 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
11030 g_assert_not_reached ();
11035 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
11037 g_assert_not_reached ();
11042 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
11047 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
11052 #endif /* DISABLE_REFLECTION_EMIT */
11054 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
11055 const static guint32 declsec_flags_map
[] = {
11056 0x00000000, /* empty */
11057 MONO_DECLSEC_FLAG_REQUEST
, /* SECURITY_ACTION_REQUEST (x01) */
11058 MONO_DECLSEC_FLAG_DEMAND
, /* SECURITY_ACTION_DEMAND (x02) */
11059 MONO_DECLSEC_FLAG_ASSERT
, /* SECURITY_ACTION_ASSERT (x03) */
11060 MONO_DECLSEC_FLAG_DENY
, /* SECURITY_ACTION_DENY (x04) */
11061 MONO_DECLSEC_FLAG_PERMITONLY
, /* SECURITY_ACTION_PERMITONLY (x05) */
11062 MONO_DECLSEC_FLAG_LINKDEMAND
, /* SECURITY_ACTION_LINKDEMAND (x06) */
11063 MONO_DECLSEC_FLAG_INHERITANCEDEMAND
, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11064 MONO_DECLSEC_FLAG_REQUEST_MINIMUM
, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11065 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL
, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11066 MONO_DECLSEC_FLAG_REQUEST_REFUSE
, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11067 MONO_DECLSEC_FLAG_PREJIT_GRANT
, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11068 MONO_DECLSEC_FLAG_PREJIT_DENY
, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11069 MONO_DECLSEC_FLAG_NONCAS_DEMAND
, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11070 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11071 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11072 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11073 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11074 MONO_DECLSEC_FLAG_DEMAND_CHOICE
, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11078 * Returns flags that includes all available security action associated to the handle.
11079 * @token: metadata token (either for a class or a method)
11080 * @image: image where resides the metadata.
11083 mono_declsec_get_flags (MonoImage
*image
, guint32 token
)
11085 int index
= mono_metadata_declsec_from_index (image
, token
);
11086 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11087 guint32 result
= 0;
11091 /* HasSecurity can be present for other, not specially encoded, attributes,
11092 e.g. SuppressUnmanagedCodeSecurityAttribute */
11096 for (i
= index
; i
< t
->rows
; i
++) {
11097 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11099 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11100 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
11103 action
= cols
[MONO_DECL_SECURITY_ACTION
];
11104 if ((action
>= MONO_DECLSEC_ACTION_MIN
) && (action
<= MONO_DECLSEC_ACTION_MAX
)) {
11105 result
|= declsec_flags_map
[action
];
11107 g_assert_not_reached ();
11114 * Get the security actions (in the form of flags) associated with the specified method.
11116 * @method: The method for which we want the declarative security flags.
11117 * Return the declarative security flags for the method (only).
11119 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11120 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11123 mono_declsec_flags_from_method (MonoMethod
*method
)
11125 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11126 /* FIXME: No cache (for the moment) */
11127 guint32 idx
= mono_method_get_index (method
);
11128 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11129 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11130 return mono_declsec_get_flags (method
->klass
->image
, idx
);
11136 * Get the security actions (in the form of flags) associated with the specified class.
11138 * @klass: The class for which we want the declarative security flags.
11139 * Return the declarative security flags for the class.
11141 * Note: We cache the flags inside the MonoClass structure as this will get
11142 * called very often (at least for each method).
11145 mono_declsec_flags_from_class (MonoClass
*klass
)
11147 if (klass
->flags
& TYPE_ATTRIBUTE_HAS_SECURITY
) {
11148 if (!klass
->ext
|| !klass
->ext
->declsec_flags
) {
11151 idx
= mono_metadata_token_index (klass
->type_token
);
11152 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11153 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11154 mono_loader_lock ();
11155 mono_class_alloc_ext (klass
);
11156 mono_loader_unlock ();
11157 /* we cache the flags on classes */
11158 klass
->ext
->declsec_flags
= mono_declsec_get_flags (klass
->image
, idx
);
11160 return klass
->ext
->declsec_flags
;
11166 * Get the security actions (in the form of flags) associated with the specified assembly.
11168 * @assembly: The assembly for which we want the declarative security flags.
11169 * Return the declarative security flags for the assembly.
11172 mono_declsec_flags_from_assembly (MonoAssembly
*assembly
)
11174 guint32 idx
= 1; /* there is only one assembly */
11175 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11176 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
11177 return mono_declsec_get_flags (assembly
->image
, idx
);
11182 * Fill actions for the specific index (which may either be an encoded class token or
11183 * an encoded method token) from the metadata image.
11184 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11187 fill_actions_from_index (MonoImage
*image
, guint32 token
, MonoDeclSecurityActions
* actions
,
11188 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11190 MonoBoolean result
= FALSE
;
11192 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11193 int index
= mono_metadata_declsec_from_index (image
, token
);
11196 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11197 for (i
= index
; i
< t
->rows
; i
++) {
11198 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11200 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
11203 /* if present only replace (class) permissions with method permissions */
11204 /* if empty accept either class or method permissions */
11205 if (cols
[MONO_DECL_SECURITY_ACTION
] == id_std
) {
11206 if (!actions
->demand
.blob
) {
11207 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11208 actions
->demand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11209 actions
->demand
.blob
= (char*) (blob
+ 2);
11210 actions
->demand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11213 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_noncas
) {
11214 if (!actions
->noncasdemand
.blob
) {
11215 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11216 actions
->noncasdemand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11217 actions
->noncasdemand
.blob
= (char*) (blob
+ 2);
11218 actions
->noncasdemand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11221 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_choice
) {
11222 if (!actions
->demandchoice
.blob
) {
11223 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11224 actions
->demandchoice
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11225 actions
->demandchoice
.blob
= (char*) (blob
+ 2);
11226 actions
->demandchoice
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11236 mono_declsec_get_class_demands_params (MonoClass
*klass
, MonoDeclSecurityActions
* demands
,
11237 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11239 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
11240 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11241 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11242 return fill_actions_from_index (klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
11246 mono_declsec_get_method_demands_params (MonoMethod
*method
, MonoDeclSecurityActions
* demands
,
11247 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11249 guint32 idx
= mono_method_get_index (method
);
11250 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11251 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11252 return fill_actions_from_index (method
->klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
11256 * Collect all actions (that requires to generate code in mini) assigned for
11257 * the specified method.
11258 * Note: Don't use the content of actions if the function return FALSE.
11261 mono_declsec_get_demands (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
11263 guint32 mask
= MONO_DECLSEC_FLAG_DEMAND
| MONO_DECLSEC_FLAG_NONCAS_DEMAND
|
11264 MONO_DECLSEC_FLAG_DEMAND_CHOICE
;
11265 MonoBoolean result
= FALSE
;
11268 /* quick exit if no declarative security is present in the metadata */
11269 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11272 /* we want the original as the wrapper is "free" of the security informations */
11273 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11274 method
= mono_marshal_method_from_wrapper (method
);
11279 /* First we look for method-level attributes */
11280 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11281 mono_class_init (method
->klass
);
11282 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11284 result
= mono_declsec_get_method_demands_params (method
, demands
,
11285 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
11288 /* Here we use (or create) the class declarative cache to look for demands */
11289 flags
= mono_declsec_flags_from_class (method
->klass
);
11290 if (flags
& mask
) {
11292 mono_class_init (method
->klass
);
11293 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11295 result
|= mono_declsec_get_class_demands_params (method
->klass
, demands
,
11296 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
11299 /* The boolean return value is used as a shortcut in case nothing needs to
11300 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11306 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11308 * Note: Don't use the content of actions if the function return FALSE.
11311 mono_declsec_get_linkdemands (MonoMethod
*method
, MonoDeclSecurityActions
* klass
, MonoDeclSecurityActions
*cmethod
)
11313 MonoBoolean result
= FALSE
;
11316 /* quick exit if no declarative security is present in the metadata */
11317 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11320 /* we want the original as the wrapper is "free" of the security informations */
11321 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11322 method
= mono_marshal_method_from_wrapper (method
);
11327 /* results are independant - zeroize both */
11328 memset (cmethod
, 0, sizeof (MonoDeclSecurityActions
));
11329 memset (klass
, 0, sizeof (MonoDeclSecurityActions
));
11331 /* First we look for method-level attributes */
11332 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11333 mono_class_init (method
->klass
);
11335 result
= mono_declsec_get_method_demands_params (method
, cmethod
,
11336 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
11339 /* Here we use (or create) the class declarative cache to look for demands */
11340 flags
= mono_declsec_flags_from_class (method
->klass
);
11341 if (flags
& (MONO_DECLSEC_FLAG_LINKDEMAND
| MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
| MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
)) {
11342 mono_class_init (method
->klass
);
11344 result
|= mono_declsec_get_class_demands_params (method
->klass
, klass
,
11345 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
11352 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11354 * @klass The inherited class - this is the class that provides the security check (attributes)
11356 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11358 * Note: Don't use the content of actions if the function return FALSE.
11361 mono_declsec_get_inheritdemands_class (MonoClass
*klass
, MonoDeclSecurityActions
* demands
)
11363 MonoBoolean result
= FALSE
;
11366 /* quick exit if no declarative security is present in the metadata */
11367 if (!klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11370 /* Here we use (or create) the class declarative cache to look for demands */
11371 flags
= mono_declsec_flags_from_class (klass
);
11372 if (flags
& (MONO_DECLSEC_FLAG_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
)) {
11373 mono_class_init (klass
);
11374 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11376 result
|= mono_declsec_get_class_demands_params (klass
, demands
,
11377 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
11384 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11386 * Note: Don't use the content of actions if the function return FALSE.
11389 mono_declsec_get_inheritdemands_method (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
11391 /* quick exit if no declarative security is present in the metadata */
11392 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11395 /* we want the original as the wrapper is "free" of the security informations */
11396 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11397 method
= mono_marshal_method_from_wrapper (method
);
11402 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11403 mono_class_init (method
->klass
);
11404 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11406 return mono_declsec_get_method_demands_params (method
, demands
,
11407 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
11414 get_declsec_action (MonoImage
*image
, guint32 token
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11416 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11420 int index
= mono_metadata_declsec_from_index (image
, token
);
11424 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11425 for (i
= index
; i
< t
->rows
; i
++) {
11426 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11428 /* shortcut - index are ordered */
11429 if (token
!= cols
[MONO_DECL_SECURITY_PARENT
])
11432 if (cols
[MONO_DECL_SECURITY_ACTION
] == action
) {
11433 const char *metadata
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11434 entry
->blob
= (char*) (metadata
+ 2);
11435 entry
->size
= mono_metadata_decode_blob_size (metadata
, &metadata
);
11444 mono_declsec_get_method_action (MonoMethod
*method
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11446 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11447 guint32 idx
= mono_method_get_index (method
);
11448 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11449 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11450 return get_declsec_action (method
->klass
->image
, idx
, action
, entry
);
11456 mono_declsec_get_class_action (MonoClass
*klass
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11459 guint32 flags
= mono_declsec_flags_from_class (klass
);
11460 if (declsec_flags_map
[action
] & flags
) {
11461 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
11462 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11463 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11464 return get_declsec_action (klass
->image
, idx
, action
, entry
);
11470 mono_declsec_get_assembly_action (MonoAssembly
*assembly
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11472 guint32 idx
= 1; /* there is only one assembly */
11473 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11474 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
11476 return get_declsec_action (assembly
->image
, idx
, action
, entry
);
11480 mono_reflection_call_is_assignable_to (MonoClass
*klass
, MonoClass
*oklass
)
11482 MonoObject
*res
, *exc
;
11484 static MonoClass
*System_Reflection_Emit_TypeBuilder
= NULL
;
11485 static MonoMethod
*method
= NULL
;
11487 if (!System_Reflection_Emit_TypeBuilder
) {
11488 System_Reflection_Emit_TypeBuilder
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection.Emit", "TypeBuilder");
11489 g_assert (System_Reflection_Emit_TypeBuilder
);
11491 if (method
== NULL
) {
11492 method
= mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder
, "IsAssignableTo", 1);
11497 * The result of mono_type_get_object () might be a System.MonoType but we
11498 * need a TypeBuilder so use klass->reflection_info.
11500 g_assert (klass
->reflection_info
);
11501 g_assert (!strcmp (((MonoObject
*)(klass
->reflection_info
))->vtable
->klass
->name
, "TypeBuilder"));
11503 params
[0] = mono_type_get_object (mono_domain_get (), &oklass
->byval_arg
);
11505 res
= mono_runtime_invoke (method
, (MonoObject
*)(klass
->reflection_info
), params
, &exc
);
11509 return *(MonoBoolean
*)mono_object_unbox (res
);