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>
41 static void* reflection_info_desc
= NULL
;
42 #define MOVING_GC_REGISTER(addr) do { \
43 if (!reflection_info_desc) { \
45 reflection_info_desc = mono_gc_make_descr_from_bitmap (&bmap, 1); \
47 mono_gc_register_root ((char*)(addr), sizeof (gpointer), reflection_info_desc); \
50 #define MOVING_GC_REGISTER(addr)
54 check_array_for_usertypes (MonoArray
*arr
)
61 for (i
= 0; i
< mono_array_length (arr
); ++i
)
62 CHECK_MONOTYPE (mono_array_get (arr
, gpointer
, i
));
71 #define TEXT_OFFSET 512
72 #define CLI_H_SIZE 136
73 #define FILE_ALIGN 512
74 #define VIRT_ALIGN 8192
75 #define START_TEXT_RVA 0x00002000
78 MonoReflectionILGen
*ilgen
;
79 MonoReflectionType
*rtype
;
80 MonoArray
*parameters
;
81 MonoArray
*generic_params
;
82 MonoGenericContainer
*generic_container
;
88 guint32
*table_idx
; /* note: it's a pointer */
92 MonoBoolean init_locals
;
93 MonoBoolean skip_visibility
;
94 MonoArray
*return_modreq
;
95 MonoArray
*return_modopt
;
96 MonoArray
*param_modreq
;
97 MonoArray
*param_modopt
;
98 MonoArray
*permissions
;
103 int charset
, extra_flags
, native_cc
;
104 MonoString
*dll
, *dllentry
;
105 } ReflectionMethodBuilder
;
109 MonoReflectionGenericParam
*gparam
;
110 } GenericParamTableEntry
;
112 const unsigned char table_sizes
[MONO_TABLE_NUM
] = {
122 MONO_INTERFACEIMPL_SIZE
,
123 MONO_MEMBERREF_SIZE
, /* 0x0A */
125 MONO_CUSTOM_ATTR_SIZE
,
126 MONO_FIELD_MARSHAL_SIZE
,
127 MONO_DECL_SECURITY_SIZE
,
128 MONO_CLASS_LAYOUT_SIZE
,
129 MONO_FIELD_LAYOUT_SIZE
, /* 0x10 */
130 MONO_STAND_ALONE_SIGNATURE_SIZE
,
134 MONO_PROPERTY_MAP_SIZE
,
137 MONO_METHOD_SEMA_SIZE
,
138 MONO_METHODIMPL_SIZE
,
139 MONO_MODULEREF_SIZE
, /* 0x1A */
145 MONO_ASSEMBLY_SIZE
, /* 0x20 */
146 MONO_ASSEMBLY_PROCESSOR_SIZE
,
147 MONO_ASSEMBLYOS_SIZE
,
148 MONO_ASSEMBLYREF_SIZE
,
149 MONO_ASSEMBLYREFPROC_SIZE
,
150 MONO_ASSEMBLYREFOS_SIZE
,
154 MONO_NESTED_CLASS_SIZE
,
156 MONO_GENERICPARAM_SIZE
, /* 0x2A */
157 MONO_METHODSPEC_SIZE
,
158 MONO_GENPARCONSTRAINT_SIZE
162 static void reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
);
163 static void reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
);
164 static guint32
mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
);
165 static guint32
mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
);
166 static guint32
mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
);
167 static guint32
mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
);
168 static guint32
mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*cb
);
169 static guint32
mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
);
170 static void mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
);
171 static guint32
encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
);
172 static guint32
encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
);
173 static char* type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
);
174 static void ensure_runtime_vtable (MonoClass
*klass
);
175 static gpointer
resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
);
176 static void encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
);
177 static void get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
);
178 static MonoObject
*mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
);
179 static MonoReflectionType
*mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
);
180 static MonoType
* mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
);
181 static guint32
mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
);
182 static guint32
encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
);
185 mono_reflection_init (void)
190 sigbuffer_init (SigBuffer
*buf
, int size
)
192 buf
->buf
= g_malloc (size
);
194 buf
->end
= buf
->buf
+ size
;
198 sigbuffer_make_room (SigBuffer
*buf
, int size
)
200 if (buf
->end
- buf
->p
< size
) {
201 int new_size
= buf
->end
- buf
->buf
+ size
+ 32;
202 char *p
= g_realloc (buf
->buf
, new_size
);
203 size
= buf
->p
- buf
->buf
;
206 buf
->end
= buf
->buf
+ new_size
;
211 sigbuffer_add_value (SigBuffer
*buf
, guint32 val
)
213 sigbuffer_make_room (buf
, 6);
214 mono_metadata_encode_value (val
, buf
->p
, &buf
->p
);
218 sigbuffer_add_byte (SigBuffer
*buf
, guint8 val
)
220 sigbuffer_make_room (buf
, 1);
226 sigbuffer_add_mem (SigBuffer
*buf
, char *p
, guint32 size
)
228 sigbuffer_make_room (buf
, size
);
229 memcpy (buf
->p
, p
, size
);
234 sigbuffer_free (SigBuffer
*buf
)
242 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
246 image_g_malloc (MonoImage
*image
, guint size
)
249 return mono_image_alloc (image
, size
);
251 return g_malloc (size
);
257 * Allocate memory from the @image mempool if it is non-NULL. Otherwise, allocate memory
261 image_g_malloc0 (MonoImage
*image
, guint size
)
264 return mono_image_alloc0 (image
, size
);
266 return g_malloc0 (size
);
270 image_strdup (MonoImage
*image
, const char *s
)
273 return mono_image_strdup (image
, s
);
278 #define image_g_new(image,struct_type, n_structs) \
279 ((struct_type *) image_g_malloc (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
281 #define image_g_new0(image,struct_type, n_structs) \
282 ((struct_type *) image_g_malloc0 (image, ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
286 alloc_table (MonoDynamicTable
*table
, guint nrows
)
289 g_assert (table
->columns
);
290 if (nrows
+ 1 >= table
->alloc_rows
) {
291 while (nrows
+ 1 >= table
->alloc_rows
) {
292 if (table
->alloc_rows
== 0)
293 table
->alloc_rows
= 16;
295 table
->alloc_rows
*= 2;
298 table
->values
= g_renew (guint32
, table
->values
, (table
->alloc_rows
) * table
->columns
);
303 make_room_in_stream (MonoDynamicStream
*stream
, int size
)
305 if (size
<= stream
->alloc_size
)
308 while (stream
->alloc_size
<= size
) {
309 if (stream
->alloc_size
< 4096)
310 stream
->alloc_size
= 4096;
312 stream
->alloc_size
*= 2;
315 stream
->data
= g_realloc (stream
->data
, stream
->alloc_size
);
319 string_heap_insert (MonoDynamicStream
*sh
, const char *str
)
323 gpointer oldkey
, oldval
;
325 if (g_hash_table_lookup_extended (sh
->hash
, str
, &oldkey
, &oldval
))
326 return GPOINTER_TO_UINT (oldval
);
328 len
= strlen (str
) + 1;
331 make_room_in_stream (sh
, idx
+ len
);
334 * We strdup the string even if we already copy them in sh->data
335 * so that the string pointers in the hash remain valid even if
336 * we need to realloc sh->data. We may want to avoid that later.
338 g_hash_table_insert (sh
->hash
, g_strdup (str
), GUINT_TO_POINTER (idx
));
339 memcpy (sh
->data
+ idx
, str
, len
);
345 string_heap_insert_mstring (MonoDynamicStream
*sh
, MonoString
*str
)
347 char *name
= mono_string_to_utf8 (str
);
349 idx
= string_heap_insert (sh
, name
);
355 string_heap_init (MonoDynamicStream
*sh
)
358 sh
->alloc_size
= 4096;
359 sh
->data
= g_malloc (4096);
360 sh
->hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
361 string_heap_insert (sh
, "");
365 mono_image_add_stream_data (MonoDynamicStream
*stream
, const char *data
, guint32 len
)
369 make_room_in_stream (stream
, stream
->index
+ len
);
370 memcpy (stream
->data
+ stream
->index
, data
, len
);
372 stream
->index
+= len
;
374 * align index? Not without adding an additional param that controls it since
375 * we may store a blob value in pieces.
381 mono_image_add_stream_zero (MonoDynamicStream
*stream
, guint32 len
)
385 make_room_in_stream (stream
, stream
->index
+ len
);
386 memset (stream
->data
+ stream
->index
, 0, len
);
388 stream
->index
+= len
;
393 stream_data_align (MonoDynamicStream
*stream
)
396 guint32 count
= stream
->index
% 4;
398 /* we assume the stream data will be aligned */
400 mono_image_add_stream_data (stream
, buf
, 4 - count
);
404 mono_blob_entry_hash (const char* str
)
408 len
= mono_metadata_decode_blob_size (str
, &str
);
412 for (str
+= 1; str
< end
; str
++)
413 h
= (h
<< 5) - h
+ *str
;
421 mono_blob_entry_equal (const char *str1
, const char *str2
) {
425 len
= mono_metadata_decode_blob_size (str1
, &end1
);
426 len2
= mono_metadata_decode_blob_size (str2
, &end2
);
429 return memcmp (end1
, end2
, len
) == 0;
433 add_to_blob_cached (MonoDynamicImage
*assembly
, char *b1
, int s1
, char *b2
, int s2
)
437 gpointer oldkey
, oldval
;
439 copy
= g_malloc (s1
+s2
);
440 memcpy (copy
, b1
, s1
);
441 memcpy (copy
+ s1
, b2
, s2
);
442 if (g_hash_table_lookup_extended (assembly
->blob_cache
, copy
, &oldkey
, &oldval
)) {
444 idx
= GPOINTER_TO_UINT (oldval
);
446 idx
= mono_image_add_stream_data (&assembly
->blob
, b1
, s1
);
447 mono_image_add_stream_data (&assembly
->blob
, b2
, s2
);
448 g_hash_table_insert (assembly
->blob_cache
, copy
, GUINT_TO_POINTER (idx
));
454 sigbuffer_add_to_blob_cached (MonoDynamicImage
*assembly
, SigBuffer
*buf
)
458 guint32 size
= buf
->p
- buf
->buf
;
460 g_assert (size
<= (buf
->end
- buf
->buf
));
461 mono_metadata_encode_value (size
, b
, &b
);
462 return add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, buf
->buf
, size
);
466 * Copy len * nelem bytes from val to dest, swapping bytes to LE if necessary.
467 * dest may be misaligned.
470 swap_with_size (char *dest
, const char* val
, int len
, int nelem
) {
471 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
474 for (elem
= 0; elem
< nelem
; ++elem
) {
500 g_assert_not_reached ();
506 memcpy (dest
, val
, len
* nelem
);
511 add_mono_string_to_blob_cached (MonoDynamicImage
*assembly
, MonoString
*str
)
515 guint32 idx
= 0, len
;
517 len
= str
->length
* 2;
518 mono_metadata_encode_value (len
, b
, &b
);
519 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
521 char *swapped
= g_malloc (2 * mono_string_length (str
));
522 const char *p
= (const char*)mono_string_chars (str
);
524 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
525 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
529 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
534 /* modified version needed to handle building corlib */
536 my_mono_class_from_mono_type (MonoType
*type
) {
537 switch (type
->type
) {
538 case MONO_TYPE_ARRAY
:
540 case MONO_TYPE_SZARRAY
:
541 case MONO_TYPE_GENERICINST
:
542 return mono_class_from_mono_type (type
);
545 g_assert (type
->data
.generic_param
->pklass
);
546 return type
->data
.generic_param
->pklass
;
548 /* should be always valid when we reach this case... */
549 return type
->data
.klass
;
554 default_class_from_mono_type (MonoType
*type
)
556 switch (type
->type
) {
557 case MONO_TYPE_OBJECT
:
558 return mono_defaults
.object_class
;
560 return mono_defaults
.void_class
;
561 case MONO_TYPE_BOOLEAN
:
562 return mono_defaults
.boolean_class
;
564 return mono_defaults
.char_class
;
566 return mono_defaults
.sbyte_class
;
568 return mono_defaults
.byte_class
;
570 return mono_defaults
.int16_class
;
572 return mono_defaults
.uint16_class
;
574 return mono_defaults
.int32_class
;
576 return mono_defaults
.uint32_class
;
578 return mono_defaults
.int_class
;
580 return mono_defaults
.uint_class
;
582 return mono_defaults
.int64_class
;
584 return mono_defaults
.uint64_class
;
586 return mono_defaults
.single_class
;
588 return mono_defaults
.double_class
;
589 case MONO_TYPE_STRING
:
590 return mono_defaults
.string_class
;
592 g_warning ("default_class_from_mono_type: implement me 0x%02x\n", type
->type
);
593 g_assert_not_reached ();
600 encode_generic_class (MonoDynamicImage
*assembly
, MonoGenericClass
*gclass
, SigBuffer
*buf
)
603 MonoGenericInst
*class_inst
;
608 class_inst
= gclass
->context
.class_inst
;
610 sigbuffer_add_value (buf
, MONO_TYPE_GENERICINST
);
611 klass
= gclass
->container_class
;
612 sigbuffer_add_value (buf
, klass
->byval_arg
.type
);
613 sigbuffer_add_value (buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
615 sigbuffer_add_value (buf
, class_inst
->type_argc
);
616 for (i
= 0; i
< class_inst
->type_argc
; ++i
)
617 encode_type (assembly
, class_inst
->type_argv
[i
], buf
);
622 encode_type (MonoDynamicImage
*assembly
, MonoType
*type
, SigBuffer
*buf
)
625 g_assert_not_reached ();
630 sigbuffer_add_value (buf
, MONO_TYPE_BYREF
);
634 case MONO_TYPE_BOOLEAN
:
648 case MONO_TYPE_STRING
:
649 case MONO_TYPE_OBJECT
:
650 case MONO_TYPE_TYPEDBYREF
:
651 sigbuffer_add_value (buf
, type
->type
);
654 sigbuffer_add_value (buf
, type
->type
);
655 encode_type (assembly
, type
->data
.type
, buf
);
657 case MONO_TYPE_SZARRAY
:
658 sigbuffer_add_value (buf
, type
->type
);
659 encode_type (assembly
, &type
->data
.klass
->byval_arg
, buf
);
661 case MONO_TYPE_VALUETYPE
:
662 case MONO_TYPE_CLASS
: {
663 MonoClass
*k
= mono_class_from_mono_type (type
);
665 if (k
->generic_container
) {
666 MonoGenericClass
*gclass
= mono_metadata_lookup_generic_class (k
, k
->generic_container
->context
.class_inst
, TRUE
);
667 encode_generic_class (assembly
, gclass
, buf
);
670 * Make sure we use the correct type.
672 sigbuffer_add_value (buf
, k
->byval_arg
.type
);
674 * ensure only non-byref gets passed to mono_image_typedef_or_ref(),
675 * otherwise two typerefs could point to the same type, leading to
676 * verification errors.
678 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, &k
->byval_arg
));
682 case MONO_TYPE_ARRAY
:
683 sigbuffer_add_value (buf
, type
->type
);
684 encode_type (assembly
, &type
->data
.array
->eklass
->byval_arg
, buf
);
685 sigbuffer_add_value (buf
, type
->data
.array
->rank
);
686 sigbuffer_add_value (buf
, 0); /* FIXME: set to 0 for now */
687 sigbuffer_add_value (buf
, 0);
689 case MONO_TYPE_GENERICINST
:
690 encode_generic_class (assembly
, type
->data
.generic_class
, buf
);
694 sigbuffer_add_value (buf
, type
->type
);
695 sigbuffer_add_value (buf
, type
->data
.generic_param
->num
);
698 g_error ("need to encode type %x", type
->type
);
703 encode_reflection_type (MonoDynamicImage
*assembly
, MonoReflectionType
*type
, SigBuffer
*buf
)
706 sigbuffer_add_value (buf
, MONO_TYPE_VOID
);
711 ((type
= mono_reflection_type_get_underlying_system_type (type
)) && type
->type
)) {
712 encode_type (assembly
, type
->type
, buf
);
716 g_assert_not_reached ();
721 encode_custom_modifiers (MonoDynamicImage
*assembly
, MonoArray
*modreq
, MonoArray
*modopt
, SigBuffer
*buf
)
726 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
727 MonoReflectionType
*mod
= mono_type_array_get (modreq
, i
);
728 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_REQD
);
729 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
->type
));
733 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
734 MonoReflectionType
*mod
= mono_type_array_get (modopt
, i
);
735 sigbuffer_add_byte (buf
, MONO_TYPE_CMOD_OPT
);
736 sigbuffer_add_value (buf
, mono_image_typedef_or_ref (assembly
, mod
->type
));
742 method_encode_signature (MonoDynamicImage
*assembly
, MonoMethodSignature
*sig
)
746 guint32 nparams
= sig
->param_count
;
752 sigbuffer_init (&buf
, 32);
754 * FIXME: vararg, explicit_this, differenc call_conv values...
756 idx
= sig
->call_convention
;
758 idx
|= 0x20; /* hasthis */
759 if (sig
->generic_param_count
)
760 idx
|= 0x10; /* generic */
761 sigbuffer_add_byte (&buf
, idx
);
762 if (sig
->generic_param_count
)
763 sigbuffer_add_value (&buf
, sig
->generic_param_count
);
764 sigbuffer_add_value (&buf
, nparams
);
765 encode_type (assembly
, sig
->ret
, &buf
);
766 for (i
= 0; i
< nparams
; ++i
) {
767 if (i
== sig
->sentinelpos
)
768 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
769 encode_type (assembly
, sig
->params
[i
], &buf
);
771 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
772 sigbuffer_free (&buf
);
777 method_builder_encode_signature (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
780 * FIXME: reuse code from method_encode_signature().
784 guint32 nparams
= mb
->parameters
? mono_array_length (mb
->parameters
): 0;
785 guint32 ngparams
= mb
->generic_params
? mono_array_length (mb
->generic_params
): 0;
786 guint32 notypes
= mb
->opt_types
? mono_array_length (mb
->opt_types
): 0;
789 sigbuffer_init (&buf
, 32);
790 /* LAMESPEC: all the call conv spec is foobared */
791 idx
= mb
->call_conv
& 0x60; /* has-this, explicit-this */
792 if (mb
->call_conv
& 2)
793 idx
|= 0x5; /* vararg */
794 if (!(mb
->attrs
& METHOD_ATTRIBUTE_STATIC
))
795 idx
|= 0x20; /* hasthis */
797 idx
|= 0x10; /* generic */
798 sigbuffer_add_byte (&buf
, idx
);
800 sigbuffer_add_value (&buf
, ngparams
);
801 sigbuffer_add_value (&buf
, nparams
+ notypes
);
802 encode_custom_modifiers (assembly
, mb
->return_modreq
, mb
->return_modopt
, &buf
);
803 encode_reflection_type (assembly
, mb
->rtype
, &buf
);
804 for (i
= 0; i
< nparams
; ++i
) {
805 MonoArray
*modreq
= NULL
;
806 MonoArray
*modopt
= NULL
;
807 MonoReflectionType
*pt
;
809 if (mb
->param_modreq
&& (i
< mono_array_length (mb
->param_modreq
)))
810 modreq
= mono_array_get (mb
->param_modreq
, MonoArray
*, i
);
811 if (mb
->param_modopt
&& (i
< mono_array_length (mb
->param_modopt
)))
812 modopt
= mono_array_get (mb
->param_modopt
, MonoArray
*, i
);
813 encode_custom_modifiers (assembly
, modreq
, modopt
, &buf
);
814 pt
= mono_type_array_get (mb
->parameters
, i
);
815 encode_reflection_type (assembly
, pt
, &buf
);
818 sigbuffer_add_byte (&buf
, MONO_TYPE_SENTINEL
);
819 for (i
= 0; i
< notypes
; ++i
) {
820 MonoReflectionType
*pt
;
822 pt
= mono_type_array_get (mb
->opt_types
, i
);
823 encode_reflection_type (assembly
, pt
, &buf
);
826 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
827 sigbuffer_free (&buf
);
832 encode_locals (MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
)
834 MonoDynamicTable
*table
;
836 guint32 idx
, sig_idx
;
837 guint nl
= mono_array_length (ilgen
->locals
);
841 sigbuffer_init (&buf
, 32);
842 sigbuffer_add_value (&buf
, 0x07);
843 sigbuffer_add_value (&buf
, nl
);
844 for (i
= 0; i
< nl
; ++i
) {
845 MonoReflectionLocalBuilder
*lb
= mono_array_get (ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
848 sigbuffer_add_value (&buf
, MONO_TYPE_PINNED
);
850 encode_reflection_type (assembly
, monotype_cast (lb
->type
), &buf
);
852 sig_idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
853 sigbuffer_free (&buf
);
855 if (assembly
->standalonesig_cache
== NULL
)
856 assembly
->standalonesig_cache
= g_hash_table_new (NULL
, NULL
);
857 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
)));
861 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
862 idx
= table
->next_idx
++;
864 alloc_table (table
, table
->rows
);
865 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
867 values
[MONO_STAND_ALONE_SIGNATURE
] = sig_idx
;
869 g_hash_table_insert (assembly
->standalonesig_cache
, GUINT_TO_POINTER (sig_idx
), GUINT_TO_POINTER (idx
));
875 method_count_clauses (MonoReflectionILGen
*ilgen
)
877 guint32 num_clauses
= 0;
880 MonoILExceptionInfo
*ex_info
;
881 for (i
= 0; i
< mono_array_length (ilgen
->ex_handlers
); ++i
) {
882 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
883 if (ex_info
->handlers
)
884 num_clauses
+= mono_array_length (ex_info
->handlers
);
892 static MonoExceptionClause
*
893 method_encode_clauses (MonoImage
*image
, MonoDynamicImage
*assembly
, MonoReflectionILGen
*ilgen
, guint32 num_clauses
)
895 MonoExceptionClause
*clauses
;
896 MonoExceptionClause
*clause
;
897 MonoILExceptionInfo
*ex_info
;
898 MonoILExceptionBlock
*ex_block
;
899 guint32 finally_start
;
900 int i
, j
, clause_index
;;
902 clauses
= image_g_new0 (image
, MonoExceptionClause
, num_clauses
);
905 for (i
= mono_array_length (ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
906 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
907 finally_start
= ex_info
->start
+ ex_info
->len
;
908 if (!ex_info
->handlers
)
910 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
911 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
912 clause
= &(clauses
[clause_index
]);
914 clause
->flags
= ex_block
->type
;
915 clause
->try_offset
= ex_info
->start
;
917 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
918 clause
->try_len
= finally_start
- ex_info
->start
;
920 clause
->try_len
= ex_info
->len
;
921 clause
->handler_offset
= ex_block
->start
;
922 clause
->handler_len
= ex_block
->len
;
923 if (ex_block
->extype
) {
924 clause
->data
.catch_class
= mono_class_from_mono_type (monotype_cast (ex_block
->extype
)->type
);
926 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
927 clause
->data
.filter_offset
= ex_block
->filter_offset
;
929 clause
->data
.filter_offset
= 0;
931 finally_start
= ex_block
->start
+ ex_block
->len
;
941 method_encode_code (MonoDynamicImage
*assembly
, ReflectionMethodBuilder
*mb
)
947 gint32 num_locals
= 0;
948 gint32 num_exception
= 0;
951 char fat_header
[12];
954 guint32 local_sig
= 0;
955 guint32 header_size
= 12;
958 if ((mb
->attrs
& (METHOD_ATTRIBUTE_PINVOKE_IMPL
| METHOD_ATTRIBUTE_ABSTRACT
)) ||
959 (mb
->iattrs
& (METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
| METHOD_IMPL_ATTRIBUTE_RUNTIME
)))
963 g_print ("Encode method %s\n", mono_string_to_utf8 (mb->name));*/
965 code
= mb
->ilgen
->code
;
966 code_size
= mb
->ilgen
->code_len
;
967 max_stack
= mb
->ilgen
->max_stack
;
968 num_locals
= mb
->ilgen
->locals
? mono_array_length (mb
->ilgen
->locals
) : 0;
969 if (mb
->ilgen
->ex_handlers
)
970 num_exception
= method_count_clauses (mb
->ilgen
);
974 char *name
= mono_string_to_utf8 (mb
->name
);
975 char *str
= g_strdup_printf ("Method %s does not have any IL associated", name
);
976 MonoException
*exception
= mono_get_exception_argument (NULL
, "a method does not have any IL associated");
979 mono_raise_exception (exception
);
982 code_size
= mono_array_length (code
);
983 max_stack
= 8; /* we probably need to run a verifier on the code... */
986 stream_data_align (&assembly
->code
);
988 /* check for exceptions, maxstack, locals */
989 maybe_small
= (max_stack
<= 8) && (!num_locals
) && (!num_exception
);
991 if (code_size
< 64 && !(code_size
& 1)) {
992 flags
= (code_size
<< 2) | 0x2;
993 } else if (code_size
< 32 && (code_size
& 1)) {
994 flags
= (code_size
<< 2) | 0x6; /* LAMESPEC: see metadata.c */
998 idx
= mono_image_add_stream_data (&assembly
->code
, &flags
, 1);
999 /* add to the fixup todo list */
1000 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1001 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 1));
1002 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1003 return assembly
->text_rva
+ idx
;
1007 local_sig
= MONO_TOKEN_SIGNATURE
| encode_locals (assembly
, mb
->ilgen
);
1009 * FIXME: need to set also the header size in fat_flags.
1010 * (and more sects and init locals flags)
1014 fat_flags
|= METHOD_HEADER_MORE_SECTS
;
1015 if (mb
->init_locals
)
1016 fat_flags
|= METHOD_HEADER_INIT_LOCALS
;
1017 fat_header
[0] = fat_flags
;
1018 fat_header
[1] = (header_size
/ 4 ) << 4;
1019 short_value
= GUINT16_TO_LE (max_stack
);
1020 memcpy (fat_header
+ 2, &short_value
, 2);
1021 int_value
= GUINT32_TO_LE (code_size
);
1022 memcpy (fat_header
+ 4, &int_value
, 4);
1023 int_value
= GUINT32_TO_LE (local_sig
);
1024 memcpy (fat_header
+ 8, &int_value
, 4);
1025 idx
= mono_image_add_stream_data (&assembly
->code
, fat_header
, 12);
1026 /* add to the fixup todo list */
1027 if (mb
->ilgen
&& mb
->ilgen
->num_token_fixups
)
1028 mono_g_hash_table_insert (assembly
->token_fixups
, mb
->ilgen
, GUINT_TO_POINTER (idx
+ 12));
1030 mono_image_add_stream_data (&assembly
->code
, mono_array_addr (code
, char, 0), code_size
);
1031 if (num_exception
) {
1032 unsigned char sheader
[4];
1033 MonoILExceptionInfo
* ex_info
;
1034 MonoILExceptionBlock
* ex_block
;
1037 stream_data_align (&assembly
->code
);
1038 /* always use fat format for now */
1039 sheader
[0] = METHOD_HEADER_SECTION_FAT_FORMAT
| METHOD_HEADER_SECTION_EHTABLE
;
1040 num_exception
*= 6 * sizeof (guint32
);
1041 num_exception
+= 4; /* include the size of the header */
1042 sheader
[1] = num_exception
& 0xff;
1043 sheader
[2] = (num_exception
>> 8) & 0xff;
1044 sheader
[3] = (num_exception
>> 16) & 0xff;
1045 mono_image_add_stream_data (&assembly
->code
, (char*)sheader
, 4);
1046 /* fat header, so we are already aligned */
1048 for (i
= mono_array_length (mb
->ilgen
->ex_handlers
) - 1; i
>= 0; --i
) {
1049 ex_info
= (MonoILExceptionInfo
*)mono_array_addr (mb
->ilgen
->ex_handlers
, MonoILExceptionInfo
, i
);
1050 if (ex_info
->handlers
) {
1051 int finally_start
= ex_info
->start
+ ex_info
->len
;
1052 for (j
= 0; j
< mono_array_length (ex_info
->handlers
); ++j
) {
1054 ex_block
= (MonoILExceptionBlock
*)mono_array_addr (ex_info
->handlers
, MonoILExceptionBlock
, j
);
1056 val
= GUINT32_TO_LE (ex_block
->type
);
1057 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1059 val
= GUINT32_TO_LE (ex_info
->start
);
1060 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1061 /* need fault, too, probably */
1062 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FINALLY
)
1063 val
= GUINT32_TO_LE (finally_start
- ex_info
->start
);
1065 val
= GUINT32_TO_LE (ex_info
->len
);
1066 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1067 /* handler offset */
1068 val
= GUINT32_TO_LE (ex_block
->start
);
1069 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1071 val
= GUINT32_TO_LE (ex_block
->len
);
1072 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1073 finally_start
= ex_block
->start
+ ex_block
->len
;
1074 if (ex_block
->extype
) {
1075 val
= mono_metadata_token_from_dor (mono_image_typedef_or_ref (assembly
, monotype_cast (ex_block
->extype
)->type
));
1077 if (ex_block
->type
== MONO_EXCEPTION_CLAUSE_FILTER
)
1078 val
= ex_block
->filter_offset
;
1082 val
= GUINT32_TO_LE (val
);
1083 mono_image_add_stream_data (&assembly
->code
, (char*)&val
, sizeof (guint32
));
1084 /*g_print ("out clause %d: from %d len=%d, handler at %d, %d, finally_start=%d, ex_info->start=%d, ex_info->len=%d, ex_block->type=%d, j=%d, i=%d\n",
1085 clause.flags, clause.try_offset, clause.try_len, clause.handler_offset, clause.handler_len, finally_start, ex_info->start, ex_info->len, ex_block->type, j, i);*/
1088 g_error ("No clauses for ex info block %d", i
);
1092 return assembly
->text_rva
+ idx
;
1096 find_index_in_table (MonoDynamicImage
*assembly
, int table_idx
, int col
, guint32 token
)
1099 MonoDynamicTable
*table
;
1102 table
= &assembly
->tables
[table_idx
];
1104 g_assert (col
< table
->columns
);
1106 values
= table
->values
+ table
->columns
;
1107 for (i
= 1; i
<= table
->rows
; ++i
) {
1108 if (values
[col
] == token
)
1110 values
+= table
->columns
;
1116 * LOCKING: Acquires the loader lock.
1118 static MonoCustomAttrInfo
*
1119 lookup_custom_attr (MonoImage
*image
, gpointer member
)
1121 MonoCustomAttrInfo
* res
;
1123 res
= mono_image_property_lookup (image
, member
, MONO_PROP_DYNAMIC_CATTR
);
1128 return g_memdup (res
, sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (res
->num_attrs
- MONO_ZERO_LEN_ARRAY
));
1132 custom_attr_visible (MonoImage
*image
, MonoReflectionCustomAttr
*cattr
)
1134 /* FIXME: Need to do more checks */
1135 if (cattr
->ctor
->method
&& (cattr
->ctor
->method
->klass
->image
!= image
)) {
1136 int visibility
= cattr
->ctor
->method
->klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
1138 if ((visibility
!= TYPE_ATTRIBUTE_PUBLIC
) && (visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
))
1145 static MonoCustomAttrInfo
*
1146 mono_custom_attrs_from_builders (MonoImage
*alloc_img
, MonoImage
*image
, MonoArray
*cattrs
)
1148 int i
, index
, count
, not_visible
;
1149 MonoCustomAttrInfo
*ainfo
;
1150 MonoReflectionCustomAttr
*cattr
;
1154 /* FIXME: check in assembly the Run flag is set */
1156 count
= mono_array_length (cattrs
);
1158 /* Skip nonpublic attributes since MS.NET seems to do the same */
1159 /* FIXME: This needs to be done more globally */
1161 for (i
= 0; i
< count
; ++i
) {
1162 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1163 if (!custom_attr_visible (image
, cattr
))
1166 count
-= not_visible
;
1168 ainfo
= image_g_malloc0 (alloc_img
, sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (count
- MONO_ZERO_LEN_ARRAY
));
1170 ainfo
->image
= image
;
1171 ainfo
->num_attrs
= count
;
1172 ainfo
->cached
= alloc_img
!= NULL
;
1174 for (i
= 0; i
< count
; ++i
) {
1175 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1176 if (custom_attr_visible (image
, cattr
)) {
1177 unsigned char *saved
= mono_image_alloc (image
, mono_array_length (cattr
->data
));
1178 memcpy (saved
, mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1179 ainfo
->attrs
[index
].ctor
= cattr
->ctor
->method
;
1180 ainfo
->attrs
[index
].data
= saved
;
1181 ainfo
->attrs
[index
].data_size
= mono_array_length (cattr
->data
);
1190 * LOCKING: Acquires the loader lock.
1193 mono_save_custom_attrs (MonoImage
*image
, void *obj
, MonoArray
*cattrs
)
1195 MonoCustomAttrInfo
*ainfo
, *tmp
;
1197 if (!cattrs
|| !mono_array_length (cattrs
))
1200 ainfo
= mono_custom_attrs_from_builders (image
, image
, cattrs
);
1202 mono_loader_lock ();
1203 tmp
= mono_image_property_lookup (image
, obj
, MONO_PROP_DYNAMIC_CATTR
);
1205 mono_custom_attrs_free (tmp
);
1206 mono_image_property_insert (image
, obj
, MONO_PROP_DYNAMIC_CATTR
, ainfo
);
1207 mono_loader_unlock ();
1212 mono_custom_attrs_free (MonoCustomAttrInfo
*ainfo
)
1219 * idx is the table index of the object
1220 * type is one of MONO_CUSTOM_ATTR_*
1223 mono_image_add_cattrs (MonoDynamicImage
*assembly
, guint32 idx
, guint32 type
, MonoArray
*cattrs
)
1225 MonoDynamicTable
*table
;
1226 MonoReflectionCustomAttr
*cattr
;
1228 guint32 count
, i
, token
;
1230 char *p
= blob_size
;
1232 /* it is legal to pass a NULL cattrs: we avoid to use the if in a lot of places */
1235 count
= mono_array_length (cattrs
);
1236 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
1237 table
->rows
+= count
;
1238 alloc_table (table
, table
->rows
);
1239 values
= table
->values
+ table
->next_idx
* MONO_CUSTOM_ATTR_SIZE
;
1240 idx
<<= MONO_CUSTOM_ATTR_BITS
;
1242 for (i
= 0; i
< count
; ++i
) {
1243 cattr
= (MonoReflectionCustomAttr
*)mono_array_get (cattrs
, gpointer
, i
);
1244 values
[MONO_CUSTOM_ATTR_PARENT
] = idx
;
1245 token
= mono_image_create_token (assembly
, (MonoObject
*)cattr
->ctor
, FALSE
, FALSE
);
1246 type
= mono_metadata_token_index (token
);
1247 type
<<= MONO_CUSTOM_ATTR_TYPE_BITS
;
1248 switch (mono_metadata_token_table (token
)) {
1249 case MONO_TABLE_METHOD
:
1250 type
|= MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
1252 case MONO_TABLE_MEMBERREF
:
1253 type
|= MONO_CUSTOM_ATTR_TYPE_MEMBERREF
;
1256 g_warning ("got wrong token in custom attr");
1259 values
[MONO_CUSTOM_ATTR_TYPE
] = type
;
1261 mono_metadata_encode_value (mono_array_length (cattr
->data
), p
, &p
);
1262 values
[MONO_CUSTOM_ATTR_VALUE
] = add_to_blob_cached (assembly
, blob_size
, p
- blob_size
,
1263 mono_array_addr (cattr
->data
, char, 0), mono_array_length (cattr
->data
));
1264 values
+= MONO_CUSTOM_ATTR_SIZE
;
1270 mono_image_add_decl_security (MonoDynamicImage
*assembly
, guint32 parent_token
, MonoArray
*permissions
)
1272 MonoDynamicTable
*table
;
1274 guint32 count
, i
, idx
;
1275 MonoReflectionPermissionSet
*perm
;
1280 count
= mono_array_length (permissions
);
1281 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
1282 table
->rows
+= count
;
1283 alloc_table (table
, table
->rows
);
1285 for (i
= 0; i
< mono_array_length (permissions
); ++i
) {
1286 perm
= (MonoReflectionPermissionSet
*)mono_array_addr (permissions
, MonoReflectionPermissionSet
, i
);
1288 values
= table
->values
+ table
->next_idx
* MONO_DECL_SECURITY_SIZE
;
1290 idx
= mono_metadata_token_index (parent_token
);
1291 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
1292 switch (mono_metadata_token_table (parent_token
)) {
1293 case MONO_TABLE_TYPEDEF
:
1294 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
1296 case MONO_TABLE_METHOD
:
1297 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
1299 case MONO_TABLE_ASSEMBLY
:
1300 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
1303 g_assert_not_reached ();
1306 values
[MONO_DECL_SECURITY_ACTION
] = perm
->action
;
1307 values
[MONO_DECL_SECURITY_PARENT
] = idx
;
1308 values
[MONO_DECL_SECURITY_PERMISSIONSET
] = add_mono_string_to_blob_cached (assembly
, perm
->pset
);
1315 * Fill in the MethodDef and ParamDef tables for a method.
1316 * This is used for both normal methods and constructors.
1319 mono_image_basic_method (ReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1321 MonoDynamicTable
*table
;
1325 /* room in this table is already allocated */
1326 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
1327 *mb
->table_idx
= table
->next_idx
++;
1328 g_hash_table_insert (assembly
->method_to_table_idx
, mb
->mhandle
, GUINT_TO_POINTER ((*mb
->table_idx
)));
1329 values
= table
->values
+ *mb
->table_idx
* MONO_METHOD_SIZE
;
1330 values
[MONO_METHOD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1331 values
[MONO_METHOD_FLAGS
] = mb
->attrs
;
1332 values
[MONO_METHOD_IMPLFLAGS
] = mb
->iattrs
;
1333 values
[MONO_METHOD_SIGNATURE
] = method_builder_encode_signature (assembly
, mb
);
1334 values
[MONO_METHOD_RVA
] = method_encode_code (assembly
, mb
);
1336 table
= &assembly
->tables
[MONO_TABLE_PARAM
];
1337 values
[MONO_METHOD_PARAMLIST
] = table
->next_idx
;
1339 mono_image_add_decl_security (assembly
,
1340 mono_metadata_make_token (MONO_TABLE_METHOD
, *mb
->table_idx
), mb
->permissions
);
1343 MonoDynamicTable
*mtable
;
1346 mtable
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1347 mvalues
= mtable
->values
+ mtable
->next_idx
* MONO_FIELD_MARSHAL_SIZE
;
1350 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1351 if (mono_array_get (mb
->pinfo
, gpointer
, i
))
1354 table
->rows
+= count
;
1355 alloc_table (table
, table
->rows
);
1356 values
= table
->values
+ table
->next_idx
* MONO_PARAM_SIZE
;
1357 for (i
= 0; i
< mono_array_length (mb
->pinfo
); ++i
) {
1358 MonoReflectionParamBuilder
*pb
;
1359 if ((pb
= mono_array_get (mb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
1360 values
[MONO_PARAM_FLAGS
] = pb
->attrs
;
1361 values
[MONO_PARAM_SEQUENCE
] = i
;
1362 if (pb
->name
!= NULL
) {
1363 values
[MONO_PARAM_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1365 values
[MONO_PARAM_NAME
] = 0;
1367 values
+= MONO_PARAM_SIZE
;
1368 if (pb
->marshal_info
) {
1370 alloc_table (mtable
, mtable
->rows
);
1371 mvalues
= mtable
->values
+ mtable
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1372 mvalues
[MONO_FIELD_MARSHAL_PARENT
] = (table
->next_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_PARAMDEF
;
1373 mvalues
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, pb
->marshal_info
);
1375 pb
->table_idx
= table
->next_idx
++;
1376 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
1377 guint32 field_type
= 0;
1378 mtable
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1380 alloc_table (mtable
, mtable
->rows
);
1381 mvalues
= mtable
->values
+ mtable
->rows
* MONO_CONSTANT_SIZE
;
1382 mvalues
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_PARAM
| (pb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1383 mvalues
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, pb
->def_value
, &field_type
);
1384 mvalues
[MONO_CONSTANT_TYPE
] = field_type
;
1385 mvalues
[MONO_CONSTANT_PADDING
] = 0;
1393 reflection_methodbuilder_from_method_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionMethodBuilder
*mb
)
1395 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1397 rmb
->ilgen
= mb
->ilgen
;
1398 rmb
->rtype
= monotype_cast (mb
->rtype
);
1399 rmb
->parameters
= mb
->parameters
;
1400 rmb
->generic_params
= mb
->generic_params
;
1401 rmb
->generic_container
= mb
->generic_container
;
1402 rmb
->opt_types
= NULL
;
1403 rmb
->pinfo
= mb
->pinfo
;
1404 rmb
->attrs
= mb
->attrs
;
1405 rmb
->iattrs
= mb
->iattrs
;
1406 rmb
->call_conv
= mb
->call_conv
;
1407 rmb
->code
= mb
->code
;
1408 rmb
->type
= mb
->type
;
1409 rmb
->name
= mb
->name
;
1410 rmb
->table_idx
= &mb
->table_idx
;
1411 rmb
->init_locals
= mb
->init_locals
;
1412 rmb
->skip_visibility
= FALSE
;
1413 rmb
->return_modreq
= mb
->return_modreq
;
1414 rmb
->return_modopt
= mb
->return_modopt
;
1415 rmb
->param_modreq
= mb
->param_modreq
;
1416 rmb
->param_modopt
= mb
->param_modopt
;
1417 rmb
->permissions
= mb
->permissions
;
1418 rmb
->mhandle
= mb
->mhandle
;
1423 rmb
->charset
= mb
->charset
;
1424 rmb
->extra_flags
= mb
->extra_flags
;
1425 rmb
->native_cc
= mb
->native_cc
;
1426 rmb
->dllentry
= mb
->dllentry
;
1432 reflection_methodbuilder_from_ctor_builder (ReflectionMethodBuilder
*rmb
, MonoReflectionCtorBuilder
*mb
)
1434 const char *name
= mb
->attrs
& METHOD_ATTRIBUTE_STATIC
? ".cctor": ".ctor";
1436 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1438 rmb
->ilgen
= mb
->ilgen
;
1439 rmb
->rtype
= mono_type_get_object (mono_domain_get (), &mono_defaults
.void_class
->byval_arg
);
1440 rmb
->parameters
= mb
->parameters
;
1441 rmb
->generic_params
= NULL
;
1442 rmb
->generic_container
= NULL
;
1443 rmb
->opt_types
= NULL
;
1444 rmb
->pinfo
= mb
->pinfo
;
1445 rmb
->attrs
= mb
->attrs
;
1446 rmb
->iattrs
= mb
->iattrs
;
1447 rmb
->call_conv
= mb
->call_conv
;
1449 rmb
->type
= mb
->type
;
1450 rmb
->name
= mono_string_new (mono_domain_get (), name
);
1451 rmb
->table_idx
= &mb
->table_idx
;
1452 rmb
->init_locals
= mb
->init_locals
;
1453 rmb
->skip_visibility
= FALSE
;
1454 rmb
->return_modreq
= NULL
;
1455 rmb
->return_modopt
= NULL
;
1456 rmb
->param_modreq
= mb
->param_modreq
;
1457 rmb
->param_modopt
= mb
->param_modopt
;
1458 rmb
->permissions
= mb
->permissions
;
1459 rmb
->mhandle
= mb
->mhandle
;
1465 reflection_methodbuilder_from_dynamic_method (ReflectionMethodBuilder
*rmb
, MonoReflectionDynamicMethod
*mb
)
1467 memset (rmb
, 0, sizeof (ReflectionMethodBuilder
));
1469 rmb
->ilgen
= mb
->ilgen
;
1470 rmb
->rtype
= mb
->rtype
;
1471 rmb
->parameters
= mb
->parameters
;
1472 rmb
->generic_params
= NULL
;
1473 rmb
->generic_container
= NULL
;
1474 rmb
->opt_types
= NULL
;
1476 rmb
->attrs
= mb
->attrs
;
1478 rmb
->call_conv
= mb
->call_conv
;
1480 rmb
->type
= (MonoObject
*) mb
->owner
;
1481 rmb
->name
= mb
->name
;
1482 rmb
->table_idx
= NULL
;
1483 rmb
->init_locals
= mb
->init_locals
;
1484 rmb
->skip_visibility
= mb
->skip_visibility
;
1485 rmb
->return_modreq
= NULL
;
1486 rmb
->return_modopt
= NULL
;
1487 rmb
->param_modreq
= NULL
;
1488 rmb
->param_modopt
= NULL
;
1489 rmb
->permissions
= NULL
;
1490 rmb
->mhandle
= mb
->mhandle
;
1496 mono_image_add_methodimpl (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
1498 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
1499 MonoDynamicTable
*table
;
1503 if (!mb
->override_method
)
1506 table
= &assembly
->tables
[MONO_TABLE_METHODIMPL
];
1508 alloc_table (table
, table
->rows
);
1509 values
= table
->values
+ table
->rows
* MONO_METHODIMPL_SIZE
;
1510 values
[MONO_METHODIMPL_CLASS
] = tb
->table_idx
;
1511 values
[MONO_METHODIMPL_BODY
] = MONO_METHODDEFORREF_METHODDEF
| (mb
->table_idx
<< MONO_METHODDEFORREF_BITS
);
1513 tok
= mono_image_create_token (assembly
, (MonoObject
*)mb
->override_method
, FALSE
, FALSE
);
1514 switch (mono_metadata_token_table (tok
)) {
1515 case MONO_TABLE_MEMBERREF
:
1516 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
1518 case MONO_TABLE_METHOD
:
1519 tok
= (mono_metadata_token_index (tok
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
1522 g_assert_not_reached ();
1524 values
[MONO_METHODIMPL_DECLARATION
] = tok
;
1528 mono_image_get_method_info (MonoReflectionMethodBuilder
*mb
, MonoDynamicImage
*assembly
)
1530 MonoDynamicTable
*table
;
1532 ReflectionMethodBuilder rmb
;
1535 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
1537 mono_image_basic_method (&rmb
, assembly
);
1538 mb
->table_idx
= *rmb
.table_idx
;
1540 if (mb
->dll
) { /* It's a P/Invoke method */
1542 /* map CharSet values to on-disk values */
1543 int ncharset
= (mb
->charset
? (mb
->charset
- 1) * 2 : 0);
1544 int extra_flags
= mb
->extra_flags
;
1545 table
= &assembly
->tables
[MONO_TABLE_IMPLMAP
];
1547 alloc_table (table
, table
->rows
);
1548 values
= table
->values
+ table
->rows
* MONO_IMPLMAP_SIZE
;
1550 values
[MONO_IMPLMAP_FLAGS
] = (mb
->native_cc
<< 8) | ncharset
| extra_flags
;
1551 values
[MONO_IMPLMAP_MEMBER
] = (mb
->table_idx
<< 1) | 1; /* memberforwarded: method */
1553 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->dllentry
);
1555 values
[MONO_IMPLMAP_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->name
);
1556 moduleref
= string_heap_insert_mstring (&assembly
->sheap
, mb
->dll
);
1557 if (!(values
[MONO_IMPLMAP_SCOPE
] = find_index_in_table (assembly
, MONO_TABLE_MODULEREF
, MONO_MODULEREF_NAME
, moduleref
))) {
1558 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
1560 alloc_table (table
, table
->rows
);
1561 table
->values
[table
->rows
* MONO_MODULEREF_SIZE
+ MONO_MODULEREF_NAME
] = moduleref
;
1562 values
[MONO_IMPLMAP_SCOPE
] = table
->rows
;
1566 if (mb
->generic_params
) {
1567 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
1568 table
->rows
+= mono_array_length (mb
->generic_params
);
1569 alloc_table (table
, table
->rows
);
1570 for (i
= 0; i
< mono_array_length (mb
->generic_params
); ++i
) {
1571 guint32 owner
= MONO_TYPEORMETHOD_METHOD
| (mb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
1573 mono_image_get_generic_param_info (
1574 mono_array_get (mb
->generic_params
, gpointer
, i
), owner
, assembly
);
1581 mono_image_get_ctor_info (MonoDomain
*domain
, MonoReflectionCtorBuilder
*mb
, MonoDynamicImage
*assembly
)
1583 ReflectionMethodBuilder rmb
;
1585 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
1587 mono_image_basic_method (&rmb
, assembly
);
1588 mb
->table_idx
= *rmb
.table_idx
;
1592 type_get_fully_qualified_name (MonoType
*type
)
1594 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1598 type_get_qualified_name (MonoType
*type
, MonoAssembly
*ass
) {
1602 klass
= my_mono_class_from_mono_type (type
);
1604 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1605 ta
= klass
->image
->assembly
;
1606 if (ta
->dynamic
|| (ta
== ass
)) {
1607 if (klass
->generic_class
|| klass
->generic_container
)
1608 /* For generic type definitions, we want T, while REFLECTION returns T<K> */
1609 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_FULL_NAME
);
1611 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_REFLECTION
);
1614 return mono_type_get_name_full (type
, MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
);
1618 fieldref_encode_signature (MonoDynamicImage
*assembly
, MonoType
*type
)
1623 if (!assembly
->save
)
1626 sigbuffer_init (&buf
, 32);
1628 sigbuffer_add_value (&buf
, 0x06);
1629 /* encode custom attributes before the type */
1630 /* FIXME: This should probably go in encode_type () */
1631 if (type
->num_mods
) {
1632 for (i
= 0; i
< type
->num_mods
; ++i
) {
1633 if (type
->modifiers
[i
].required
)
1634 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_REQD
);
1636 sigbuffer_add_byte (&buf
, MONO_TYPE_CMOD_OPT
);
1637 sigbuffer_add_value (&buf
, type
->modifiers
[i
].token
);
1640 encode_type (assembly
, type
, &buf
);
1641 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1642 sigbuffer_free (&buf
);
1647 field_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
1652 sigbuffer_init (&buf
, 32);
1654 sigbuffer_add_value (&buf
, 0x06);
1655 encode_custom_modifiers (assembly
, fb
->modreq
, fb
->modopt
, &buf
);
1656 /* encode custom attributes before the type */
1657 encode_reflection_type (assembly
, monotype_cast (fb
->type
), &buf
);
1658 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1659 sigbuffer_free (&buf
);
1664 encode_constant (MonoDynamicImage
*assembly
, MonoObject
*val
, guint32
*ret_type
) {
1665 char blob_size
[64];
1666 char *b
= blob_size
;
1669 guint32 idx
= 0, len
= 0, dummy
= 0;
1671 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1672 guint32 fpa_double
[2];
1677 p
= buf
= g_malloc (64);
1679 *ret_type
= MONO_TYPE_CLASS
;
1681 box_val
= (char*)&dummy
;
1683 box_val
= ((char*)val
) + sizeof (MonoObject
);
1684 *ret_type
= val
->vtable
->klass
->byval_arg
.type
;
1687 switch (*ret_type
) {
1688 case MONO_TYPE_BOOLEAN
:
1693 case MONO_TYPE_CHAR
:
1710 #if G_BYTE_ORDER == G_LITTLE_ENDIAN
1711 fpa_p
= (guint32
*)box_val
;
1712 fpa_double
[0] = fpa_p
[1];
1713 fpa_double
[1] = fpa_p
[0];
1714 box_val
= (char*)fpa_double
;
1718 case MONO_TYPE_VALUETYPE
:
1719 if (val
->vtable
->klass
->enumtype
) {
1720 *ret_type
= mono_class_enum_basetype (val
->vtable
->klass
)->type
;
1723 g_error ("we can't encode valuetypes");
1724 case MONO_TYPE_CLASS
:
1726 case MONO_TYPE_STRING
: {
1727 MonoString
*str
= (MonoString
*)val
;
1728 /* there is no signature */
1729 len
= str
->length
* 2;
1730 mono_metadata_encode_value (len
, b
, &b
);
1731 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1733 char *swapped
= g_malloc (2 * mono_string_length (str
));
1734 const char *p
= (const char*)mono_string_chars (str
);
1736 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
1737 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, swapped
, len
);
1741 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, (char*)mono_string_chars (str
), len
);
1747 case MONO_TYPE_GENERICINST
:
1748 *ret_type
= val
->vtable
->klass
->generic_class
->container_class
->byval_arg
.type
;
1751 g_error ("we don't encode constant type 0x%02x yet", *ret_type
);
1754 /* there is no signature */
1755 mono_metadata_encode_value (len
, b
, &b
);
1756 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
1757 idx
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
1758 swap_with_size (blob_size
, box_val
, len
, 1);
1759 mono_image_add_stream_data (&assembly
->blob
, blob_size
, len
);
1761 idx
= add_to_blob_cached (assembly
, blob_size
, b
-blob_size
, box_val
, len
);
1769 encode_marshal_blob (MonoDynamicImage
*assembly
, MonoReflectionMarshal
*minfo
) {
1774 sigbuffer_init (&buf
, 32);
1776 sigbuffer_add_value (&buf
, minfo
->type
);
1778 switch (minfo
->type
) {
1779 case MONO_NATIVE_BYVALTSTR
:
1780 case MONO_NATIVE_BYVALARRAY
:
1781 sigbuffer_add_value (&buf
, minfo
->count
);
1783 case MONO_NATIVE_LPARRAY
:
1784 if (minfo
->eltype
|| minfo
->has_size
) {
1785 sigbuffer_add_value (&buf
, minfo
->eltype
);
1786 if (minfo
->has_size
) {
1787 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? minfo
->param_num
: 0);
1788 sigbuffer_add_value (&buf
, minfo
->count
!= -1? minfo
->count
: 0);
1790 /* LAMESPEC: ElemMult is undocumented */
1791 sigbuffer_add_value (&buf
, minfo
->param_num
!= -1? 1: 0);
1795 case MONO_NATIVE_CUSTOM
:
1797 str
= mono_string_to_utf8 (minfo
->guid
);
1799 sigbuffer_add_value (&buf
, len
);
1800 sigbuffer_add_mem (&buf
, str
, len
);
1803 sigbuffer_add_value (&buf
, 0);
1805 /* native type name */
1806 sigbuffer_add_value (&buf
, 0);
1807 /* custom marshaler type name */
1808 if (minfo
->marshaltype
|| minfo
->marshaltyperef
) {
1809 if (minfo
->marshaltyperef
)
1810 str
= type_get_fully_qualified_name (monotype_cast (minfo
->marshaltyperef
)->type
);
1812 str
= mono_string_to_utf8 (minfo
->marshaltype
);
1814 sigbuffer_add_value (&buf
, len
);
1815 sigbuffer_add_mem (&buf
, str
, len
);
1818 /* FIXME: Actually a bug, since this field is required. Punting for now ... */
1819 sigbuffer_add_value (&buf
, 0);
1821 if (minfo
->mcookie
) {
1822 str
= mono_string_to_utf8 (minfo
->mcookie
);
1824 sigbuffer_add_value (&buf
, len
);
1825 sigbuffer_add_mem (&buf
, str
, len
);
1828 sigbuffer_add_value (&buf
, 0);
1834 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1835 sigbuffer_free (&buf
);
1840 mono_image_get_field_info (MonoReflectionFieldBuilder
*fb
, MonoDynamicImage
*assembly
)
1842 MonoDynamicTable
*table
;
1845 /* maybe this fixup should be done in the C# code */
1846 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
)
1847 fb
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
1848 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
1849 fb
->table_idx
= table
->next_idx
++;
1850 g_hash_table_insert (assembly
->field_to_table_idx
, fb
->handle
, GUINT_TO_POINTER (fb
->table_idx
));
1851 values
= table
->values
+ fb
->table_idx
* MONO_FIELD_SIZE
;
1852 values
[MONO_FIELD_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, fb
->name
);
1853 values
[MONO_FIELD_FLAGS
] = fb
->attrs
;
1854 values
[MONO_FIELD_SIGNATURE
] = field_encode_signature (assembly
, fb
);
1856 if (fb
->offset
!= -1) {
1857 table
= &assembly
->tables
[MONO_TABLE_FIELDLAYOUT
];
1859 alloc_table (table
, table
->rows
);
1860 values
= table
->values
+ table
->rows
* MONO_FIELD_LAYOUT_SIZE
;
1861 values
[MONO_FIELD_LAYOUT_FIELD
] = fb
->table_idx
;
1862 values
[MONO_FIELD_LAYOUT_OFFSET
] = fb
->offset
;
1864 if (fb
->attrs
& FIELD_ATTRIBUTE_LITERAL
) {
1865 guint32 field_type
= 0;
1866 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
1868 alloc_table (table
, table
->rows
);
1869 values
= table
->values
+ table
->rows
* MONO_CONSTANT_SIZE
;
1870 values
[MONO_CONSTANT_PARENT
] = MONO_HASCONSTANT_FIEDDEF
| (fb
->table_idx
<< MONO_HASCONSTANT_BITS
);
1871 values
[MONO_CONSTANT_VALUE
] = encode_constant (assembly
, fb
->def_value
, &field_type
);
1872 values
[MONO_CONSTANT_TYPE
] = field_type
;
1873 values
[MONO_CONSTANT_PADDING
] = 0;
1875 if (fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) {
1877 table
= &assembly
->tables
[MONO_TABLE_FIELDRVA
];
1879 alloc_table (table
, table
->rows
);
1880 values
= table
->values
+ table
->rows
* MONO_FIELD_RVA_SIZE
;
1881 values
[MONO_FIELD_RVA_FIELD
] = fb
->table_idx
;
1883 * We store it in the code section because it's simpler for now.
1886 if (mono_array_length (fb
->rva_data
) >= 10)
1887 stream_data_align (&assembly
->code
);
1888 rva_idx
= mono_image_add_stream_data (&assembly
->code
, mono_array_addr (fb
->rva_data
, char, 0), mono_array_length (fb
->rva_data
));
1890 rva_idx
= mono_image_add_stream_zero (&assembly
->code
, mono_class_value_size (fb
->handle
->parent
, NULL
));
1891 values
[MONO_FIELD_RVA_RVA
] = rva_idx
+ assembly
->text_rva
;
1893 if (fb
->marshal_info
) {
1894 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
1896 alloc_table (table
, table
->rows
);
1897 values
= table
->values
+ table
->rows
* MONO_FIELD_MARSHAL_SIZE
;
1898 values
[MONO_FIELD_MARSHAL_PARENT
] = (fb
->table_idx
<< MONO_HAS_FIELD_MARSHAL_BITS
) | MONO_HAS_FIELD_MARSHAL_FIELDSREF
;
1899 values
[MONO_FIELD_MARSHAL_NATIVE_TYPE
] = encode_marshal_blob (assembly
, fb
->marshal_info
);
1904 property_encode_signature (MonoDynamicImage
*assembly
, MonoReflectionPropertyBuilder
*fb
)
1907 guint32 nparams
= 0;
1908 MonoReflectionMethodBuilder
*mb
= fb
->get_method
;
1909 MonoReflectionMethodBuilder
*smb
= fb
->set_method
;
1912 if (mb
&& mb
->parameters
)
1913 nparams
= mono_array_length (mb
->parameters
);
1914 if (!mb
&& smb
&& smb
->parameters
)
1915 nparams
= mono_array_length (smb
->parameters
) - 1;
1916 sigbuffer_init (&buf
, 32);
1917 sigbuffer_add_byte (&buf
, 0x08);
1918 sigbuffer_add_value (&buf
, nparams
);
1920 encode_reflection_type (assembly
, monotype_cast (mb
->rtype
), &buf
);
1921 for (i
= 0; i
< nparams
; ++i
) {
1922 MonoReflectionType
*pt
= mono_type_array_get (mb
->parameters
, i
);
1923 encode_reflection_type (assembly
, pt
, &buf
);
1925 } else if (smb
&& smb
->parameters
) {
1926 /* the property type is the last param */
1927 encode_reflection_type (assembly
, mono_type_array_get (smb
->parameters
, nparams
), &buf
);
1928 for (i
= 0; i
< nparams
; ++i
) {
1929 MonoReflectionType
*pt
= mono_type_array_get (smb
->parameters
, i
);
1930 encode_reflection_type (assembly
, pt
, &buf
);
1933 encode_reflection_type (assembly
, monotype_cast (fb
->type
), &buf
);
1936 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
1937 sigbuffer_free (&buf
);
1942 mono_image_get_property_info (MonoReflectionPropertyBuilder
*pb
, MonoDynamicImage
*assembly
)
1944 MonoDynamicTable
*table
;
1946 guint num_methods
= 0;
1950 * we need to set things in the following tables:
1951 * PROPERTYMAP (info already filled in _get_type_info ())
1952 * PROPERTY (rows already preallocated in _get_type_info ())
1953 * METHOD (method info already done with the generic method code)
1956 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
1957 pb
->table_idx
= table
->next_idx
++;
1958 values
= table
->values
+ pb
->table_idx
* MONO_PROPERTY_SIZE
;
1959 values
[MONO_PROPERTY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, pb
->name
);
1960 values
[MONO_PROPERTY_FLAGS
] = pb
->attrs
;
1961 values
[MONO_PROPERTY_TYPE
] = property_encode_signature (assembly
, pb
);
1963 /* FIXME: we still don't handle 'other' methods */
1964 if (pb
->get_method
) num_methods
++;
1965 if (pb
->set_method
) num_methods
++;
1967 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
1968 table
->rows
+= num_methods
;
1969 alloc_table (table
, table
->rows
);
1971 if (pb
->get_method
) {
1972 semaidx
= table
->next_idx
++;
1973 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
1974 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_GETTER
;
1975 values
[MONO_METHOD_SEMA_METHOD
] = pb
->get_method
->table_idx
;
1976 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
1978 if (pb
->set_method
) {
1979 semaidx
= table
->next_idx
++;
1980 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
1981 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_SETTER
;
1982 values
[MONO_METHOD_SEMA_METHOD
] = pb
->set_method
->table_idx
;
1983 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (pb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_PROPERTY
;
1988 mono_image_get_event_info (MonoReflectionEventBuilder
*eb
, MonoDynamicImage
*assembly
)
1990 MonoDynamicTable
*table
;
1992 guint num_methods
= 0;
1996 * we need to set things in the following tables:
1997 * EVENTMAP (info already filled in _get_type_info ())
1998 * EVENT (rows already preallocated in _get_type_info ())
1999 * METHOD (method info already done with the generic method code)
2002 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
2003 eb
->table_idx
= table
->next_idx
++;
2004 values
= table
->values
+ eb
->table_idx
* MONO_EVENT_SIZE
;
2005 values
[MONO_EVENT_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, eb
->name
);
2006 values
[MONO_EVENT_FLAGS
] = eb
->attrs
;
2007 values
[MONO_EVENT_TYPE
] = mono_image_typedef_or_ref (assembly
, eb
->type
->type
);
2010 * FIXME: we still don't handle 'other' methods
2012 if (eb
->add_method
) num_methods
++;
2013 if (eb
->remove_method
) num_methods
++;
2014 if (eb
->raise_method
) num_methods
++;
2016 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
2017 table
->rows
+= num_methods
;
2018 alloc_table (table
, table
->rows
);
2020 if (eb
->add_method
) {
2021 semaidx
= table
->next_idx
++;
2022 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2023 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_ADD_ON
;
2024 values
[MONO_METHOD_SEMA_METHOD
] = eb
->add_method
->table_idx
;
2025 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2027 if (eb
->remove_method
) {
2028 semaidx
= table
->next_idx
++;
2029 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2030 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_REMOVE_ON
;
2031 values
[MONO_METHOD_SEMA_METHOD
] = eb
->remove_method
->table_idx
;
2032 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2034 if (eb
->raise_method
) {
2035 semaidx
= table
->next_idx
++;
2036 values
= table
->values
+ semaidx
* MONO_METHOD_SEMA_SIZE
;
2037 values
[MONO_METHOD_SEMA_SEMANTICS
] = METHOD_SEMANTIC_FIRE
;
2038 values
[MONO_METHOD_SEMA_METHOD
] = eb
->raise_method
->table_idx
;
2039 values
[MONO_METHOD_SEMA_ASSOCIATION
] = (eb
->table_idx
<< MONO_HAS_SEMANTICS_BITS
) | MONO_HAS_SEMANTICS_EVENT
;
2044 encode_constraints (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2046 MonoDynamicTable
*table
;
2047 guint32 num_constraints
, i
;
2051 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAMCONSTRAINT
];
2052 num_constraints
= gparam
->iface_constraints
?
2053 mono_array_length (gparam
->iface_constraints
) : 0;
2054 table
->rows
+= num_constraints
;
2055 if (gparam
->base_type
)
2057 alloc_table (table
, table
->rows
);
2059 if (gparam
->base_type
) {
2060 table_idx
= table
->next_idx
++;
2061 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2063 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2064 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2065 assembly
, gparam
->base_type
->type
);
2068 for (i
= 0; i
< num_constraints
; i
++) {
2069 MonoReflectionType
*constraint
= mono_array_get (
2070 gparam
->iface_constraints
, gpointer
, i
);
2072 table_idx
= table
->next_idx
++;
2073 values
= table
->values
+ table_idx
* MONO_GENPARCONSTRAINT_SIZE
;
2075 values
[MONO_GENPARCONSTRAINT_GENERICPAR
] = owner
;
2076 values
[MONO_GENPARCONSTRAINT_CONSTRAINT
] = mono_image_typedef_or_ref (
2077 assembly
, constraint
->type
);
2082 mono_image_get_generic_param_info (MonoReflectionGenericParam
*gparam
, guint32 owner
, MonoDynamicImage
*assembly
)
2084 GenericParamTableEntry
*entry
;
2087 * The GenericParam table must be sorted according to the `owner' field.
2088 * We need to do this sorting prior to writing the GenericParamConstraint
2089 * table, since we have to use the final GenericParam table indices there
2090 * and they must also be sorted.
2093 entry
= g_new0 (GenericParamTableEntry
, 1);
2094 entry
->owner
= owner
;
2095 /* FIXME: track where gen_params should be freed and remove the GC root as well */
2096 MOVING_GC_REGISTER (&entry
->gparam
);
2097 entry
->gparam
= gparam
;
2099 g_ptr_array_add (assembly
->gen_params
, entry
);
2103 write_generic_param_entry (MonoDynamicImage
*assembly
, GenericParamTableEntry
*entry
)
2105 MonoDynamicTable
*table
;
2106 MonoGenericParam
*param
;
2110 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
2111 table_idx
= table
->next_idx
++;
2112 values
= table
->values
+ table_idx
* MONO_GENERICPARAM_SIZE
;
2114 param
= entry
->gparam
->type
.type
->data
.generic_param
;
2116 values
[MONO_GENERICPARAM_OWNER
] = entry
->owner
;
2117 values
[MONO_GENERICPARAM_FLAGS
] = entry
->gparam
->attrs
;
2118 values
[MONO_GENERICPARAM_NUMBER
] = param
->num
;
2119 values
[MONO_GENERICPARAM_NAME
] = string_heap_insert (&assembly
->sheap
, param
->name
);
2121 mono_image_add_cattrs (assembly
, table_idx
, MONO_CUSTOM_ATTR_GENERICPAR
, entry
->gparam
->cattrs
);
2123 encode_constraints (entry
->gparam
, table_idx
, assembly
);
2127 resolution_scope_from_image (MonoDynamicImage
*assembly
, MonoImage
*image
)
2129 MonoDynamicTable
*table
;
2132 guint32 cols
[MONO_ASSEMBLY_SIZE
];
2136 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, image
))))
2139 if (image
->assembly
->dynamic
&& (image
->assembly
== assembly
->image
.assembly
)) {
2140 table
= &assembly
->tables
[MONO_TABLE_MODULEREF
];
2141 token
= table
->next_idx
++;
2143 alloc_table (table
, table
->rows
);
2144 values
= table
->values
+ token
* MONO_MODULEREF_SIZE
;
2145 values
[MONO_MODULEREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->module_name
);
2147 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2148 token
|= MONO_RESOLTION_SCOPE_MODULEREF
;
2149 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2154 if (image
->assembly
->dynamic
)
2156 memset (cols
, 0, sizeof (cols
));
2158 /* image->assembly->image is the manifest module */
2159 image
= image
->assembly
->image
;
2160 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_ASSEMBLY
], 0, cols
, MONO_ASSEMBLY_SIZE
);
2163 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLYREF
];
2164 token
= table
->next_idx
++;
2166 alloc_table (table
, table
->rows
);
2167 values
= table
->values
+ token
* MONO_ASSEMBLYREF_SIZE
;
2168 values
[MONO_ASSEMBLYREF_NAME
] = string_heap_insert (&assembly
->sheap
, image
->assembly_name
);
2169 values
[MONO_ASSEMBLYREF_MAJOR_VERSION
] = cols
[MONO_ASSEMBLY_MAJOR_VERSION
];
2170 values
[MONO_ASSEMBLYREF_MINOR_VERSION
] = cols
[MONO_ASSEMBLY_MINOR_VERSION
];
2171 values
[MONO_ASSEMBLYREF_BUILD_NUMBER
] = cols
[MONO_ASSEMBLY_BUILD_NUMBER
];
2172 values
[MONO_ASSEMBLYREF_REV_NUMBER
] = cols
[MONO_ASSEMBLY_REV_NUMBER
];
2173 values
[MONO_ASSEMBLYREF_FLAGS
] = 0;
2174 values
[MONO_ASSEMBLYREF_CULTURE
] = 0;
2175 values
[MONO_ASSEMBLYREF_HASH_VALUE
] = 0;
2177 if (strcmp ("", image
->assembly
->aname
.culture
)) {
2178 values
[MONO_ASSEMBLYREF_CULTURE
] = string_heap_insert (&assembly
->sheap
,
2179 image
->assembly
->aname
.culture
);
2182 if ((pubkey
= mono_image_get_public_key (image
, &publen
))) {
2183 guchar pubtoken
[9];
2185 mono_digest_get_public_token (pubtoken
+ 1, (guchar
*)pubkey
, publen
);
2186 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = mono_image_add_stream_data (&assembly
->blob
, (char*)pubtoken
, 9);
2188 values
[MONO_ASSEMBLYREF_PUBLIC_KEY
] = 0;
2190 token
<<= MONO_RESOLTION_SCOPE_BITS
;
2191 token
|= MONO_RESOLTION_SCOPE_ASSEMBLYREF
;
2192 g_hash_table_insert (assembly
->handleref
, image
, GUINT_TO_POINTER (token
));
2197 create_typespec (MonoDynamicImage
*assembly
, MonoType
*type
)
2199 MonoDynamicTable
*table
;
2204 if ((token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, type
))))
2207 sigbuffer_init (&buf
, 32);
2208 switch (type
->type
) {
2209 case MONO_TYPE_FNPTR
:
2211 case MONO_TYPE_SZARRAY
:
2212 case MONO_TYPE_ARRAY
:
2214 case MONO_TYPE_MVAR
:
2215 case MONO_TYPE_GENERICINST
:
2216 encode_type (assembly
, type
, &buf
);
2218 case MONO_TYPE_CLASS
:
2219 case MONO_TYPE_VALUETYPE
: {
2220 MonoClass
*k
= mono_class_from_mono_type (type
);
2221 if (!k
|| !k
->generic_container
) {
2222 sigbuffer_free (&buf
);
2225 encode_type (assembly
, type
, &buf
);
2229 sigbuffer_free (&buf
);
2233 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2234 if (assembly
->save
) {
2235 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2236 alloc_table (table
, table
->rows
+ 1);
2237 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2238 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2240 sigbuffer_free (&buf
);
2242 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2243 g_hash_table_insert (assembly
->typespec
, type
, GUINT_TO_POINTER(token
));
2249 mono_image_typedef_or_ref_full (MonoDynamicImage
*assembly
, MonoType
*type
, gboolean try_typespec
)
2251 MonoDynamicTable
*table
;
2253 guint32 token
, scope
, enclosing
;
2256 /* if the type requires a typespec, we must try that first*/
2257 if (try_typespec
&& (token
= create_typespec (assembly
, type
)))
2259 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typeref
, type
));
2262 klass
= my_mono_class_from_mono_type (type
);
2264 klass
= mono_class_from_mono_type (type
);
2267 * If it's in the same module and not a generic type parameter:
2269 if ((klass
->image
== &assembly
->image
) && (type
->type
!= MONO_TYPE_VAR
) &&
2270 (type
->type
!= MONO_TYPE_MVAR
)) {
2271 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
2272 token
= MONO_TYPEDEFORREF_TYPEDEF
| (tb
->table_idx
<< MONO_TYPEDEFORREF_BITS
);
2273 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), klass
->reflection_info
);
2277 if (klass
->nested_in
) {
2278 enclosing
= mono_image_typedef_or_ref_full (assembly
, &klass
->nested_in
->byval_arg
, FALSE
);
2279 /* get the typeref idx of the enclosing type */
2280 enclosing
>>= MONO_TYPEDEFORREF_BITS
;
2281 scope
= (enclosing
<< MONO_RESOLTION_SCOPE_BITS
) | MONO_RESOLTION_SCOPE_TYPEREF
;
2283 scope
= resolution_scope_from_image (assembly
, klass
->image
);
2285 table
= &assembly
->tables
[MONO_TABLE_TYPEREF
];
2286 if (assembly
->save
) {
2287 alloc_table (table
, table
->rows
+ 1);
2288 values
= table
->values
+ table
->next_idx
* MONO_TYPEREF_SIZE
;
2289 values
[MONO_TYPEREF_SCOPE
] = scope
;
2290 values
[MONO_TYPEREF_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
2291 values
[MONO_TYPEREF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
2293 token
= MONO_TYPEDEFORREF_TYPEREF
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
); /* typeref */
2294 g_hash_table_insert (assembly
->typeref
, type
, GUINT_TO_POINTER(token
));
2296 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), klass
->reflection_info
);
2301 * Despite the name, we handle also TypeSpec (with the above helper).
2304 mono_image_typedef_or_ref (MonoDynamicImage
*assembly
, MonoType
*type
)
2306 return mono_image_typedef_or_ref_full (assembly
, type
, TRUE
);
2310 * Insert a memberef row into the metadata: the token that point to the memberref
2311 * is returned. Caching is done in the caller (mono_image_get_methodref_token() or
2312 * mono_image_get_fieldref_token()).
2313 * The sig param is an index to an already built signature.
2316 mono_image_get_memberref_token (MonoDynamicImage
*assembly
, MonoType
*type
, const char *name
, guint32 sig
)
2318 MonoDynamicTable
*table
;
2320 guint32 token
, pclass
;
2323 parent
= mono_image_typedef_or_ref (assembly
, type
);
2324 switch (parent
& MONO_TYPEDEFORREF_MASK
) {
2325 case MONO_TYPEDEFORREF_TYPEREF
:
2326 pclass
= MONO_MEMBERREF_PARENT_TYPEREF
;
2328 case MONO_TYPEDEFORREF_TYPESPEC
:
2329 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2331 case MONO_TYPEDEFORREF_TYPEDEF
:
2332 pclass
= MONO_MEMBERREF_PARENT_TYPEDEF
;
2335 g_warning ("unknown typeref or def token 0x%08x for %s", parent
, name
);
2338 /* extract the index */
2339 parent
>>= MONO_TYPEDEFORREF_BITS
;
2341 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2343 if (assembly
->save
) {
2344 alloc_table (table
, table
->rows
+ 1);
2345 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2346 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2347 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2348 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2351 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2358 mono_image_get_methodref_token (MonoDynamicImage
*assembly
, MonoMethod
*method
, gboolean create_typespec
)
2361 MonoMethodSignature
*sig
;
2363 create_typespec
= create_typespec
&& method
->is_generic
&& method
->klass
->image
!= &assembly
->image
;
2365 if (create_typespec
) {
2366 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1)));
2371 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2372 if (token
&& !create_typespec
)
2375 g_assert (!method
->is_inflated
);
2378 * A methodref signature can't contain an unmanaged calling convention.
2380 sig
= mono_metadata_signature_dup (mono_method_signature (method
));
2381 if ((sig
->call_convention
!= MONO_CALL_DEFAULT
) && (sig
->call_convention
!= MONO_CALL_VARARG
))
2382 sig
->call_convention
= MONO_CALL_DEFAULT
;
2383 token
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
,
2384 method
->name
, method_encode_signature (assembly
, sig
));
2386 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2389 if (create_typespec
) {
2390 MonoDynamicTable
*table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2391 g_assert (mono_metadata_token_table (token
) == MONO_TABLE_MEMBERREF
);
2392 token
= (mono_metadata_token_index (token
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2394 if (assembly
->save
) {
2397 alloc_table (table
, table
->rows
+ 1);
2398 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2399 values
[MONO_METHODSPEC_METHOD
] = token
;
2400 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_sig (assembly
, &mono_method_get_generic_container (method
)->context
);
2403 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2405 /*methodspec and memberef tokens are diferent, */
2406 g_hash_table_insert (assembly
->handleref
, GUINT_TO_POINTER (GPOINTER_TO_UINT (method
) + 1), GUINT_TO_POINTER (token
));
2413 mono_image_get_methodref_token_for_methodbuilder (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*method
)
2416 ReflectionMethodBuilder rmb
;
2419 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2423 name
= mono_string_to_utf8 (method
->name
);
2424 reflection_methodbuilder_from_method_builder (&rmb
, method
);
2427 * A methodref signature can't contain an unmanaged calling convention.
2428 * Since some flags are encoded as part of call_conv, we need to check against it.
2430 if ((rmb
.call_conv
& ~0x60) != MONO_CALL_DEFAULT
&& (rmb
.call_conv
& ~0x60) != MONO_CALL_VARARG
)
2431 rmb
.call_conv
= (rmb
.call_conv
& 0x60) | MONO_CALL_DEFAULT
;
2432 token
= mono_image_get_memberref_token (assembly
, ((MonoReflectionTypeBuilder
*)rmb
.type
)->type
.type
,
2433 name
, method_builder_encode_signature (assembly
, &rmb
));
2436 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2441 mono_image_get_varargs_method_token (MonoDynamicImage
*assembly
, guint32 original
,
2442 const gchar
*name
, guint32 sig
)
2444 MonoDynamicTable
*table
;
2448 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2450 if (assembly
->save
) {
2451 alloc_table (table
, table
->rows
+ 1);
2452 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2453 values
[MONO_MEMBERREF_CLASS
] = original
;
2454 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2455 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2458 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2465 encode_generic_method_definition_sig (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2469 guint32 nparams
= mono_array_length (mb
->generic_params
);
2472 if (!assembly
->save
)
2475 sigbuffer_init (&buf
, 32);
2477 sigbuffer_add_value (&buf
, 0xa);
2478 sigbuffer_add_value (&buf
, nparams
);
2480 for (i
= 0; i
< nparams
; i
++) {
2481 sigbuffer_add_value (&buf
, MONO_TYPE_MVAR
);
2482 sigbuffer_add_value (&buf
, i
);
2485 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2486 sigbuffer_free (&buf
);
2491 mono_image_get_methodspec_token_for_generic_method_definition (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
)
2493 MonoDynamicTable
*table
;
2495 guint32 token
, mtoken
= 0;
2497 token
= GPOINTER_TO_UINT (mono_g_hash_table_lookup (assembly
->methodspec
, mb
));
2501 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2503 mtoken
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2504 switch (mono_metadata_token_table (mtoken
)) {
2505 case MONO_TABLE_MEMBERREF
:
2506 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2508 case MONO_TABLE_METHOD
:
2509 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2512 g_assert_not_reached ();
2515 if (assembly
->save
) {
2516 alloc_table (table
, table
->rows
+ 1);
2517 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2518 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2519 values
[MONO_METHODSPEC_SIGNATURE
] = encode_generic_method_definition_sig (assembly
, mb
);
2522 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2525 mono_g_hash_table_insert (assembly
->methodspec
, mb
, GUINT_TO_POINTER(token
));
2530 mono_image_get_methodbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionMethodBuilder
*mb
, gboolean create_methodspec
)
2534 if (mb
->generic_params
&& create_methodspec
)
2535 return mono_image_get_methodspec_token_for_generic_method_definition (assembly
, mb
);
2537 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, mb
));
2541 token
= mono_image_get_methodref_token_for_methodbuilder (assembly
, mb
);
2542 g_hash_table_insert (assembly
->handleref
, mb
, GUINT_TO_POINTER(token
));
2547 mono_image_get_ctorbuilder_token (MonoDynamicImage
*assembly
, MonoReflectionCtorBuilder
*mb
)
2550 ReflectionMethodBuilder rmb
;
2553 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, mb
));
2557 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
2559 name
= mono_string_to_utf8 (rmb
.name
);
2560 token
= mono_image_get_memberref_token (assembly
, ((MonoReflectionTypeBuilder
*)rmb
.type
)->type
.type
,
2561 name
, method_builder_encode_signature (assembly
, &rmb
));
2564 g_hash_table_insert (assembly
->handleref
, mb
, GUINT_TO_POINTER(token
));
2569 is_field_on_inst (MonoClassField
*field
)
2571 return (field
->parent
->generic_class
&& field
->parent
->generic_class
->is_dynamic
&& ((MonoDynamicGenericClass
*)field
->parent
->generic_class
)->fields
);
2575 * If FIELD is a field of a MonoDynamicGenericClass, return its non-inflated type.
2578 get_field_on_inst_generic_type (MonoClassField
*field
)
2580 MonoDynamicGenericClass
*dgclass
;
2583 g_assert (is_field_on_inst (field
));
2585 dgclass
= (MonoDynamicGenericClass
*)field
->parent
->generic_class
;
2586 field_index
= field
- dgclass
->fields
;
2588 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
2589 return dgclass
->field_generic_types
[field_index
];
2593 mono_image_get_fieldref_token (MonoDynamicImage
*assembly
, MonoReflectionField
*f
)
2597 MonoClassField
*field
;
2599 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, f
));
2602 g_assert (f
->field
->parent
);
2605 if (field
->parent
->generic_class
&& field
->parent
->generic_class
->container_class
&& field
->parent
->generic_class
->container_class
->fields
) {
2606 int index
= field
- field
->parent
->fields
;
2607 type
= field
->parent
->generic_class
->container_class
->fields
[index
].type
;
2609 if (is_field_on_inst (f
->field
))
2610 type
= get_field_on_inst_generic_type (f
->field
);
2612 type
= f
->field
->type
;
2614 token
= mono_image_get_memberref_token (assembly
, &f
->field
->parent
->byval_arg
,
2615 mono_field_get_name (f
->field
),
2616 fieldref_encode_signature (assembly
, type
));
2617 g_hash_table_insert (assembly
->handleref
, f
, GUINT_TO_POINTER(token
));
2622 mono_image_get_field_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionFieldOnTypeBuilderInst
*f
)
2626 MonoGenericClass
*gclass
;
2627 MonoDynamicGenericClass
*dgclass
;
2628 MonoReflectionFieldBuilder
*fb
= f
->fb
;
2631 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, f
));
2634 klass
= mono_class_from_mono_type (f
->inst
->type
.type
);
2635 gclass
= f
->inst
->type
.type
->data
.generic_class
;
2636 g_assert (gclass
->is_dynamic
);
2637 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2639 name
= mono_string_to_utf8 (fb
->name
);
2640 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
,
2641 field_encode_signature (assembly
, fb
));
2643 g_hash_table_insert (assembly
->handleref
, f
, GUINT_TO_POINTER (token
));
2648 mono_image_get_ctor_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionCtorOnTypeBuilderInst
*c
, gboolean create_methodspec
)
2652 MonoGenericClass
*gclass
;
2653 MonoDynamicGenericClass
*dgclass
;
2654 MonoReflectionCtorBuilder
*cb
= c
->cb
;
2655 ReflectionMethodBuilder rmb
;
2658 /* A ctor cannot be a generic method, so we can ignore create_methodspec */
2660 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, c
));
2663 klass
= mono_class_from_mono_type (c
->inst
->type
.type
);
2664 gclass
= c
->inst
->type
.type
->data
.generic_class
;
2665 g_assert (gclass
->is_dynamic
);
2666 dgclass
= (MonoDynamicGenericClass
*) gclass
;
2668 reflection_methodbuilder_from_ctor_builder (&rmb
, cb
);
2670 name
= mono_string_to_utf8 (rmb
.name
);
2672 sig
= method_builder_encode_signature (assembly
, &rmb
);
2674 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2677 g_hash_table_insert (assembly
->handleref
, c
, GUINT_TO_POINTER (token
));
2682 mono_image_get_method_on_inst_token (MonoDynamicImage
*assembly
, MonoReflectionMethodOnTypeBuilderInst
*m
, gboolean create_methodspec
)
2686 MonoGenericClass
*gclass
;
2687 MonoReflectionMethodBuilder
*mb
= m
->mb
;
2688 ReflectionMethodBuilder rmb
;
2691 if (create_methodspec
&& mb
->generic_params
)
2693 g_assert_not_reached ();
2695 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, m
));
2698 klass
= mono_class_from_mono_type (m
->inst
->type
.type
);
2699 gclass
= m
->inst
->type
.type
->data
.generic_class
;
2700 g_assert (gclass
->is_dynamic
);
2702 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
2704 name
= mono_string_to_utf8 (rmb
.name
);
2706 sig
= method_builder_encode_signature (assembly
, &rmb
);
2708 token
= mono_image_get_memberref_token (assembly
, &klass
->byval_arg
, name
, sig
);
2711 g_hash_table_insert (assembly
->handleref
, m
, GUINT_TO_POINTER (token
));
2716 encode_generic_method_sig (MonoDynamicImage
*assembly
, MonoGenericContext
*context
)
2720 guint32 nparams
= context
->method_inst
->type_argc
;
2723 if (!assembly
->save
)
2726 sigbuffer_init (&buf
, 32);
2728 * FIXME: vararg, explicit_this, differenc call_conv values...
2730 sigbuffer_add_value (&buf
, 0xa); /* FIXME FIXME FIXME */
2731 sigbuffer_add_value (&buf
, nparams
);
2733 for (i
= 0; i
< nparams
; i
++)
2734 encode_type (assembly
, context
->method_inst
->type_argv
[i
], &buf
);
2736 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2737 sigbuffer_free (&buf
);
2742 method_encode_methodspec (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2744 MonoDynamicTable
*table
;
2746 guint32 token
, mtoken
= 0, sig
;
2747 MonoMethodInflated
*imethod
;
2748 MonoMethod
*declaring
;
2750 table
= &assembly
->tables
[MONO_TABLE_METHODSPEC
];
2752 g_assert (method
->is_inflated
);
2753 imethod
= (MonoMethodInflated
*) method
;
2754 declaring
= imethod
->declaring
;
2756 sig
= method_encode_signature (assembly
, mono_method_signature (declaring
));
2757 mtoken
= mono_image_get_memberref_token (assembly
, &method
->klass
->byval_arg
, declaring
->name
, sig
);
2759 if (!mono_method_signature (declaring
)->generic_param_count
)
2762 switch (mono_metadata_token_table (mtoken
)) {
2763 case MONO_TABLE_MEMBERREF
:
2764 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODREF
;
2766 case MONO_TABLE_METHOD
:
2767 mtoken
= (mono_metadata_token_index (mtoken
) << MONO_METHODDEFORREF_BITS
) | MONO_METHODDEFORREF_METHODDEF
;
2770 g_assert_not_reached ();
2773 sig
= encode_generic_method_sig (assembly
, mono_method_get_context (method
));
2775 if (assembly
->save
) {
2776 alloc_table (table
, table
->rows
+ 1);
2777 values
= table
->values
+ table
->next_idx
* MONO_METHODSPEC_SIZE
;
2778 values
[MONO_METHODSPEC_METHOD
] = mtoken
;
2779 values
[MONO_METHODSPEC_SIGNATURE
] = sig
;
2782 token
= MONO_TOKEN_METHOD_SPEC
| table
->next_idx
;
2789 mono_image_get_methodspec_token (MonoDynamicImage
*assembly
, MonoMethod
*method
)
2791 MonoMethodInflated
*imethod
;
2794 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, method
));
2798 g_assert (method
->is_inflated
);
2799 imethod
= (MonoMethodInflated
*) method
;
2801 if (mono_method_signature (imethod
->declaring
)->generic_param_count
) {
2802 token
= method_encode_methodspec (assembly
, method
);
2804 guint32 sig
= method_encode_signature (
2805 assembly
, mono_method_signature (imethod
->declaring
));
2806 token
= mono_image_get_memberref_token (
2807 assembly
, &method
->klass
->byval_arg
, method
->name
, sig
);
2810 g_hash_table_insert (assembly
->handleref
, method
, GUINT_TO_POINTER(token
));
2815 mono_image_get_inflated_method_token (MonoDynamicImage
*assembly
, MonoMethod
*m
)
2817 MonoMethodInflated
*imethod
= (MonoMethodInflated
*) m
;
2820 sig
= method_encode_signature (assembly
, mono_method_signature (imethod
->declaring
));
2821 token
= mono_image_get_memberref_token (
2822 assembly
, &m
->klass
->byval_arg
, m
->name
, sig
);
2828 create_generic_typespec (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
)
2830 MonoDynamicTable
*table
;
2838 * We're creating a TypeSpec for the TypeBuilder of a generic type declaration,
2839 * ie. what we'd normally use as the generic type in a TypeSpec signature.
2840 * Because of this, we must not insert it into the `typeref' hash table.
2843 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->typespec
, tb
->type
.type
));
2847 sigbuffer_init (&buf
, 32);
2849 g_assert (tb
->generic_params
);
2850 klass
= mono_class_from_mono_type (tb
->type
.type
);
2852 if (tb
->generic_container
)
2853 mono_reflection_create_generic_class (tb
);
2855 sigbuffer_add_value (&buf
, MONO_TYPE_GENERICINST
);
2856 g_assert (klass
->generic_container
);
2857 sigbuffer_add_value (&buf
, klass
->byval_arg
.type
);
2858 sigbuffer_add_value (&buf
, mono_image_typedef_or_ref_full (assembly
, &klass
->byval_arg
, FALSE
));
2860 count
= mono_array_length (tb
->generic_params
);
2861 sigbuffer_add_value (&buf
, count
);
2862 for (i
= 0; i
< count
; i
++) {
2863 MonoReflectionGenericParam
*gparam
;
2865 gparam
= mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
);
2867 encode_type (assembly
, gparam
->type
.type
, &buf
);
2870 table
= &assembly
->tables
[MONO_TABLE_TYPESPEC
];
2872 if (assembly
->save
) {
2873 token
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
2874 alloc_table (table
, table
->rows
+ 1);
2875 values
= table
->values
+ table
->next_idx
* MONO_TYPESPEC_SIZE
;
2876 values
[MONO_TYPESPEC_SIGNATURE
] = token
;
2878 sigbuffer_free (&buf
);
2880 token
= MONO_TYPEDEFORREF_TYPESPEC
| (table
->next_idx
<< MONO_TYPEDEFORREF_BITS
);
2881 g_hash_table_insert (assembly
->typespec
, tb
->type
.type
, GUINT_TO_POINTER(token
));
2887 * Return a copy of TYPE, adding the custom modifiers in MODREQ and MODOPT.
2890 add_custom_modifiers (MonoDynamicImage
*assembly
, MonoType
*type
, MonoArray
*modreq
, MonoArray
*modopt
)
2892 int i
, count
, len
, pos
;
2897 count
+= mono_array_length (modreq
);
2899 count
+= mono_array_length (modopt
);
2902 return mono_metadata_type_dup (NULL
, type
);
2904 len
= sizeof (MonoType
) + ((gint32
)count
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoCustomMod
);
2906 memcpy (t
, type
, len
);
2908 t
->num_mods
= count
;
2911 for (i
= 0; i
< mono_array_length (modreq
); ++i
) {
2912 MonoReflectionType
*mod
= mono_type_array_get (modreq
, i
);
2913 t
->modifiers
[pos
].required
= 1;
2914 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
->type
);
2919 for (i
= 0; i
< mono_array_length (modopt
); ++i
) {
2920 MonoReflectionType
*mod
= mono_type_array_get (modopt
, i
);
2921 t
->modifiers
[pos
].required
= 0;
2922 t
->modifiers
[pos
].token
= mono_image_typedef_or_ref (assembly
, mod
->type
);
2931 mono_image_get_generic_field_token (MonoDynamicImage
*assembly
, MonoReflectionFieldBuilder
*fb
)
2933 MonoDynamicTable
*table
;
2935 MonoType
*custom
= NULL
;
2937 guint32 token
, pclass
, parent
, sig
;
2940 token
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->handleref
, fb
));
2944 klass
= mono_class_from_mono_type (fb
->typeb
->type
);
2945 name
= mono_string_to_utf8 (fb
->name
);
2947 /* fb->type does not include the custom modifiers */
2948 /* FIXME: We should do this in one place when a fieldbuilder is created */
2949 if (fb
->modreq
|| fb
->modopt
) {
2950 custom
= add_custom_modifiers (assembly
, monotype_cast (fb
->type
)->type
, fb
->modreq
, fb
->modopt
);
2951 sig
= fieldref_encode_signature (assembly
, custom
);
2954 sig
= fieldref_encode_signature (assembly
, monotype_cast (fb
->type
)->type
);
2957 parent
= create_generic_typespec (assembly
, (MonoReflectionTypeBuilder
*) fb
->typeb
);
2958 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_TYPEDEFORREF_TYPESPEC
);
2960 pclass
= MONO_MEMBERREF_PARENT_TYPESPEC
;
2961 parent
>>= MONO_TYPEDEFORREF_BITS
;
2963 table
= &assembly
->tables
[MONO_TABLE_MEMBERREF
];
2965 if (assembly
->save
) {
2966 alloc_table (table
, table
->rows
+ 1);
2967 values
= table
->values
+ table
->next_idx
* MONO_MEMBERREF_SIZE
;
2968 values
[MONO_MEMBERREF_CLASS
] = pclass
| (parent
<< MONO_MEMBERREF_PARENT_BITS
);
2969 values
[MONO_MEMBERREF_NAME
] = string_heap_insert (&assembly
->sheap
, name
);
2970 values
[MONO_MEMBERREF_SIGNATURE
] = sig
;
2973 token
= MONO_TOKEN_MEMBER_REF
| table
->next_idx
;
2975 g_hash_table_insert (assembly
->handleref
, fb
, GUINT_TO_POINTER(token
));
2981 mono_reflection_encode_sighelper (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
2988 if (!assembly
->save
)
2991 /* FIXME: this means SignatureHelper.SignatureHelpType.HELPER_METHOD */
2992 g_assert (helper
->type
== 2);
2994 if (helper
->arguments
)
2995 nargs
= mono_array_length (helper
->arguments
);
2999 size
= 10 + (nargs
* 10);
3001 sigbuffer_init (&buf
, 32);
3003 /* Encode calling convention */
3004 /* Change Any to Standard */
3005 if ((helper
->call_conv
& 0x03) == 0x03)
3006 helper
->call_conv
= 0x01;
3007 /* explicit_this implies has_this */
3008 if (helper
->call_conv
& 0x40)
3009 helper
->call_conv
&= 0x20;
3011 if (helper
->call_conv
== 0) { /* Unmanaged */
3012 idx
= helper
->unmanaged_call_conv
- 1;
3015 idx
= helper
->call_conv
& 0x60; /* has_this + explicit_this */
3016 if (helper
->call_conv
& 0x02) /* varargs */
3020 sigbuffer_add_byte (&buf
, idx
);
3021 sigbuffer_add_value (&buf
, nargs
);
3022 encode_reflection_type (assembly
, helper
->return_type
, &buf
);
3023 for (i
= 0; i
< nargs
; ++i
) {
3024 MonoArray
*modreqs
= NULL
;
3025 MonoArray
*modopts
= NULL
;
3026 MonoReflectionType
*pt
;
3028 if (helper
->modreqs
&& (i
< mono_array_length (helper
->modreqs
)))
3029 modreqs
= mono_array_get (helper
->modreqs
, MonoArray
*, i
);
3030 if (helper
->modopts
&& (i
< mono_array_length (helper
->modopts
)))
3031 modopts
= mono_array_get (helper
->modopts
, MonoArray
*, i
);
3033 encode_custom_modifiers (assembly
, modreqs
, modopts
, &buf
);
3034 pt
= mono_type_array_get (helper
->arguments
, i
);
3035 encode_reflection_type (assembly
, pt
, &buf
);
3037 idx
= sigbuffer_add_to_blob_cached (assembly
, &buf
);
3038 sigbuffer_free (&buf
);
3044 mono_image_get_sighelper_token (MonoDynamicImage
*assembly
, MonoReflectionSigHelper
*helper
)
3047 MonoDynamicTable
*table
;
3050 table
= &assembly
->tables
[MONO_TABLE_STANDALONESIG
];
3051 idx
= table
->next_idx
++;
3053 alloc_table (table
, table
->rows
);
3054 values
= table
->values
+ idx
* MONO_STAND_ALONE_SIGNATURE_SIZE
;
3056 values
[MONO_STAND_ALONE_SIGNATURE
] =
3057 mono_reflection_encode_sighelper (assembly
, helper
);
3063 reflection_cc_to_file (int call_conv
) {
3064 switch (call_conv
& 0x3) {
3066 case 1: return MONO_CALL_DEFAULT
;
3067 case 2: return MONO_CALL_VARARG
;
3069 g_assert_not_reached ();
3076 MonoMethodSignature
*sig
;
3082 mono_image_get_array_token (MonoDynamicImage
*assembly
, MonoReflectionArrayMethod
*m
)
3087 MonoMethodSignature
*sig
;
3090 name
= mono_string_to_utf8 (m
->name
);
3091 nparams
= mono_array_length (m
->parameters
);
3092 sig
= g_malloc0 (sizeof (MonoMethodSignature
) + sizeof (MonoType
*) * nparams
);
3094 sig
->sentinelpos
= -1;
3095 sig
->call_convention
= reflection_cc_to_file (m
->call_conv
);
3096 sig
->param_count
= nparams
;
3097 sig
->ret
= m
->ret
? m
->ret
->type
: &mono_defaults
.void_class
->byval_arg
;
3098 for (i
= 0; i
< nparams
; ++i
) {
3099 MonoReflectionType
*t
= mono_type_array_get (m
->parameters
, i
);
3100 sig
->params
[i
] = t
->type
;
3103 for (tmp
= assembly
->array_methods
; tmp
; tmp
= tmp
->next
) {
3105 if (strcmp (name
, am
->name
) == 0 &&
3106 mono_metadata_type_equal (am
->parent
, m
->parent
->type
) &&
3107 mono_metadata_signature_equal (am
->sig
, sig
)) {
3110 m
->table_idx
= am
->token
& 0xffffff;
3114 am
= g_new0 (ArrayMethod
, 1);
3117 am
->parent
= m
->parent
->type
;
3118 am
->token
= mono_image_get_memberref_token (assembly
, am
->parent
, name
,
3119 method_encode_signature (assembly
, sig
));
3120 assembly
->array_methods
= g_list_prepend (assembly
->array_methods
, am
);
3121 m
->table_idx
= am
->token
& 0xffffff;
3126 * Insert into the metadata tables all the info about the TypeBuilder tb.
3127 * Data in the tables is inserted in a predefined order, since some tables need to be sorted.
3130 mono_image_get_type_info (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
, MonoDynamicImage
*assembly
)
3132 MonoDynamicTable
*table
;
3134 int i
, is_object
= 0, is_system
= 0;
3137 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
3138 values
= table
->values
+ tb
->table_idx
* MONO_TYPEDEF_SIZE
;
3139 values
[MONO_TYPEDEF_FLAGS
] = tb
->attrs
;
3140 n
= mono_string_to_utf8 (tb
->name
);
3141 if (strcmp (n
, "Object") == 0)
3143 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, n
);
3145 n
= mono_string_to_utf8 (tb
->nspace
);
3146 if (strcmp (n
, "System") == 0)
3148 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, n
);
3150 if (tb
->parent
&& !(is_system
&& is_object
) &&
3151 !(tb
->attrs
& TYPE_ATTRIBUTE_INTERFACE
)) { /* interfaces don't have a parent */
3152 values
[MONO_TYPEDEF_EXTENDS
] = mono_image_typedef_or_ref (assembly
, monotype_cast (tb
->parent
)->type
);
3154 values
[MONO_TYPEDEF_EXTENDS
] = 0;
3156 values
[MONO_TYPEDEF_FIELD_LIST
] = assembly
->tables
[MONO_TABLE_FIELD
].next_idx
;
3157 values
[MONO_TYPEDEF_METHOD_LIST
] = assembly
->tables
[MONO_TABLE_METHOD
].next_idx
;
3160 * if we have explicitlayout or sequentiallayouts, output data in the
3161 * ClassLayout table.
3163 if (((tb
->attrs
& TYPE_ATTRIBUTE_LAYOUT_MASK
) != TYPE_ATTRIBUTE_AUTO_LAYOUT
) &&
3164 ((tb
->class_size
> 0) || (tb
->packing_size
> 0))) {
3165 table
= &assembly
->tables
[MONO_TABLE_CLASSLAYOUT
];
3167 alloc_table (table
, table
->rows
);
3168 values
= table
->values
+ table
->rows
* MONO_CLASS_LAYOUT_SIZE
;
3169 values
[MONO_CLASS_LAYOUT_PARENT
] = tb
->table_idx
;
3170 values
[MONO_CLASS_LAYOUT_CLASS_SIZE
] = tb
->class_size
;
3171 values
[MONO_CLASS_LAYOUT_PACKING_SIZE
] = tb
->packing_size
;
3174 /* handle interfaces */
3175 if (tb
->interfaces
) {
3176 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3178 table
->rows
+= mono_array_length (tb
->interfaces
);
3179 alloc_table (table
, table
->rows
);
3180 values
= table
->values
+ (i
+ 1) * MONO_INTERFACEIMPL_SIZE
;
3181 for (i
= 0; i
< mono_array_length (tb
->interfaces
); ++i
) {
3182 MonoReflectionType
* iface
= (MonoReflectionType
*) mono_array_get (tb
->interfaces
, gpointer
, i
);
3183 values
[MONO_INTERFACEIMPL_CLASS
] = tb
->table_idx
;
3184 values
[MONO_INTERFACEIMPL_INTERFACE
] = mono_image_typedef_or_ref (assembly
, iface
->type
);
3185 values
+= MONO_INTERFACEIMPL_SIZE
;
3191 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
3192 table
->rows
+= tb
->num_fields
;
3193 alloc_table (table
, table
->rows
);
3194 for (i
= 0; i
< tb
->num_fields
; ++i
)
3195 mono_image_get_field_info (
3196 mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
3199 /* handle constructors */
3201 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3202 table
->rows
+= mono_array_length (tb
->ctors
);
3203 alloc_table (table
, table
->rows
);
3204 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
)
3205 mono_image_get_ctor_info (domain
,
3206 mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
), assembly
);
3209 /* handle methods */
3211 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
3212 table
->rows
+= tb
->num_methods
;
3213 alloc_table (table
, table
->rows
);
3214 for (i
= 0; i
< tb
->num_methods
; ++i
)
3215 mono_image_get_method_info (
3216 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
3219 /* Do the same with properties etc.. */
3220 if (tb
->events
&& mono_array_length (tb
->events
)) {
3221 table
= &assembly
->tables
[MONO_TABLE_EVENT
];
3222 table
->rows
+= mono_array_length (tb
->events
);
3223 alloc_table (table
, table
->rows
);
3224 table
= &assembly
->tables
[MONO_TABLE_EVENTMAP
];
3226 alloc_table (table
, table
->rows
);
3227 values
= table
->values
+ table
->rows
* MONO_EVENT_MAP_SIZE
;
3228 values
[MONO_EVENT_MAP_PARENT
] = tb
->table_idx
;
3229 values
[MONO_EVENT_MAP_EVENTLIST
] = assembly
->tables
[MONO_TABLE_EVENT
].next_idx
;
3230 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
)
3231 mono_image_get_event_info (
3232 mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
), assembly
);
3234 if (tb
->properties
&& mono_array_length (tb
->properties
)) {
3235 table
= &assembly
->tables
[MONO_TABLE_PROPERTY
];
3236 table
->rows
+= mono_array_length (tb
->properties
);
3237 alloc_table (table
, table
->rows
);
3238 table
= &assembly
->tables
[MONO_TABLE_PROPERTYMAP
];
3240 alloc_table (table
, table
->rows
);
3241 values
= table
->values
+ table
->rows
* MONO_PROPERTY_MAP_SIZE
;
3242 values
[MONO_PROPERTY_MAP_PARENT
] = tb
->table_idx
;
3243 values
[MONO_PROPERTY_MAP_PROPERTY_LIST
] = assembly
->tables
[MONO_TABLE_PROPERTY
].next_idx
;
3244 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
)
3245 mono_image_get_property_info (
3246 mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
), assembly
);
3249 /* handle generic parameters */
3250 if (tb
->generic_params
) {
3251 table
= &assembly
->tables
[MONO_TABLE_GENERICPARAM
];
3252 table
->rows
+= mono_array_length (tb
->generic_params
);
3253 alloc_table (table
, table
->rows
);
3254 for (i
= 0; i
< mono_array_length (tb
->generic_params
); ++i
) {
3255 guint32 owner
= MONO_TYPEORMETHOD_TYPE
| (tb
->table_idx
<< MONO_TYPEORMETHOD_BITS
);
3257 mono_image_get_generic_param_info (
3258 mono_array_get (tb
->generic_params
, MonoReflectionGenericParam
*, i
), owner
, assembly
);
3262 mono_image_add_decl_security (assembly
,
3263 mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
), tb
->permissions
);
3266 MonoDynamicTable
*ntable
;
3268 ntable
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3269 ntable
->rows
+= mono_array_length (tb
->subtypes
);
3270 alloc_table (ntable
, ntable
->rows
);
3271 values
= ntable
->values
+ ntable
->next_idx
* MONO_NESTED_CLASS_SIZE
;
3273 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
3274 MonoReflectionTypeBuilder
*subtype
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3276 values
[MONO_NESTED_CLASS_NESTED
] = subtype
->table_idx
;
3277 values
[MONO_NESTED_CLASS_ENCLOSING
] = tb
->table_idx
;
3278 /*g_print ("nesting %s (%d) in %s (%d) (rows %d/%d)\n",
3279 mono_string_to_utf8 (subtype->name), subtype->table_idx,
3280 mono_string_to_utf8 (tb->name), tb->table_idx,
3281 ntable->next_idx, ntable->rows);*/
3282 values
+= MONO_NESTED_CLASS_SIZE
;
3289 collect_types (GPtrArray
*types
, MonoReflectionTypeBuilder
*type
)
3293 g_ptr_array_add (types
, type
); /* FIXME: GC object added to unmanaged memory */
3295 if (!type
->subtypes
)
3298 for (i
= 0; i
< mono_array_length (type
->subtypes
); ++i
) {
3299 MonoReflectionTypeBuilder
*subtype
= mono_array_get (type
->subtypes
, MonoReflectionTypeBuilder
*, i
);
3300 collect_types (types
, subtype
);
3305 compare_types_by_table_idx (MonoReflectionTypeBuilder
**type1
, MonoReflectionTypeBuilder
**type2
)
3307 if ((*type1
)->table_idx
< (*type2
)->table_idx
)
3310 if ((*type1
)->table_idx
> (*type2
)->table_idx
)
3317 params_add_cattrs (MonoDynamicImage
*assembly
, MonoArray
*pinfo
) {
3322 for (i
= 0; i
< mono_array_length (pinfo
); ++i
) {
3323 MonoReflectionParamBuilder
*pb
;
3324 pb
= mono_array_get (pinfo
, MonoReflectionParamBuilder
*, i
);
3327 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PARAMDEF
, pb
->cattrs
);
3332 type_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionTypeBuilder
*tb
) {
3335 mono_image_add_cattrs (assembly
, tb
->table_idx
, MONO_CUSTOM_ATTR_TYPEDEF
, tb
->cattrs
);
3337 for (i
= 0; i
< tb
->num_fields
; ++i
) {
3338 MonoReflectionFieldBuilder
* fb
;
3339 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, i
);
3340 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3344 for (i
= 0; i
< mono_array_length (tb
->events
); ++i
) {
3345 MonoReflectionEventBuilder
* eb
;
3346 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
3347 mono_image_add_cattrs (assembly
, eb
->table_idx
, MONO_CUSTOM_ATTR_EVENT
, eb
->cattrs
);
3350 if (tb
->properties
) {
3351 for (i
= 0; i
< mono_array_length (tb
->properties
); ++i
) {
3352 MonoReflectionPropertyBuilder
* pb
;
3353 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
3354 mono_image_add_cattrs (assembly
, pb
->table_idx
, MONO_CUSTOM_ATTR_PROPERTY
, pb
->cattrs
);
3358 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
3359 MonoReflectionCtorBuilder
* cb
;
3360 cb
= mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
);
3361 mono_image_add_cattrs (assembly
, cb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, cb
->cattrs
);
3362 params_add_cattrs (assembly
, cb
->pinfo
);
3367 for (i
= 0; i
< tb
->num_methods
; ++i
) {
3368 MonoReflectionMethodBuilder
* mb
;
3369 mb
= mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
3370 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3371 params_add_cattrs (assembly
, mb
->pinfo
);
3376 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3377 type_add_cattrs (assembly
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
));
3382 module_add_cattrs (MonoDynamicImage
*assembly
, MonoReflectionModuleBuilder
*moduleb
)
3386 mono_image_add_cattrs (assembly
, moduleb
->table_idx
, MONO_CUSTOM_ATTR_MODULE
, moduleb
->cattrs
);
3388 if (moduleb
->global_methods
) {
3389 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
3390 MonoReflectionMethodBuilder
* mb
= mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
3391 mono_image_add_cattrs (assembly
, mb
->table_idx
, MONO_CUSTOM_ATTR_METHODDEF
, mb
->cattrs
);
3392 params_add_cattrs (assembly
, mb
->pinfo
);
3396 if (moduleb
->global_fields
) {
3397 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
) {
3398 MonoReflectionFieldBuilder
*fb
= mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
);
3399 mono_image_add_cattrs (assembly
, fb
->table_idx
, MONO_CUSTOM_ATTR_FIELDDEF
, fb
->cattrs
);
3403 if (moduleb
->types
) {
3404 for (i
= 0; i
< moduleb
->num_types
; ++i
)
3405 type_add_cattrs (assembly
, mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
));
3410 mono_image_fill_file_table (MonoDomain
*domain
, MonoReflectionModule
*module
, MonoDynamicImage
*assembly
)
3412 MonoDynamicTable
*table
;
3416 char *b
= blob_size
;
3419 table
= &assembly
->tables
[MONO_TABLE_FILE
];
3421 alloc_table (table
, table
->rows
);
3422 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
3423 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_METADATA
;
3424 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, module
->image
->module_name
);
3425 if (module
->image
->dynamic
) {
3426 /* This depends on the fact that the main module is emitted last */
3427 dir
= mono_string_to_utf8 (((MonoReflectionModuleBuilder
*)module
)->assemblyb
->dir
);
3428 path
= g_strdup_printf ("%s%c%s", dir
, G_DIR_SEPARATOR
, module
->image
->module_name
);
3431 path
= g_strdup (module
->image
->name
);
3433 mono_sha1_get_digest_from_file (path
, hash
);
3436 mono_metadata_encode_value (20, b
, &b
);
3437 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
3438 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
3443 mono_image_fill_module_table (MonoDomain
*domain
, MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
)
3445 MonoDynamicTable
*table
;
3448 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
3449 mb
->table_idx
= table
->next_idx
++;
3450 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, mb
->module
.name
);
3451 i
= mono_image_add_stream_data (&assembly
->guid
, mono_array_addr (mb
->guid
, char, 0), 16);
3454 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_GENERATION
] = 0;
3455 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_MVID
] = i
;
3456 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENC
] = 0;
3457 table
->values
[mb
->table_idx
* MONO_MODULE_SIZE
+ MONO_MODULE_ENCBASE
] = 0;
3461 mono_image_fill_export_table_from_class (MonoDomain
*domain
, MonoClass
*klass
,
3462 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3464 MonoDynamicTable
*table
;
3468 visib
= klass
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
3469 if (! ((visib
& TYPE_ATTRIBUTE_PUBLIC
) || (visib
& TYPE_ATTRIBUTE_NESTED_PUBLIC
)))
3472 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3474 alloc_table (table
, table
->rows
);
3475 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3477 values
[MONO_EXP_TYPE_FLAGS
] = klass
->flags
;
3478 values
[MONO_EXP_TYPE_TYPEDEF
] = klass
->type_token
;
3479 if (klass
->nested_in
)
3480 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (parent_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_EXP_TYPE
;
3482 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (module_index
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_FILE
;
3483 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3484 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3486 res
= table
->next_idx
;
3490 /* Emit nested types */
3491 if (klass
->ext
&& klass
->ext
->nested_classes
) {
3494 for (tmp
= klass
->ext
->nested_classes
; tmp
; tmp
= tmp
->next
)
3495 mono_image_fill_export_table_from_class (domain
, tmp
->data
, module_index
, table
->next_idx
- 1, assembly
);
3502 mono_image_fill_export_table (MonoDomain
*domain
, MonoReflectionTypeBuilder
*tb
,
3503 guint32 module_index
, guint32 parent_index
, MonoDynamicImage
*assembly
)
3508 klass
= mono_class_from_mono_type (tb
->type
.type
);
3510 klass
->type_token
= mono_metadata_make_token (MONO_TABLE_TYPEDEF
, tb
->table_idx
);
3512 idx
= mono_image_fill_export_table_from_class (domain
, klass
, module_index
,
3513 parent_index
, assembly
);
3517 * We need to do this ourselves since klass->nested_classes is not set up.
3520 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
)
3521 mono_image_fill_export_table (domain
, mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
), module_index
, idx
, assembly
);
3526 mono_image_fill_export_table_from_module (MonoDomain
*domain
, MonoReflectionModule
*module
,
3527 guint32 module_index
, MonoDynamicImage
*assembly
)
3529 MonoImage
*image
= module
->image
;
3533 t
= &image
->tables
[MONO_TABLE_TYPEDEF
];
3535 for (i
= 0; i
< t
->rows
; ++i
) {
3536 MonoClass
*klass
= mono_class_get (image
, mono_metadata_make_token (MONO_TABLE_TYPEDEF
, i
+ 1));
3538 if (klass
->flags
& TYPE_ATTRIBUTE_PUBLIC
)
3539 mono_image_fill_export_table_from_class (domain
, klass
, module_index
, 0, assembly
);
3544 mono_image_fill_export_table_from_type_forwarders (MonoReflectionAssemblyBuilder
*assemblyb
, MonoDynamicImage
*assembly
)
3546 MonoDynamicTable
*table
;
3552 table
= &assembly
->tables
[MONO_TABLE_EXPORTEDTYPE
];
3554 if (assemblyb
->type_forwarders
) {
3555 for (i
= 0; i
< mono_array_length (assemblyb
->type_forwarders
); ++i
) {
3556 MonoReflectionType
*t
= mono_type_array_get (assemblyb
->type_forwarders
, i
);
3562 klass
= mono_class_from_mono_type (t
->type
);
3564 scope
= resolution_scope_from_image (assembly
, klass
->image
);
3565 g_assert ((scope
& MONO_RESOLTION_SCOPE_MASK
) == MONO_RESOLTION_SCOPE_ASSEMBLYREF
);
3566 idx
= scope
>> MONO_RESOLTION_SCOPE_BITS
;
3569 alloc_table (table
, table
->rows
);
3570 values
= table
->values
+ table
->next_idx
* MONO_EXP_TYPE_SIZE
;
3572 values
[MONO_EXP_TYPE_FLAGS
] = TYPE_ATTRIBUTE_FORWARDER
;
3573 values
[MONO_EXP_TYPE_TYPEDEF
] = 0;
3574 values
[MONO_EXP_TYPE_IMPLEMENTATION
] = (idx
<< MONO_IMPLEMENTATION_BITS
) + MONO_IMPLEMENTATION_ASSEMBLYREF
;
3575 values
[MONO_EXP_TYPE_NAME
] = string_heap_insert (&assembly
->sheap
, klass
->name
);
3576 values
[MONO_EXP_TYPE_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, klass
->name_space
);
3583 #define align_pointer(base,p)\
3585 guint32 __diff = (unsigned char*)(p)-(unsigned char*)(base);\
3587 (p) += 4 - (__diff & 3);\
3591 compare_constants (const void *a
, const void *b
)
3593 const guint32
*a_values
= a
;
3594 const guint32
*b_values
= b
;
3595 return a_values
[MONO_CONSTANT_PARENT
] - b_values
[MONO_CONSTANT_PARENT
];
3599 compare_semantics (const void *a
, const void *b
)
3601 const guint32
*a_values
= a
;
3602 const guint32
*b_values
= b
;
3603 int assoc
= a_values
[MONO_METHOD_SEMA_ASSOCIATION
] - b_values
[MONO_METHOD_SEMA_ASSOCIATION
];
3606 return a_values
[MONO_METHOD_SEMA_SEMANTICS
] - b_values
[MONO_METHOD_SEMA_SEMANTICS
];
3610 compare_custom_attrs (const void *a
, const void *b
)
3612 const guint32
*a_values
= a
;
3613 const guint32
*b_values
= b
;
3615 return a_values
[MONO_CUSTOM_ATTR_PARENT
] - b_values
[MONO_CUSTOM_ATTR_PARENT
];
3619 compare_field_marshal (const void *a
, const void *b
)
3621 const guint32
*a_values
= a
;
3622 const guint32
*b_values
= b
;
3624 return a_values
[MONO_FIELD_MARSHAL_PARENT
] - b_values
[MONO_FIELD_MARSHAL_PARENT
];
3628 compare_nested (const void *a
, const void *b
)
3630 const guint32
*a_values
= a
;
3631 const guint32
*b_values
= b
;
3633 return a_values
[MONO_NESTED_CLASS_NESTED
] - b_values
[MONO_NESTED_CLASS_NESTED
];
3637 compare_genericparam (const void *a
, const void *b
)
3639 const GenericParamTableEntry
**a_entry
= (const GenericParamTableEntry
**) a
;
3640 const GenericParamTableEntry
**b_entry
= (const GenericParamTableEntry
**) b
;
3642 if ((*b_entry
)->owner
== (*a_entry
)->owner
)
3644 (*a_entry
)->gparam
->type
.type
->data
.generic_param
->num
-
3645 (*b_entry
)->gparam
->type
.type
->data
.generic_param
->num
;
3647 return (*a_entry
)->owner
- (*b_entry
)->owner
;
3651 compare_declsecurity_attrs (const void *a
, const void *b
)
3653 const guint32
*a_values
= a
;
3654 const guint32
*b_values
= b
;
3656 return a_values
[MONO_DECL_SECURITY_PARENT
] - b_values
[MONO_DECL_SECURITY_PARENT
];
3660 compare_interface_impl (const void *a
, const void *b
)
3662 const guint32
*a_values
= a
;
3663 const guint32
*b_values
= b
;
3665 int klass
= a_values
[MONO_INTERFACEIMPL_CLASS
] - b_values
[MONO_INTERFACEIMPL_CLASS
];
3669 return a_values
[MONO_INTERFACEIMPL_INTERFACE
] - b_values
[MONO_INTERFACEIMPL_INTERFACE
];
3673 pad_heap (MonoDynamicStream
*sh
)
3675 if (sh
->index
& 3) {
3676 int sz
= 4 - (sh
->index
& 3);
3677 memset (sh
->data
+ sh
->index
, 0, sz
);
3684 MonoDynamicStream
*stream
;
3688 * build_compressed_metadata() fills in the blob of data that represents the
3689 * raw metadata as it will be saved in the PE file. The five streams are output
3690 * and the metadata tables are comnpressed from the guint32 array representation,
3691 * to the compressed on-disk format.
3694 build_compressed_metadata (MonoDynamicImage
*assembly
)
3696 MonoDynamicTable
*table
;
3698 guint64 valid_mask
= 0;
3699 guint64 sorted_mask
;
3700 guint32 heapt_size
= 0;
3701 guint32 meta_size
= 256; /* allow for header and other stuff */
3702 guint32 table_offset
;
3703 guint32 ntables
= 0;
3709 struct StreamDesc stream_desc
[5];
3711 qsort (assembly
->gen_params
->pdata
, assembly
->gen_params
->len
, sizeof (gpointer
), compare_genericparam
);
3712 for (i
= 0; i
< assembly
->gen_params
->len
; i
++){
3713 GenericParamTableEntry
*entry
= g_ptr_array_index (assembly
->gen_params
, i
);
3714 write_generic_param_entry (assembly
, entry
);
3717 stream_desc
[0].name
= "#~";
3718 stream_desc
[0].stream
= &assembly
->tstream
;
3719 stream_desc
[1].name
= "#Strings";
3720 stream_desc
[1].stream
= &assembly
->sheap
;
3721 stream_desc
[2].name
= "#US";
3722 stream_desc
[2].stream
= &assembly
->us
;
3723 stream_desc
[3].name
= "#Blob";
3724 stream_desc
[3].stream
= &assembly
->blob
;
3725 stream_desc
[4].name
= "#GUID";
3726 stream_desc
[4].stream
= &assembly
->guid
;
3728 /* tables that are sorted */
3729 sorted_mask
= ((guint64
)1 << MONO_TABLE_CONSTANT
) | ((guint64
)1 << MONO_TABLE_FIELDMARSHAL
)
3730 | ((guint64
)1 << MONO_TABLE_METHODSEMANTICS
) | ((guint64
)1 << MONO_TABLE_CLASSLAYOUT
)
3731 | ((guint64
)1 << MONO_TABLE_FIELDLAYOUT
) | ((guint64
)1 << MONO_TABLE_FIELDRVA
)
3732 | ((guint64
)1 << MONO_TABLE_IMPLMAP
) | ((guint64
)1 << MONO_TABLE_NESTEDCLASS
)
3733 | ((guint64
)1 << MONO_TABLE_METHODIMPL
) | ((guint64
)1 << MONO_TABLE_CUSTOMATTRIBUTE
)
3734 | ((guint64
)1 << MONO_TABLE_DECLSECURITY
) | ((guint64
)1 << MONO_TABLE_GENERICPARAM
)
3735 | ((guint64
)1 << MONO_TABLE_INTERFACEIMPL
);
3737 /* Compute table sizes */
3738 /* the MonoImage has already been created in mono_image_basic_init() */
3739 meta
= &assembly
->image
;
3741 /* sizes should be multiple of 4 */
3742 pad_heap (&assembly
->blob
);
3743 pad_heap (&assembly
->guid
);
3744 pad_heap (&assembly
->sheap
);
3745 pad_heap (&assembly
->us
);
3747 /* Setup the info used by compute_sizes () */
3748 meta
->idx_blob_wide
= assembly
->blob
.index
>= 65536 ? 1 : 0;
3749 meta
->idx_guid_wide
= assembly
->guid
.index
>= 65536 ? 1 : 0;
3750 meta
->idx_string_wide
= assembly
->sheap
.index
>= 65536 ? 1 : 0;
3752 meta_size
+= assembly
->blob
.index
;
3753 meta_size
+= assembly
->guid
.index
;
3754 meta_size
+= assembly
->sheap
.index
;
3755 meta_size
+= assembly
->us
.index
;
3757 for (i
=0; i
< MONO_TABLE_NUM
; ++i
)
3758 meta
->tables
[i
].rows
= assembly
->tables
[i
].rows
;
3760 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3761 if (meta
->tables
[i
].rows
== 0)
3763 valid_mask
|= (guint64
)1 << i
;
3765 meta
->tables
[i
].row_size
= mono_metadata_compute_size (
3766 meta
, i
, &meta
->tables
[i
].size_bitfield
);
3767 heapt_size
+= meta
->tables
[i
].row_size
* meta
->tables
[i
].rows
;
3769 heapt_size
+= 24; /* #~ header size */
3770 heapt_size
+= ntables
* 4;
3771 /* make multiple of 4 */
3774 meta_size
+= heapt_size
;
3775 meta
->raw_metadata
= g_malloc0 (meta_size
);
3776 p
= (unsigned char*)meta
->raw_metadata
;
3777 /* the metadata signature */
3778 *p
++ = 'B'; *p
++ = 'S'; *p
++ = 'J'; *p
++ = 'B';
3779 /* version numbers and 4 bytes reserved */
3780 int16val
= (guint16
*)p
;
3781 *int16val
++ = GUINT16_TO_LE (meta
->md_version_major
);
3782 *int16val
= GUINT16_TO_LE (meta
->md_version_minor
);
3784 /* version string */
3785 int32val
= (guint32
*)p
;
3786 *int32val
= GUINT32_TO_LE ((strlen (meta
->version
) + 3) & (~3)); /* needs to be multiple of 4 */
3788 memcpy (p
, meta
->version
, strlen (meta
->version
));
3789 p
+= GUINT32_FROM_LE (*int32val
);
3790 align_pointer (meta
->raw_metadata
, p
);
3791 int16val
= (guint16
*)p
;
3792 *int16val
++ = GUINT16_TO_LE (0); /* flags must be 0 */
3793 *int16val
= GUINT16_TO_LE (5); /* number of streams */
3797 * write the stream info.
3799 table_offset
= (p
- (unsigned char*)meta
->raw_metadata
) + 5 * 8 + 40; /* room needed for stream headers */
3800 table_offset
+= 3; table_offset
&= ~3;
3802 assembly
->tstream
.index
= heapt_size
;
3803 for (i
= 0; i
< 5; ++i
) {
3804 int32val
= (guint32
*)p
;
3805 stream_desc
[i
].stream
->offset
= table_offset
;
3806 *int32val
++ = GUINT32_TO_LE (table_offset
);
3807 *int32val
= GUINT32_TO_LE (stream_desc
[i
].stream
->index
);
3808 table_offset
+= GUINT32_FROM_LE (*int32val
);
3809 table_offset
+= 3; table_offset
&= ~3;
3811 strcpy ((char*)p
, stream_desc
[i
].name
);
3812 p
+= strlen (stream_desc
[i
].name
) + 1;
3813 align_pointer (meta
->raw_metadata
, p
);
3816 * now copy the data, the table stream header and contents goes first.
3818 g_assert ((p
- (unsigned char*)meta
->raw_metadata
) < assembly
->tstream
.offset
);
3819 p
= (guchar
*)meta
->raw_metadata
+ assembly
->tstream
.offset
;
3820 int32val
= (guint32
*)p
;
3821 *int32val
= GUINT32_TO_LE (0); /* reserved */
3824 if (mono_framework_version () > 1) {
3825 *p
++ = 2; /* version */
3828 *p
++ = 1; /* version */
3832 if (meta
->idx_string_wide
)
3834 if (meta
->idx_guid_wide
)
3836 if (meta
->idx_blob_wide
)
3839 *p
++ = 1; /* reserved */
3840 int64val
= (guint64
*)p
;
3841 *int64val
++ = GUINT64_TO_LE (valid_mask
);
3842 *int64val
++ = GUINT64_TO_LE (valid_mask
& sorted_mask
); /* bitvector of sorted tables */
3844 int32val
= (guint32
*)p
;
3845 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3846 if (meta
->tables
[i
].rows
== 0)
3848 *int32val
++ = GUINT32_TO_LE (meta
->tables
[i
].rows
);
3850 p
= (unsigned char*)int32val
;
3852 /* sort the tables that still need sorting */
3853 table
= &assembly
->tables
[MONO_TABLE_CONSTANT
];
3855 qsort (table
->values
+ MONO_CONSTANT_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CONSTANT_SIZE
, compare_constants
);
3856 table
= &assembly
->tables
[MONO_TABLE_METHODSEMANTICS
];
3858 qsort (table
->values
+ MONO_METHOD_SEMA_SIZE
, table
->rows
, sizeof (guint32
) * MONO_METHOD_SEMA_SIZE
, compare_semantics
);
3859 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
3861 qsort (table
->values
+ MONO_CUSTOM_ATTR_SIZE
, table
->rows
, sizeof (guint32
) * MONO_CUSTOM_ATTR_SIZE
, compare_custom_attrs
);
3862 table
= &assembly
->tables
[MONO_TABLE_FIELDMARSHAL
];
3864 qsort (table
->values
+ MONO_FIELD_MARSHAL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_FIELD_MARSHAL_SIZE
, compare_field_marshal
);
3865 table
= &assembly
->tables
[MONO_TABLE_NESTEDCLASS
];
3867 qsort (table
->values
+ MONO_NESTED_CLASS_SIZE
, table
->rows
, sizeof (guint32
) * MONO_NESTED_CLASS_SIZE
, compare_nested
);
3868 /* Section 21.11 DeclSecurity in Partition II doesn't specify this to be sorted by MS implementation requires it */
3869 table
= &assembly
->tables
[MONO_TABLE_DECLSECURITY
];
3871 qsort (table
->values
+ MONO_DECL_SECURITY_SIZE
, table
->rows
, sizeof (guint32
) * MONO_DECL_SECURITY_SIZE
, compare_declsecurity_attrs
);
3872 table
= &assembly
->tables
[MONO_TABLE_INTERFACEIMPL
];
3874 qsort (table
->values
+ MONO_INTERFACEIMPL_SIZE
, table
->rows
, sizeof (guint32
) * MONO_INTERFACEIMPL_SIZE
, compare_interface_impl
);
3876 /* compress the tables */
3877 for (i
= 0; i
< MONO_TABLE_NUM
; i
++){
3880 guint32 bitfield
= meta
->tables
[i
].size_bitfield
;
3881 if (!meta
->tables
[i
].rows
)
3883 if (assembly
->tables
[i
].columns
!= mono_metadata_table_count (bitfield
))
3884 g_error ("col count mismatch in %d: %d %d", i
, assembly
->tables
[i
].columns
, mono_metadata_table_count (bitfield
));
3885 meta
->tables
[i
].base
= (char*)p
;
3886 for (row
= 1; row
<= meta
->tables
[i
].rows
; ++row
) {
3887 values
= assembly
->tables
[i
].values
+ row
* assembly
->tables
[i
].columns
;
3888 for (col
= 0; col
< assembly
->tables
[i
].columns
; ++col
) {
3889 switch (mono_metadata_table_size (bitfield
, col
)) {
3891 *p
++ = values
[col
];
3894 *p
++ = values
[col
] & 0xff;
3895 *p
++ = (values
[col
] >> 8) & 0xff;
3898 *p
++ = values
[col
] & 0xff;
3899 *p
++ = (values
[col
] >> 8) & 0xff;
3900 *p
++ = (values
[col
] >> 16) & 0xff;
3901 *p
++ = (values
[col
] >> 24) & 0xff;
3904 g_assert_not_reached ();
3908 g_assert ((p
- (const unsigned char*)meta
->tables
[i
].base
) == (meta
->tables
[i
].rows
* meta
->tables
[i
].row_size
));
3911 g_assert (assembly
->guid
.offset
+ assembly
->guid
.index
< meta_size
);
3912 memcpy (meta
->raw_metadata
+ assembly
->sheap
.offset
, assembly
->sheap
.data
, assembly
->sheap
.index
);
3913 memcpy (meta
->raw_metadata
+ assembly
->us
.offset
, assembly
->us
.data
, assembly
->us
.index
);
3914 memcpy (meta
->raw_metadata
+ assembly
->blob
.offset
, assembly
->blob
.data
, assembly
->blob
.index
);
3915 memcpy (meta
->raw_metadata
+ assembly
->guid
.offset
, assembly
->guid
.data
, assembly
->guid
.index
);
3917 assembly
->meta_size
= assembly
->guid
.offset
+ assembly
->guid
.index
;
3921 * Some tables in metadata need to be sorted according to some criteria, but
3922 * when methods and fields are first created with reflection, they may be assigned a token
3923 * that doesn't correspond to the final token they will get assigned after the sorting.
3924 * ILGenerator.cs keeps a fixup table that maps the position of tokens in the IL code stream
3925 * with the reflection objects that represent them. Once all the tables are set up, the
3926 * reflection objects will contains the correct table index. fixup_method() will fixup the
3927 * tokens for the method with ILGenerator @ilgen.
3930 fixup_method (MonoReflectionILGen
*ilgen
, gpointer value
, MonoDynamicImage
*assembly
)
3932 guint32 code_idx
= GPOINTER_TO_UINT (value
);
3933 MonoReflectionILTokenInfo
*iltoken
;
3934 MonoReflectionFieldBuilder
*field
;
3935 MonoReflectionCtorBuilder
*ctor
;
3936 MonoReflectionMethodBuilder
*method
;
3937 MonoReflectionTypeBuilder
*tb
;
3938 MonoReflectionArrayMethod
*am
;
3940 unsigned char *target
;
3942 for (i
= 0; i
< ilgen
->num_token_fixups
; ++i
) {
3943 iltoken
= (MonoReflectionILTokenInfo
*)mono_array_addr_with_size (ilgen
->token_fixups
, sizeof (MonoReflectionILTokenInfo
), i
);
3944 target
= (guchar
*)assembly
->code
.data
+ code_idx
+ iltoken
->code_pos
;
3945 switch (target
[3]) {
3946 case MONO_TABLE_FIELD
:
3947 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
3948 field
= (MonoReflectionFieldBuilder
*)iltoken
->member
;
3949 idx
= field
->table_idx
;
3950 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
3951 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
3952 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->field_to_table_idx
, f
));
3954 g_assert_not_reached ();
3957 case MONO_TABLE_METHOD
:
3958 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
3959 method
= (MonoReflectionMethodBuilder
*)iltoken
->member
;
3960 idx
= method
->table_idx
;
3961 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
3962 ctor
= (MonoReflectionCtorBuilder
*)iltoken
->member
;
3963 idx
= ctor
->table_idx
;
3964 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
3965 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod")) {
3966 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
3967 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
3969 g_assert_not_reached ();
3972 case MONO_TABLE_TYPEDEF
:
3973 if (strcmp (iltoken
->member
->vtable
->klass
->name
, "TypeBuilder"))
3974 g_assert_not_reached ();
3975 tb
= (MonoReflectionTypeBuilder
*)iltoken
->member
;
3976 idx
= tb
->table_idx
;
3978 case MONO_TABLE_MEMBERREF
:
3979 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoArrayMethod")) {
3980 am
= (MonoReflectionArrayMethod
*)iltoken
->member
;
3981 idx
= am
->table_idx
;
3982 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoMethod") ||
3983 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoCMethod") ||
3984 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod") ||
3985 !strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericCMethod")) {
3986 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
3987 g_assert (m
->klass
->generic_class
|| m
->klass
->generic_container
);
3989 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldBuilder")) {
3991 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoField")) {
3992 MonoClassField
*f
= ((MonoReflectionField
*)iltoken
->member
)->field
;
3993 g_assert (is_field_on_inst (f
));
3995 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder") ||
3996 !strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorBuilder")) {
3998 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "FieldOnTypeBuilderInst")) {
4000 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodOnTypeBuilderInst")) {
4002 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst")) {
4005 g_assert_not_reached ();
4008 case MONO_TABLE_METHODSPEC
:
4009 if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MonoGenericMethod")) {
4010 MonoMethod
*m
= ((MonoReflectionMethod
*)iltoken
->member
)->method
;
4011 g_assert (mono_method_signature (m
)->generic_param_count
);
4013 } else if (!strcmp (iltoken
->member
->vtable
->klass
->name
, "MethodBuilder")) {
4016 g_assert_not_reached ();
4020 g_error ("got unexpected table 0x%02x in fixup", target
[3]);
4022 target
[0] = idx
& 0xff;
4023 target
[1] = (idx
>> 8) & 0xff;
4024 target
[2] = (idx
>> 16) & 0xff;
4031 * The CUSTOM_ATTRIBUTE table might contain METHODDEF tokens whose final
4032 * value is not known when the table is emitted.
4035 fixup_cattrs (MonoDynamicImage
*assembly
)
4037 MonoDynamicTable
*table
;
4039 guint32 type
, i
, idx
, token
;
4042 table
= &assembly
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
4044 for (i
= 0; i
< table
->rows
; ++i
) {
4045 values
= table
->values
+ ((i
+ 1) * MONO_CUSTOM_ATTR_SIZE
);
4047 type
= values
[MONO_CUSTOM_ATTR_TYPE
];
4048 if ((type
& MONO_CUSTOM_ATTR_TYPE_MASK
) == MONO_CUSTOM_ATTR_TYPE_METHODDEF
) {
4049 idx
= type
>> MONO_CUSTOM_ATTR_TYPE_BITS
;
4050 token
= mono_metadata_make_token (MONO_TABLE_METHOD
, idx
);
4051 ctor
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4054 if (!strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
4055 MonoMethod
*m
= ((MonoReflectionMethod
*)ctor
)->method
;
4056 idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, m
));
4057 values
[MONO_CUSTOM_ATTR_TYPE
] = (idx
<< MONO_CUSTOM_ATTR_TYPE_BITS
) | MONO_CUSTOM_ATTR_TYPE_METHODDEF
;
4064 assembly_add_resource_manifest (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
, guint32 implementation
)
4066 MonoDynamicTable
*table
;
4069 table
= &assembly
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4071 alloc_table (table
, table
->rows
);
4072 values
= table
->values
+ table
->next_idx
* MONO_MANIFEST_SIZE
;
4073 values
[MONO_MANIFEST_OFFSET
] = rsrc
->offset
;
4074 values
[MONO_MANIFEST_FLAGS
] = rsrc
->attrs
;
4075 values
[MONO_MANIFEST_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, rsrc
->name
);
4076 values
[MONO_MANIFEST_IMPLEMENTATION
] = implementation
;
4081 assembly_add_resource (MonoReflectionModuleBuilder
*mb
, MonoDynamicImage
*assembly
, MonoReflectionResource
*rsrc
)
4083 MonoDynamicTable
*table
;
4087 char *b
= blob_size
;
4089 guint32 idx
, offset
;
4091 if (rsrc
->filename
) {
4092 name
= mono_string_to_utf8 (rsrc
->filename
);
4093 sname
= g_path_get_basename (name
);
4095 table
= &assembly
->tables
[MONO_TABLE_FILE
];
4097 alloc_table (table
, table
->rows
);
4098 values
= table
->values
+ table
->next_idx
* MONO_FILE_SIZE
;
4099 values
[MONO_FILE_FLAGS
] = FILE_CONTAINS_NO_METADATA
;
4100 values
[MONO_FILE_NAME
] = string_heap_insert (&assembly
->sheap
, sname
);
4103 mono_sha1_get_digest_from_file (name
, hash
);
4104 mono_metadata_encode_value (20, b
, &b
);
4105 values
[MONO_FILE_HASH_VALUE
] = mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
-blob_size
);
4106 mono_image_add_stream_data (&assembly
->blob
, (char*)hash
, 20);
4108 idx
= table
->next_idx
++;
4110 idx
= MONO_IMPLEMENTATION_FILE
| (idx
<< MONO_IMPLEMENTATION_BITS
);
4116 data
= mono_array_addr (rsrc
->data
, char, 0);
4117 len
= mono_array_length (rsrc
->data
);
4123 sizebuf
[0] = offset
; sizebuf
[1] = offset
>> 8;
4124 sizebuf
[2] = offset
>> 16; sizebuf
[3] = offset
>> 24;
4125 rsrc
->offset
= mono_image_add_stream_data (&assembly
->resources
, sizebuf
, 4);
4126 mono_image_add_stream_data (&assembly
->resources
, data
, len
);
4130 * The entry should be emitted into the MANIFESTRESOURCE table of
4131 * the main module, but that needs to reference the FILE table
4132 * which isn't emitted yet.
4139 assembly_add_resource_manifest (mb
, assembly
, rsrc
, idx
);
4143 set_version_from_string (MonoString
*version
, guint32
*values
)
4145 gchar
*ver
, *p
, *str
;
4148 values
[MONO_ASSEMBLY_MAJOR_VERSION
] = 0;
4149 values
[MONO_ASSEMBLY_MINOR_VERSION
] = 0;
4150 values
[MONO_ASSEMBLY_REV_NUMBER
] = 0;
4151 values
[MONO_ASSEMBLY_BUILD_NUMBER
] = 0;
4154 ver
= str
= mono_string_to_utf8 (version
);
4155 for (i
= 0; i
< 4; ++i
) {
4156 values
[MONO_ASSEMBLY_MAJOR_VERSION
+ i
] = strtol (ver
, &p
, 10);
4162 /* handle Revision and Build */
4172 load_public_key (MonoArray
*pkey
, MonoDynamicImage
*assembly
) {
4176 char *b
= blob_size
;
4181 len
= mono_array_length (pkey
);
4182 mono_metadata_encode_value (len
, b
, &b
);
4183 token
= mono_image_add_stream_data (&assembly
->blob
, blob_size
, b
- blob_size
);
4184 mono_image_add_stream_data (&assembly
->blob
, mono_array_addr (pkey
, char, 0), len
);
4186 assembly
->public_key
= g_malloc (len
);
4187 memcpy (assembly
->public_key
, mono_array_addr (pkey
, char, 0), len
);
4188 assembly
->public_key_len
= len
;
4190 /* Special case: check for ECMA key (16 bytes) */
4191 if ((len
== MONO_ECMA_KEY_LENGTH
) && mono_is_ecma_key (mono_array_addr (pkey
, char, 0), len
)) {
4192 /* In this case we must reserve 128 bytes (1024 bits) for the signature */
4193 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
;
4194 } else if (len
>= MONO_PUBLIC_KEY_HEADER_LENGTH
+ MONO_MINIMUM_PUBLIC_KEY_LENGTH
) {
4195 /* minimum key size (in 2.0) is 384 bits */
4196 assembly
->strong_name_size
= len
- MONO_PUBLIC_KEY_HEADER_LENGTH
;
4198 /* FIXME - verifier */
4199 g_warning ("Invalid public key length: %d bits (total: %d)", (int)MONO_PUBLIC_KEY_BIT_SIZE (len
), (int)len
);
4200 assembly
->strong_name_size
= MONO_DEFAULT_PUBLIC_KEY_LENGTH
; /* to be safe */
4202 assembly
->strong_name
= g_malloc0 (assembly
->strong_name_size
);
4208 mono_image_emit_manifest (MonoReflectionModuleBuilder
*moduleb
)
4210 MonoDynamicTable
*table
;
4211 MonoDynamicImage
*assembly
;
4212 MonoReflectionAssemblyBuilder
*assemblyb
;
4216 guint32 module_index
;
4218 assemblyb
= moduleb
->assemblyb
;
4219 assembly
= moduleb
->dynamic_image
;
4220 domain
= mono_object_domain (assemblyb
);
4222 /* Emit ASSEMBLY table */
4223 table
= &assembly
->tables
[MONO_TABLE_ASSEMBLY
];
4224 alloc_table (table
, 1);
4225 values
= table
->values
+ MONO_ASSEMBLY_SIZE
;
4226 values
[MONO_ASSEMBLY_HASH_ALG
] = assemblyb
->algid
? assemblyb
->algid
: ASSEMBLY_HASH_SHA1
;
4227 values
[MONO_ASSEMBLY_NAME
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->name
);
4228 if (assemblyb
->culture
) {
4229 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert_mstring (&assembly
->sheap
, assemblyb
->culture
);
4231 values
[MONO_ASSEMBLY_CULTURE
] = string_heap_insert (&assembly
->sheap
, "");
4233 values
[MONO_ASSEMBLY_PUBLIC_KEY
] = load_public_key (assemblyb
->public_key
, assembly
);
4234 values
[MONO_ASSEMBLY_FLAGS
] = assemblyb
->flags
;
4235 set_version_from_string (assemblyb
->version
, values
);
4237 /* Emit FILE + EXPORTED_TYPE table */
4239 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4241 MonoReflectionModuleBuilder
*file_module
=
4242 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4243 if (file_module
!= moduleb
) {
4244 mono_image_fill_file_table (domain
, (MonoReflectionModule
*)file_module
, assembly
);
4246 if (file_module
->types
) {
4247 for (j
= 0; j
< file_module
->num_types
; ++j
) {
4248 MonoReflectionTypeBuilder
*tb
= mono_array_get (file_module
->types
, MonoReflectionTypeBuilder
*, j
);
4249 mono_image_fill_export_table (domain
, tb
, module_index
, 0, assembly
);
4254 if (assemblyb
->loaded_modules
) {
4255 for (i
= 0; i
< mono_array_length (assemblyb
->loaded_modules
); ++i
) {
4256 MonoReflectionModule
*file_module
=
4257 mono_array_get (assemblyb
->loaded_modules
, MonoReflectionModule
*, i
);
4258 mono_image_fill_file_table (domain
, file_module
, assembly
);
4260 mono_image_fill_export_table_from_module (domain
, file_module
, module_index
, assembly
);
4263 if (assemblyb
->type_forwarders
)
4264 mono_image_fill_export_table_from_type_forwarders (assemblyb
, assembly
);
4266 /* Emit MANIFESTRESOURCE table */
4268 for (i
= 0; i
< mono_array_length (assemblyb
->modules
); ++i
) {
4270 MonoReflectionModuleBuilder
*file_module
=
4271 mono_array_get (assemblyb
->modules
, MonoReflectionModuleBuilder
*, i
);
4272 /* The table for the main module is emitted later */
4273 if (file_module
!= moduleb
) {
4275 if (file_module
->resources
) {
4276 int len
= mono_array_length (file_module
->resources
);
4277 for (j
= 0; j
< len
; ++j
) {
4278 MonoReflectionResource
* res
= (MonoReflectionResource
*)mono_array_addr (file_module
->resources
, MonoReflectionResource
, j
);
4279 assembly_add_resource_manifest (file_module
, assembly
, res
, MONO_IMPLEMENTATION_FILE
| (module_index
<< MONO_IMPLEMENTATION_BITS
));
4286 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4289 * mono_image_build_metadata() will fill the info in all the needed metadata tables
4290 * for the modulebuilder @moduleb.
4291 * At the end of the process, method and field tokens are fixed up and the
4292 * on-disk compressed metadata representation is created.
4295 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4297 MonoDynamicTable
*table
;
4298 MonoDynamicImage
*assembly
;
4299 MonoReflectionAssemblyBuilder
*assemblyb
;
4305 assemblyb
= moduleb
->assemblyb
;
4306 assembly
= moduleb
->dynamic_image
;
4307 domain
= mono_object_domain (assemblyb
);
4309 if (assembly
->text_rva
)
4312 assembly
->text_rva
= START_TEXT_RVA
;
4314 if (moduleb
->is_main
) {
4315 mono_image_emit_manifest (moduleb
);
4318 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4319 table
->rows
= 1; /* .<Module> */
4321 alloc_table (table
, table
->rows
);
4323 * Set the first entry.
4325 values
= table
->values
+ table
->columns
;
4326 values
[MONO_TYPEDEF_FLAGS
] = 0;
4327 values
[MONO_TYPEDEF_NAME
] = string_heap_insert (&assembly
->sheap
, "<Module>") ;
4328 values
[MONO_TYPEDEF_NAMESPACE
] = string_heap_insert (&assembly
->sheap
, "") ;
4329 values
[MONO_TYPEDEF_EXTENDS
] = 0;
4330 values
[MONO_TYPEDEF_FIELD_LIST
] = 1;
4331 values
[MONO_TYPEDEF_METHOD_LIST
] = 1;
4334 * handle global methods
4335 * FIXME: test what to do when global methods are defined in multiple modules.
4337 if (moduleb
->global_methods
) {
4338 table
= &assembly
->tables
[MONO_TABLE_METHOD
];
4339 table
->rows
+= mono_array_length (moduleb
->global_methods
);
4340 alloc_table (table
, table
->rows
);
4341 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
)
4342 mono_image_get_method_info (
4343 mono_array_get (moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
), assembly
);
4345 if (moduleb
->global_fields
) {
4346 table
= &assembly
->tables
[MONO_TABLE_FIELD
];
4347 table
->rows
+= mono_array_length (moduleb
->global_fields
);
4348 alloc_table (table
, table
->rows
);
4349 for (i
= 0; i
< mono_array_length (moduleb
->global_fields
); ++i
)
4350 mono_image_get_field_info (
4351 mono_array_get (moduleb
->global_fields
, MonoReflectionFieldBuilder
*, i
), assembly
);
4354 table
= &assembly
->tables
[MONO_TABLE_MODULE
];
4355 alloc_table (table
, 1);
4356 mono_image_fill_module_table (domain
, moduleb
, assembly
);
4358 /* Collect all types into a list sorted by their table_idx */
4359 types
= g_ptr_array_new ();
4362 for (i
= 0; i
< moduleb
->num_types
; ++i
) {
4363 MonoReflectionTypeBuilder
*type
= mono_array_get (moduleb
->types
, MonoReflectionTypeBuilder
*, i
);
4364 collect_types (types
, type
);
4367 g_ptr_array_sort (types
, (GCompareFunc
)compare_types_by_table_idx
);
4368 table
= &assembly
->tables
[MONO_TABLE_TYPEDEF
];
4369 table
->rows
+= types
->len
;
4370 alloc_table (table
, table
->rows
);
4373 * Emit type names + namespaces at one place inside the string heap,
4374 * so load_class_names () needs to touch fewer pages.
4376 for (i
= 0; i
< types
->len
; ++i
) {
4377 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4378 string_heap_insert_mstring (&assembly
->sheap
, tb
->nspace
);
4380 for (i
= 0; i
< types
->len
; ++i
) {
4381 MonoReflectionTypeBuilder
*tb
= g_ptr_array_index (types
, i
);
4382 string_heap_insert_mstring (&assembly
->sheap
, tb
->name
);
4385 for (i
= 0; i
< types
->len
; ++i
) {
4386 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4387 mono_image_get_type_info (domain
, type
, assembly
);
4391 * table->rows is already set above and in mono_image_fill_module_table.
4393 /* add all the custom attributes at the end, once all the indexes are stable */
4394 mono_image_add_cattrs (assembly
, 1, MONO_CUSTOM_ATTR_ASSEMBLY
, assemblyb
->cattrs
);
4396 /* CAS assembly permissions */
4397 if (assemblyb
->permissions_minimum
)
4398 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_minimum
);
4399 if (assemblyb
->permissions_optional
)
4400 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_optional
);
4401 if (assemblyb
->permissions_refused
)
4402 mono_image_add_decl_security (assembly
, mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1), assemblyb
->permissions_refused
);
4404 module_add_cattrs (assembly
, moduleb
);
4407 mono_g_hash_table_foreach (assembly
->token_fixups
, (GHFunc
)fixup_method
, assembly
);
4409 /* Create the MethodImpl table. We do this after emitting all methods so we already know
4410 * the final tokens and don't need another fixup pass. */
4412 if (moduleb
->global_methods
) {
4413 for (i
= 0; i
< mono_array_length (moduleb
->global_methods
); ++i
) {
4414 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4415 moduleb
->global_methods
, MonoReflectionMethodBuilder
*, i
);
4416 mono_image_add_methodimpl (assembly
, mb
);
4420 for (i
= 0; i
< types
->len
; ++i
) {
4421 MonoReflectionTypeBuilder
*type
= g_ptr_array_index (types
, i
);
4422 if (type
->methods
) {
4423 for (j
= 0; j
< type
->num_methods
; ++j
) {
4424 MonoReflectionMethodBuilder
*mb
= mono_array_get (
4425 type
->methods
, MonoReflectionMethodBuilder
*, j
);
4427 mono_image_add_methodimpl (assembly
, mb
);
4432 g_ptr_array_free (types
, TRUE
);
4434 fixup_cattrs (assembly
);
4437 #else /* DISABLE_REFLECTION_EMIT_SAVE */
4440 mono_image_build_metadata (MonoReflectionModuleBuilder
*moduleb
)
4442 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit_save, so saving of dynamic assemblies is not supported.");
4445 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
4447 #ifndef DISABLE_REFLECTION_EMIT
4450 * mono_image_insert_string:
4451 * @module: module builder object
4454 * Insert @str into the user string stream of @module.
4457 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
4459 MonoDynamicImage
*assembly
;
4464 MONO_ARCH_SAVE_REGS
;
4466 if (!module
->dynamic_image
)
4467 mono_image_module_basic_init (module
);
4469 assembly
= module
->dynamic_image
;
4471 if (assembly
->save
) {
4472 mono_metadata_encode_value (1 | (str
->length
* 2), b
, &b
);
4473 idx
= mono_image_add_stream_data (&assembly
->us
, buf
, b
-buf
);
4474 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
4476 char *swapped
= g_malloc (2 * mono_string_length (str
));
4477 const char *p
= (const char*)mono_string_chars (str
);
4479 swap_with_size (swapped
, p
, 2, mono_string_length (str
));
4480 mono_image_add_stream_data (&assembly
->us
, swapped
, str
->length
* 2);
4484 mono_image_add_stream_data (&assembly
->us
, (const char*)mono_string_chars (str
), str
->length
* 2);
4486 mono_image_add_stream_data (&assembly
->us
, "", 1);
4488 idx
= assembly
->us
.index
++;
4491 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (MONO_TOKEN_STRING
| idx
), str
);
4493 return MONO_TOKEN_STRING
| idx
;
4497 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
4502 klass
= obj
->vtable
->klass
;
4503 if (strcmp (klass
->name
, "MonoMethod") == 0) {
4504 MonoMethod
*method
= ((MonoReflectionMethod
*)obj
)->method
;
4505 MonoMethodSignature
*sig
, *old
;
4506 guint32 sig_token
, parent
;
4509 g_assert (opt_param_types
&& (mono_method_signature (method
)->sentinelpos
>= 0));
4511 nargs
= mono_array_length (opt_param_types
);
4512 old
= mono_method_signature (method
);
4513 sig
= mono_metadata_signature_alloc ( &assembly
->image
, old
->param_count
+ nargs
);
4515 sig
->hasthis
= old
->hasthis
;
4516 sig
->explicit_this
= old
->explicit_this
;
4517 sig
->call_convention
= old
->call_convention
;
4518 sig
->generic_param_count
= old
->generic_param_count
;
4519 sig
->param_count
= old
->param_count
+ nargs
;
4520 sig
->sentinelpos
= old
->param_count
;
4521 sig
->ret
= old
->ret
;
4523 for (i
= 0; i
< old
->param_count
; i
++)
4524 sig
->params
[i
] = old
->params
[i
];
4526 for (i
= 0; i
< nargs
; i
++) {
4527 MonoReflectionType
*rt
= mono_array_get (opt_param_types
, MonoReflectionType
*, i
);
4528 sig
->params
[old
->param_count
+ i
] = rt
->type
;
4531 parent
= mono_image_typedef_or_ref (assembly
, &method
->klass
->byval_arg
);
4532 g_assert ((parent
& MONO_TYPEDEFORREF_MASK
) == MONO_MEMBERREF_PARENT_TYPEREF
);
4533 parent
>>= MONO_TYPEDEFORREF_BITS
;
4535 parent
<<= MONO_MEMBERREF_PARENT_BITS
;
4536 parent
|= MONO_MEMBERREF_PARENT_TYPEREF
;
4538 sig_token
= method_encode_signature (assembly
, sig
);
4539 token
= mono_image_get_varargs_method_token (assembly
, parent
, method
->name
, sig_token
);
4540 } else if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4541 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4542 ReflectionMethodBuilder rmb
;
4543 guint32 parent
, sig
;
4546 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
4547 rmb
.opt_types
= opt_param_types
;
4549 sig
= method_builder_encode_signature (assembly
, &rmb
);
4551 parent
= mono_image_create_token (assembly
, obj
, TRUE
, TRUE
);
4552 g_assert (mono_metadata_token_table (parent
) == MONO_TABLE_METHOD
);
4554 parent
= mono_metadata_token_index (parent
) << MONO_MEMBERREF_PARENT_BITS
;
4555 parent
|= MONO_MEMBERREF_PARENT_METHODDEF
;
4557 name
= mono_string_to_utf8 (rmb
.name
);
4558 token
= mono_image_get_varargs_method_token (
4559 assembly
, parent
, name
, sig
);
4562 g_error ("requested method token for %s\n", klass
->name
);
4569 * mono_image_create_token:
4570 * @assembly: a dynamic assembly
4572 * @register_token: Whenever to register the token in the assembly->tokens hash.
4574 * Get a token to insert in the IL code stream for the given MemberInfo.
4575 * The metadata emission routines need to pass FALSE as REGISTER_TOKEN, since by that time,
4576 * the table_idx-es were recomputed, so registering the token would overwrite an existing
4580 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
4581 gboolean create_methodspec
, gboolean register_token
)
4586 klass
= obj
->vtable
->klass
;
4588 /* Check for user defined reflection objects */
4589 /* TypeDelegator is the only corlib type which doesn't look like a MonoReflectionType */
4590 if (klass
->image
!= mono_defaults
.corlib
|| (strcmp (klass
->name
, "TypeDelegator") == 0))
4591 mono_raise_exception (mono_get_exception_not_supported ("User defined subclasses of System.Type are not yet supported")); \
4593 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
4594 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
4595 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4597 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
&& !mb
->generic_params
)
4598 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4600 token
= mono_image_get_methodbuilder_token (assembly
, mb
, create_methodspec
);
4601 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4602 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
4603 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
4604 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
4606 if (tb
->module
->dynamic_image
== assembly
&& !tb
->generic_params
)
4607 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
4609 token
= mono_image_get_ctorbuilder_token (assembly
, mb
);
4610 /*g_print ("got token 0x%08x for %s\n", token, mono_string_to_utf8 (mb->name));*/
4611 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
4612 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
4613 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
4614 if (tb
->generic_params
) {
4615 token
= mono_image_get_generic_field_token (assembly
, fb
);
4617 token
= fb
->table_idx
| MONO_TOKEN_FIELD_DEF
;
4619 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
4620 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
4621 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
4622 } else if (strcmp (klass
->name
, "MonoType") == 0) {
4623 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4624 MonoClass
*mc
= mono_class_from_mono_type (tb
->type
);
4625 token
= mono_metadata_token_from_dor (
4626 mono_image_typedef_or_ref_full (assembly
, tb
->type
, mc
->generic_container
== NULL
));
4627 } else if (strcmp (klass
->name
, "GenericTypeParameterBuilder") == 0) {
4628 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4629 token
= mono_metadata_token_from_dor (
4630 mono_image_typedef_or_ref (assembly
, tb
->type
));
4631 } else if (strcmp (klass
->name
, "MonoGenericClass") == 0) {
4632 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4633 token
= mono_metadata_token_from_dor (
4634 mono_image_typedef_or_ref (assembly
, tb
->type
));
4635 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
4636 strcmp (klass
->name
, "MonoMethod") == 0 ||
4637 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
4638 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
4639 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
4640 if (m
->method
->is_inflated
) {
4641 if (create_methodspec
)
4642 token
= mono_image_get_methodspec_token (assembly
, m
->method
);
4644 token
= mono_image_get_inflated_method_token (assembly
, m
->method
);
4645 } else if ((m
->method
->klass
->image
== &assembly
->image
) &&
4646 !m
->method
->klass
->generic_class
) {
4647 static guint32 method_table_idx
= 0xffffff;
4648 if (m
->method
->klass
->wastypebuilder
) {
4649 /* we use the same token as the one that was assigned
4650 * to the Methodbuilder.
4651 * FIXME: do the equivalent for Fields.
4653 token
= m
->method
->token
;
4656 * Each token should have a unique index, but the indexes are
4657 * assigned by managed code, so we don't know about them. An
4658 * easy solution is to count backwards...
4660 method_table_idx
--;
4661 token
= MONO_TOKEN_METHOD_DEF
| method_table_idx
;
4664 token
= mono_image_get_methodref_token (assembly
, m
->method
, create_methodspec
);
4666 /*g_print ("got token 0x%08x for %s\n", token, m->method->name);*/
4667 } else if (strcmp (klass
->name
, "MonoField") == 0) {
4668 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
4669 if ((f
->field
->parent
->image
== &assembly
->image
) && !is_field_on_inst (f
->field
)) {
4670 static guint32 field_table_idx
= 0xffffff;
4672 token
= MONO_TOKEN_FIELD_DEF
| field_table_idx
;
4674 token
= mono_image_get_fieldref_token (assembly
, f
);
4676 /*g_print ("got token 0x%08x for %s\n", token, f->field->name);*/
4677 } else if (strcmp (klass
->name
, "MonoArrayMethod") == 0) {
4678 MonoReflectionArrayMethod
*m
= (MonoReflectionArrayMethod
*)obj
;
4679 token
= mono_image_get_array_token (assembly
, m
);
4680 } else if (strcmp (klass
->name
, "SignatureHelper") == 0) {
4681 MonoReflectionSigHelper
*s
= (MonoReflectionSigHelper
*)obj
;
4682 token
= MONO_TOKEN_SIGNATURE
| mono_image_get_sighelper_token (assembly
, s
);
4683 } else if (strcmp (klass
->name
, "EnumBuilder") == 0) {
4684 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
4685 token
= mono_metadata_token_from_dor (
4686 mono_image_typedef_or_ref (assembly
, tb
->type
));
4687 } else if (strcmp (klass
->name
, "FieldOnTypeBuilderInst") == 0) {
4688 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
4689 token
= mono_image_get_field_on_inst_token (assembly
, f
);
4690 } else if (strcmp (klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
4691 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
4692 token
= mono_image_get_ctor_on_inst_token (assembly
, c
, create_methodspec
);
4693 } else if (strcmp (klass
->name
, "MethodOnTypeBuilderInst") == 0) {
4694 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
4695 token
= mono_image_get_method_on_inst_token (assembly
, m
, create_methodspec
);
4697 g_error ("requested token for %s\n", klass
->name
);
4701 mono_image_register_token (assembly
, token
, obj
);
4707 * mono_image_register_token:
4709 * Register the TOKEN->OBJ mapping in the mapping table in ASSEMBLY. This is required for
4710 * the Module.ResolveXXXToken () methods to work.
4713 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
4715 MonoObject
*prev
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
4717 /* There could be multiple MethodInfo objects with the same token */
4718 //g_assert (prev == obj);
4720 mono_g_hash_table_insert (assembly
->tokens
, GUINT_TO_POINTER (token
), obj
);
4724 #endif /* DISABLE_REFLECTION_EMIT */
4727 guint32 import_lookup_table
;
4731 guint32 import_address_table_rva
;
4739 static gpointer
register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
);
4741 static MonoDynamicImage
*
4742 create_dynamic_mono_image (MonoDynamicAssembly
*assembly
, char *assembly_name
, char *module_name
)
4744 static const guchar entrycode
[16] = {0xff, 0x25, 0};
4745 MonoDynamicImage
*image
;
4748 const char *version
;
4750 if (!strcmp (mono_get_runtime_info ()->framework_version
, "2.1"))
4751 version
= "v2.0.50727"; /* HACK: SL 2 enforces the .net 2 metadata version */
4753 version
= mono_get_runtime_info ()->runtime_version
;
4756 image
= GC_MALLOC (sizeof (MonoDynamicImage
));
4758 image
= g_new0 (MonoDynamicImage
, 1);
4761 mono_profiler_module_event (&image
->image
, MONO_PROFILE_START_LOAD
);
4763 /*g_print ("created image %p\n", image);*/
4764 /* keep in sync with image.c */
4765 image
->image
.name
= assembly_name
;
4766 image
->image
.assembly_name
= image
->image
.name
; /* they may be different */
4767 image
->image
.module_name
= module_name
;
4768 image
->image
.version
= g_strdup (version
);
4769 image
->image
.md_version_major
= 1;
4770 image
->image
.md_version_minor
= 1;
4771 image
->image
.dynamic
= TRUE
;
4773 image
->image
.references
= g_new0 (MonoAssembly
*, 1);
4774 image
->image
.references
[0] = NULL
;
4776 mono_image_init (&image
->image
);
4778 image
->token_fixups
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_KEY_GC
);
4779 image
->method_to_table_idx
= g_hash_table_new (NULL
, NULL
);
4780 image
->field_to_table_idx
= g_hash_table_new (NULL
, NULL
);
4781 image
->method_aux_hash
= g_hash_table_new (NULL
, NULL
);
4782 image
->handleref
= g_hash_table_new (NULL
, NULL
);
4783 image
->tokens
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
4784 image
->generic_def_objects
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_VALUE_GC
);
4785 image
->methodspec
= mono_g_hash_table_new_type (NULL
, NULL
, MONO_HASH_KEY_GC
);
4786 image
->typespec
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
4787 image
->typeref
= g_hash_table_new ((GHashFunc
)mono_metadata_type_hash
, (GCompareFunc
)mono_metadata_type_equal
);
4788 image
->blob_cache
= g_hash_table_new ((GHashFunc
)mono_blob_entry_hash
, (GCompareFunc
)mono_blob_entry_equal
);
4789 image
->gen_params
= g_ptr_array_new ();
4791 /*g_print ("string heap create for image %p (%s)\n", image, module_name);*/
4792 string_heap_init (&image
->sheap
);
4793 mono_image_add_stream_data (&image
->us
, "", 1);
4794 add_to_blob_cached (image
, (char*) "", 1, NULL
, 0);
4795 /* import tables... */
4796 mono_image_add_stream_data (&image
->code
, (char*)entrycode
, sizeof (entrycode
));
4797 image
->iat_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two IAT entries */
4798 image
->idt_offset
= mono_image_add_stream_zero (&image
->code
, 2 * sizeof (MonoIDT
)); /* two IDT entries */
4799 image
->imp_names_offset
= mono_image_add_stream_zero (&image
->code
, 2); /* flags for name entry */
4800 mono_image_add_stream_data (&image
->code
, "_CorExeMain", 12);
4801 mono_image_add_stream_data (&image
->code
, "mscoree.dll", 12);
4802 image
->ilt_offset
= mono_image_add_stream_zero (&image
->code
, 8); /* two ILT entries */
4803 stream_data_align (&image
->code
);
4805 image
->cli_header_offset
= mono_image_add_stream_zero (&image
->code
, sizeof (MonoCLIHeader
));
4807 for (i
=0; i
< MONO_TABLE_NUM
; ++i
) {
4808 image
->tables
[i
].next_idx
= 1;
4809 image
->tables
[i
].columns
= table_sizes
[i
];
4812 image
->image
.assembly
= (MonoAssembly
*)assembly
;
4813 image
->run
= assembly
->run
;
4814 image
->save
= assembly
->save
;
4815 image
->pe_kind
= 0x1; /* ILOnly */
4816 image
->machine
= 0x14c; /* I386 */
4818 mono_profiler_module_loaded (&image
->image
, MONO_PROFILE_OK
);
4824 free_blob_cache_entry (gpointer key
, gpointer val
, gpointer user_data
)
4830 mono_dynamic_image_free (MonoDynamicImage
*image
)
4832 MonoDynamicImage
*di
= image
;
4837 mono_g_hash_table_destroy (di
->methodspec
);
4839 g_hash_table_destroy (di
->typespec
);
4841 g_hash_table_destroy (di
->typeref
);
4843 g_hash_table_destroy (di
->handleref
);
4845 mono_g_hash_table_destroy (di
->tokens
);
4846 if (di
->generic_def_objects
)
4847 mono_g_hash_table_destroy (di
->generic_def_objects
);
4848 if (di
->blob_cache
) {
4849 g_hash_table_foreach (di
->blob_cache
, free_blob_cache_entry
, NULL
);
4850 g_hash_table_destroy (di
->blob_cache
);
4852 if (di
->standalonesig_cache
)
4853 g_hash_table_destroy (di
->standalonesig_cache
);
4854 for (list
= di
->array_methods
; list
; list
= list
->next
) {
4855 ArrayMethod
*am
= (ArrayMethod
*)list
->data
;
4860 g_list_free (di
->array_methods
);
4861 if (di
->gen_params
) {
4862 for (i
= 0; i
< di
->gen_params
->len
; i
++) {
4863 GenericParamTableEntry
*entry
= g_ptr_array_index (di
->gen_params
, i
);
4864 if (entry
->gparam
->type
.type
) {
4865 MonoGenericParam
*param
= entry
->gparam
->type
.type
->data
.generic_param
;
4866 g_free ((char*)param
->name
);
4871 g_ptr_array_free (di
->gen_params
, TRUE
);
4873 if (di
->token_fixups
)
4874 mono_g_hash_table_destroy (di
->token_fixups
);
4875 if (di
->method_to_table_idx
)
4876 g_hash_table_destroy (di
->method_to_table_idx
);
4877 if (di
->field_to_table_idx
)
4878 g_hash_table_destroy (di
->field_to_table_idx
);
4879 if (di
->method_aux_hash
)
4880 g_hash_table_destroy (di
->method_aux_hash
);
4881 g_free (di
->strong_name
);
4882 g_free (di
->win32_res
);
4884 g_free (di
->public_key
);
4886 /*g_print ("string heap destroy for image %p\n", di);*/
4887 mono_dynamic_stream_reset (&di
->sheap
);
4888 mono_dynamic_stream_reset (&di
->code
);
4889 mono_dynamic_stream_reset (&di
->resources
);
4890 mono_dynamic_stream_reset (&di
->us
);
4891 mono_dynamic_stream_reset (&di
->blob
);
4892 mono_dynamic_stream_reset (&di
->tstream
);
4893 mono_dynamic_stream_reset (&di
->guid
);
4894 for (i
= 0; i
< MONO_TABLE_NUM
; ++i
) {
4895 g_free (di
->tables
[i
].values
);
4899 #ifndef DISABLE_REFLECTION_EMIT
4902 * mono_image_basic_init:
4903 * @assembly: an assembly builder object
4905 * Create the MonoImage that represents the assembly builder and setup some
4906 * of the helper hash table and the basic metadata streams.
4909 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
4911 MonoDynamicAssembly
*assembly
;
4912 MonoDynamicImage
*image
;
4913 MonoDomain
*domain
= mono_object_domain (assemblyb
);
4915 MONO_ARCH_SAVE_REGS
;
4917 if (assemblyb
->dynamic_assembly
)
4921 assembly
= assemblyb
->dynamic_assembly
= GC_MALLOC (sizeof (MonoDynamicAssembly
));
4923 assembly
= assemblyb
->dynamic_assembly
= g_new0 (MonoDynamicAssembly
, 1);
4926 mono_profiler_assembly_event (&assembly
->assembly
, MONO_PROFILE_START_LOAD
);
4928 assembly
->assembly
.ref_count
= 1;
4929 assembly
->assembly
.dynamic
= TRUE
;
4930 assembly
->assembly
.corlib_internal
= assemblyb
->corlib_internal
;
4931 assemblyb
->assembly
.assembly
= (MonoAssembly
*)assembly
;
4932 assembly
->assembly
.basedir
= mono_string_to_utf8 (assemblyb
->dir
);
4933 if (assemblyb
->culture
)
4934 assembly
->assembly
.aname
.culture
= mono_string_to_utf8 (assemblyb
->culture
);
4936 assembly
->assembly
.aname
.culture
= g_strdup ("");
4938 if (assemblyb
->version
) {
4939 char *vstr
= mono_string_to_utf8 (assemblyb
->version
);
4940 char **version
= g_strsplit (vstr
, ".", 4);
4941 char **parts
= version
;
4942 assembly
->assembly
.aname
.major
= atoi (*parts
++);
4943 assembly
->assembly
.aname
.minor
= atoi (*parts
++);
4944 assembly
->assembly
.aname
.build
= *parts
!= NULL
? atoi (*parts
++) : 0;
4945 assembly
->assembly
.aname
.revision
= *parts
!= NULL
? atoi (*parts
) : 0;
4947 g_strfreev (version
);
4950 assembly
->assembly
.aname
.major
= 0;
4951 assembly
->assembly
.aname
.minor
= 0;
4952 assembly
->assembly
.aname
.build
= 0;
4953 assembly
->assembly
.aname
.revision
= 0;
4956 assembly
->run
= assemblyb
->access
!= 2;
4957 assembly
->save
= assemblyb
->access
!= 1;
4959 image
= create_dynamic_mono_image (assembly
, mono_string_to_utf8 (assemblyb
->name
), g_strdup ("RefEmit_YouForgotToDefineAModule"));
4960 image
->initial_image
= TRUE
;
4961 assembly
->assembly
.aname
.name
= image
->image
.name
;
4962 assembly
->assembly
.image
= &image
->image
;
4964 mono_domain_assemblies_lock (domain
);
4965 domain
->domain_assemblies
= g_slist_prepend (domain
->domain_assemblies
, assembly
);
4966 mono_domain_assemblies_unlock (domain
);
4968 register_assembly (mono_object_domain (assemblyb
), &assemblyb
->assembly
, &assembly
->assembly
);
4970 mono_profiler_assembly_loaded (&assembly
->assembly
, MONO_PROFILE_OK
);
4972 mono_assembly_invoke_load_hook ((MonoAssembly
*)assembly
);
4975 #endif /* DISABLE_REFLECTION_EMIT */
4977 #ifndef DISABLE_REFLECTION_EMIT_SAVE
4980 calc_section_size (MonoDynamicImage
*assembly
)
4984 /* alignment constraints */
4985 mono_image_add_stream_zero (&assembly
->code
, 4 - (assembly
->code
.index
% 4));
4986 g_assert ((assembly
->code
.index
% 4) == 0);
4987 assembly
->meta_size
+= 3;
4988 assembly
->meta_size
&= ~3;
4989 mono_image_add_stream_zero (&assembly
->resources
, 4 - (assembly
->resources
.index
% 4));
4990 g_assert ((assembly
->resources
.index
% 4) == 0);
4992 assembly
->sections
[MONO_SECTION_TEXT
].size
= assembly
->meta_size
+ assembly
->code
.index
+ assembly
->resources
.index
+ assembly
->strong_name_size
;
4993 assembly
->sections
[MONO_SECTION_TEXT
].attrs
= SECT_FLAGS_HAS_CODE
| SECT_FLAGS_MEM_EXECUTE
| SECT_FLAGS_MEM_READ
;
4996 if (assembly
->win32_res
) {
4997 guint32 res_size
= (assembly
->win32_res_size
+ 3) & ~3;
4999 assembly
->sections
[MONO_SECTION_RSRC
].size
= res_size
;
5000 assembly
->sections
[MONO_SECTION_RSRC
].attrs
= SECT_FLAGS_HAS_INITIALIZED_DATA
| SECT_FLAGS_MEM_READ
;
5004 assembly
->sections
[MONO_SECTION_RELOC
].size
= 12;
5005 assembly
->sections
[MONO_SECTION_RELOC
].attrs
= SECT_FLAGS_MEM_READ
| SECT_FLAGS_MEM_DISCARDABLE
| SECT_FLAGS_HAS_INITIALIZED_DATA
;
5015 MonoReflectionWin32Resource
*win32_res
; /* Only for leaf nodes */
5019 resource_tree_compare_by_id (gconstpointer a
, gconstpointer b
)
5021 ResTreeNode
*t1
= (ResTreeNode
*)a
;
5022 ResTreeNode
*t2
= (ResTreeNode
*)b
;
5024 return t1
->id
- t2
->id
;
5028 * resource_tree_create:
5030 * Organize the resources into a resource tree.
5032 static ResTreeNode
*
5033 resource_tree_create (MonoArray
*win32_resources
)
5035 ResTreeNode
*tree
, *res_node
, *type_node
, *lang_node
;
5039 tree
= g_new0 (ResTreeNode
, 1);
5041 for (i
= 0; i
< mono_array_length (win32_resources
); ++i
) {
5042 MonoReflectionWin32Resource
*win32_res
=
5043 (MonoReflectionWin32Resource
*)mono_array_addr (win32_resources
, MonoReflectionWin32Resource
, i
);
5047 /* FIXME: BUG: this stores managed references in unmanaged memory */
5048 lang_node
= g_new0 (ResTreeNode
, 1);
5049 lang_node
->id
= win32_res
->lang_id
;
5050 lang_node
->win32_res
= win32_res
;
5052 /* Create type node if neccesary */
5054 for (l
= tree
->children
; l
; l
= l
->next
)
5055 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_type
) {
5056 type_node
= (ResTreeNode
*)l
->data
;
5061 type_node
= g_new0 (ResTreeNode
, 1);
5062 type_node
->id
= win32_res
->res_type
;
5065 * The resource types have to be sorted otherwise
5066 * Windows Explorer can't display the version information.
5068 tree
->children
= g_slist_insert_sorted (tree
->children
,
5069 type_node
, resource_tree_compare_by_id
);
5072 /* Create res node if neccesary */
5074 for (l
= type_node
->children
; l
; l
= l
->next
)
5075 if (((ResTreeNode
*)(l
->data
))->id
== win32_res
->res_id
) {
5076 res_node
= (ResTreeNode
*)l
->data
;
5081 res_node
= g_new0 (ResTreeNode
, 1);
5082 res_node
->id
= win32_res
->res_id
;
5083 type_node
->children
= g_slist_append (type_node
->children
, res_node
);
5086 res_node
->children
= g_slist_append (res_node
->children
, lang_node
);
5093 * resource_tree_encode:
5095 * Encode the resource tree into the format used in the PE file.
5098 resource_tree_encode (ResTreeNode
*node
, char *begin
, char *p
, char **endbuf
)
5101 MonoPEResourceDir dir
;
5102 MonoPEResourceDirEntry dir_entry
;
5103 MonoPEResourceDataEntry data_entry
;
5105 guint32 res_id_entries
;
5108 * For the format of the resource directory, see the article
5109 * "An In-Depth Look into the Win32 Portable Executable File Format" by
5113 memset (&dir
, 0, sizeof (dir
));
5114 memset (&dir_entry
, 0, sizeof (dir_entry
));
5115 memset (&data_entry
, 0, sizeof (data_entry
));
5117 g_assert (sizeof (dir
) == 16);
5118 g_assert (sizeof (dir_entry
) == 8);
5119 g_assert (sizeof (data_entry
) == 16);
5121 node
->offset
= p
- begin
;
5123 /* IMAGE_RESOURCE_DIRECTORY */
5124 res_id_entries
= g_slist_length (node
->children
);
5125 dir
.res_id_entries
= GUINT16_TO_LE (res_id_entries
);
5127 memcpy (p
, &dir
, sizeof (dir
));
5130 /* Reserve space for entries */
5132 p
+= sizeof (dir_entry
) * res_id_entries
;
5134 /* Write children */
5135 for (l
= node
->children
; l
; l
= l
->next
) {
5136 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5138 if (child
->win32_res
) {
5141 child
->offset
= p
- begin
;
5143 /* IMAGE_RESOURCE_DATA_ENTRY */
5144 data_entry
.rde_data_offset
= GUINT32_TO_LE (p
- begin
+ sizeof (data_entry
));
5145 size
= mono_array_length (child
->win32_res
->res_data
);
5146 data_entry
.rde_size
= GUINT32_TO_LE (size
);
5148 memcpy (p
, &data_entry
, sizeof (data_entry
));
5149 p
+= sizeof (data_entry
);
5151 memcpy (p
, mono_array_addr (child
->win32_res
->res_data
, char, 0), size
);
5154 resource_tree_encode (child
, begin
, p
, &p
);
5158 /* IMAGE_RESOURCE_ENTRY */
5159 for (l
= node
->children
; l
; l
= l
->next
) {
5160 ResTreeNode
*child
= (ResTreeNode
*)l
->data
;
5162 MONO_PE_RES_DIR_ENTRY_SET_NAME (dir_entry
, FALSE
, child
->id
);
5163 MONO_PE_RES_DIR_ENTRY_SET_DIR (dir_entry
, !child
->win32_res
, child
->offset
);
5165 memcpy (entries
, &dir_entry
, sizeof (dir_entry
));
5166 entries
+= sizeof (dir_entry
);
5173 resource_tree_free (ResTreeNode
* node
)
5176 for (list
= node
->children
; list
; list
= list
->next
)
5177 resource_tree_free ((ResTreeNode
*)list
->data
);
5178 g_slist_free(node
->children
);
5183 assembly_add_win32_resources (MonoDynamicImage
*assembly
, MonoReflectionAssemblyBuilder
*assemblyb
)
5188 MonoReflectionWin32Resource
*win32_res
;
5191 if (!assemblyb
->win32_resources
)
5195 * Resources are stored in a three level tree inside the PE file.
5196 * - level one contains a node for each type of resource
5197 * - level two contains a node for each resource
5198 * - level three contains a node for each instance of a resource for a
5199 * specific language.
5202 tree
= resource_tree_create (assemblyb
->win32_resources
);
5204 /* Estimate the size of the encoded tree */
5206 for (i
= 0; i
< mono_array_length (assemblyb
->win32_resources
); ++i
) {
5207 win32_res
= (MonoReflectionWin32Resource
*)mono_array_addr (assemblyb
->win32_resources
, MonoReflectionWin32Resource
, i
);
5208 size
+= mono_array_length (win32_res
->res_data
);
5210 /* Directory structure */
5211 size
+= mono_array_length (assemblyb
->win32_resources
) * 256;
5212 p
= buf
= g_malloc (size
);
5214 resource_tree_encode (tree
, p
, p
, &p
);
5216 g_assert (p
- buf
<= size
);
5218 assembly
->win32_res
= g_malloc (p
- buf
);
5219 assembly
->win32_res_size
= p
- buf
;
5220 memcpy (assembly
->win32_res
, buf
, p
- buf
);
5223 resource_tree_free (tree
);
5227 fixup_resource_directory (char *res_section
, char *p
, guint32 rva
)
5229 MonoPEResourceDir
*dir
= (MonoPEResourceDir
*)p
;
5232 p
+= sizeof (MonoPEResourceDir
);
5233 for (i
= 0; i
< GUINT16_FROM_LE (dir
->res_named_entries
) + GUINT16_FROM_LE (dir
->res_id_entries
); ++i
) {
5234 MonoPEResourceDirEntry
*dir_entry
= (MonoPEResourceDirEntry
*)p
;
5235 char *child
= res_section
+ MONO_PE_RES_DIR_ENTRY_DIR_OFFSET (*dir_entry
);
5236 if (MONO_PE_RES_DIR_ENTRY_IS_DIR (*dir_entry
)) {
5237 fixup_resource_directory (res_section
, child
, rva
);
5239 MonoPEResourceDataEntry
*data_entry
= (MonoPEResourceDataEntry
*)child
;
5240 data_entry
->rde_data_offset
= GUINT32_TO_LE (GUINT32_FROM_LE (data_entry
->rde_data_offset
) + rva
);
5243 p
+= sizeof (MonoPEResourceDirEntry
);
5248 checked_write_file (HANDLE f
, gconstpointer buffer
, guint32 numbytes
)
5251 if (!WriteFile (f
, buffer
, numbytes
, &dummy
, NULL
))
5252 g_error ("WriteFile returned %d\n", GetLastError ());
5256 * mono_image_create_pefile:
5257 * @mb: a module builder object
5259 * This function creates the PE-COFF header, the image sections, the CLI header * etc. all the data is written in
5260 * assembly->pefile where it can be easily retrieved later in chunks.
5263 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5265 MonoMSDOSHeader
*msdos
;
5266 MonoDotNetHeader
*header
;
5267 MonoSectionTable
*section
;
5268 MonoCLIHeader
*cli_header
;
5269 guint32 size
, image_size
, virtual_base
, text_offset
;
5270 guint32 header_start
, section_start
, file_offset
, virtual_offset
;
5271 MonoDynamicImage
*assembly
;
5272 MonoReflectionAssemblyBuilder
*assemblyb
;
5273 MonoDynamicStream pefile_stream
= {0};
5274 MonoDynamicStream
*pefile
= &pefile_stream
;
5276 guint32
*rva
, value
;
5278 static const unsigned char msheader
[] = {
5279 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
5280 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
5283 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68,
5284 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f,
5285 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
5286 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
5289 assemblyb
= mb
->assemblyb
;
5291 mono_image_basic_init (assemblyb
);
5292 assembly
= mb
->dynamic_image
;
5294 assembly
->pe_kind
= assemblyb
->pe_kind
;
5295 assembly
->machine
= assemblyb
->machine
;
5296 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->pe_kind
= assemblyb
->pe_kind
;
5297 ((MonoDynamicImage
*)assemblyb
->dynamic_assembly
->assembly
.image
)->machine
= assemblyb
->machine
;
5299 mono_image_build_metadata (mb
);
5301 if (mb
->is_main
&& assemblyb
->resources
) {
5302 int len
= mono_array_length (assemblyb
->resources
);
5303 for (i
= 0; i
< len
; ++i
)
5304 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (assemblyb
->resources
, MonoReflectionResource
, i
));
5307 if (mb
->resources
) {
5308 int len
= mono_array_length (mb
->resources
);
5309 for (i
= 0; i
< len
; ++i
)
5310 assembly_add_resource (mb
, assembly
, (MonoReflectionResource
*)mono_array_addr (mb
->resources
, MonoReflectionResource
, i
));
5313 build_compressed_metadata (assembly
);
5316 assembly_add_win32_resources (assembly
, assemblyb
);
5318 nsections
= calc_section_size (assembly
);
5320 /* The DOS header and stub */
5321 g_assert (sizeof (MonoMSDOSHeader
) == sizeof (msheader
));
5322 mono_image_add_stream_data (pefile
, (char*)msheader
, sizeof (msheader
));
5324 /* the dotnet header */
5325 header_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoDotNetHeader
));
5327 /* the section tables */
5328 section_start
= mono_image_add_stream_zero (pefile
, sizeof (MonoSectionTable
) * nsections
);
5330 file_offset
= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5331 virtual_offset
= VIRT_ALIGN
;
5334 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5335 if (!assembly
->sections
[i
].size
)
5338 file_offset
+= FILE_ALIGN
- 1;
5339 file_offset
&= ~(FILE_ALIGN
- 1);
5340 virtual_offset
+= VIRT_ALIGN
- 1;
5341 virtual_offset
&= ~(VIRT_ALIGN
- 1);
5343 assembly
->sections
[i
].offset
= file_offset
;
5344 assembly
->sections
[i
].rva
= virtual_offset
;
5346 file_offset
+= assembly
->sections
[i
].size
;
5347 virtual_offset
+= assembly
->sections
[i
].size
;
5348 image_size
+= (assembly
->sections
[i
].size
+ VIRT_ALIGN
- 1) & ~(VIRT_ALIGN
- 1);
5351 file_offset
+= FILE_ALIGN
- 1;
5352 file_offset
&= ~(FILE_ALIGN
- 1);
5354 image_size
+= section_start
+ sizeof (MonoSectionTable
) * nsections
;
5356 /* back-patch info */
5357 msdos
= (MonoMSDOSHeader
*)pefile
->data
;
5358 msdos
->pe_offset
= GUINT32_FROM_LE (sizeof (MonoMSDOSHeader
));
5360 header
= (MonoDotNetHeader
*)(pefile
->data
+ header_start
);
5361 header
->pesig
[0] = 'P';
5362 header
->pesig
[1] = 'E';
5364 header
->coff
.coff_machine
= GUINT16_FROM_LE (assemblyb
->machine
);
5365 header
->coff
.coff_sections
= GUINT16_FROM_LE (nsections
);
5366 header
->coff
.coff_time
= GUINT32_FROM_LE (time (NULL
));
5367 header
->coff
.coff_opt_header_size
= GUINT16_FROM_LE (sizeof (MonoDotNetHeader
) - sizeof (MonoCOFFHeader
) - 4);
5368 if (assemblyb
->pekind
== 1) {
5370 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x210e);
5373 header
->coff
.coff_attributes
= GUINT16_FROM_LE (0x010e);
5376 virtual_base
= 0x400000; /* FIXME: 0x10000000 if a DLL */
5378 header
->pe
.pe_magic
= GUINT16_FROM_LE (0x10B);
5379 header
->pe
.pe_major
= 6;
5380 header
->pe
.pe_minor
= 0;
5381 size
= assembly
->sections
[MONO_SECTION_TEXT
].size
;
5382 size
+= FILE_ALIGN
- 1;
5383 size
&= ~(FILE_ALIGN
- 1);
5384 header
->pe
.pe_code_size
= GUINT32_FROM_LE(size
);
5385 size
= assembly
->sections
[MONO_SECTION_RSRC
].size
;
5386 size
+= FILE_ALIGN
- 1;
5387 size
&= ~(FILE_ALIGN
- 1);
5388 header
->pe
.pe_data_size
= GUINT32_FROM_LE(size
);
5389 g_assert (START_TEXT_RVA
== assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5390 header
->pe
.pe_rva_code_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5391 header
->pe
.pe_rva_data_base
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5392 /* pe_rva_entry_point always at the beginning of the text section */
5393 header
->pe
.pe_rva_entry_point
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_TEXT
].rva
);
5395 header
->nt
.pe_image_base
= GUINT32_FROM_LE (virtual_base
);
5396 header
->nt
.pe_section_align
= GUINT32_FROM_LE (VIRT_ALIGN
);
5397 header
->nt
.pe_file_alignment
= GUINT32_FROM_LE (FILE_ALIGN
);
5398 header
->nt
.pe_os_major
= GUINT16_FROM_LE (4);
5399 header
->nt
.pe_os_minor
= GUINT16_FROM_LE (0);
5400 header
->nt
.pe_subsys_major
= GUINT16_FROM_LE (4);
5401 size
= section_start
;
5402 size
+= FILE_ALIGN
- 1;
5403 size
&= ~(FILE_ALIGN
- 1);
5404 header
->nt
.pe_header_size
= GUINT32_FROM_LE (size
);
5406 size
+= VIRT_ALIGN
- 1;
5407 size
&= ~(VIRT_ALIGN
- 1);
5408 header
->nt
.pe_image_size
= GUINT32_FROM_LE (size
);
5411 // Translate the PEFileKind value to the value expected by the Windows loader
5417 // PEFileKinds.Dll == 1
5418 // PEFileKinds.ConsoleApplication == 2
5419 // PEFileKinds.WindowApplication == 3
5422 // IMAGE_SUBSYSTEM_WINDOWS_GUI 2 // Image runs in the Windows GUI subsystem.
5423 // IMAGE_SUBSYSTEM_WINDOWS_CUI 3 // Image runs in the Windows character subsystem.
5425 if (assemblyb
->pekind
== 3)
5430 header
->nt
.pe_subsys_required
= GUINT16_FROM_LE (kind
);
5432 header
->nt
.pe_stack_reserve
= GUINT32_FROM_LE (0x00100000);
5433 header
->nt
.pe_stack_commit
= GUINT32_FROM_LE (0x00001000);
5434 header
->nt
.pe_heap_reserve
= GUINT32_FROM_LE (0x00100000);
5435 header
->nt
.pe_heap_commit
= GUINT32_FROM_LE (0x00001000);
5436 header
->nt
.pe_loader_flags
= GUINT32_FROM_LE (0);
5437 header
->nt
.pe_data_dir_count
= GUINT32_FROM_LE (16);
5439 /* fill data directory entries */
5441 header
->datadir
.pe_resource_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].size
);
5442 header
->datadir
.pe_resource_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RSRC
].rva
);
5444 header
->datadir
.pe_reloc_table
.size
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].size
);
5445 header
->datadir
.pe_reloc_table
.rva
= GUINT32_FROM_LE (assembly
->sections
[MONO_SECTION_RELOC
].rva
);
5447 header
->datadir
.pe_cli_header
.size
= GUINT32_FROM_LE (72);
5448 header
->datadir
.pe_cli_header
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->cli_header_offset
);
5449 header
->datadir
.pe_iat
.size
= GUINT32_FROM_LE (8);
5450 header
->datadir
.pe_iat
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5451 /* patch entrypoint name */
5452 if (assemblyb
->pekind
== 1)
5453 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorDllMain", 12);
5455 memcpy (assembly
->code
.data
+ assembly
->imp_names_offset
+ 2, "_CorExeMain", 12);
5456 /* patch imported function RVA name */
5457 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->iat_offset
);
5458 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
);
5460 /* the import table */
5461 header
->datadir
.pe_import_table
.size
= GUINT32_FROM_LE (79); /* FIXME: magic number? */
5462 header
->datadir
.pe_import_table
.rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->idt_offset
);
5463 /* patch imported dll RVA name and other entries in the dir */
5464 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, name_rva
));
5465 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->imp_names_offset
+ 14); /* 14 is hint+strlen+1 of func name */
5466 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_address_table_rva
));
5467 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->iat_offset
);
5468 rva
= (guint32
*)(assembly
->code
.data
+ assembly
->idt_offset
+ G_STRUCT_OFFSET (MonoIDT
, import_lookup_table
));
5469 *rva
= GUINT32_FROM_LE (assembly
->text_rva
+ assembly
->ilt_offset
);
5471 p
= (guchar
*)(assembly
->code
.data
+ assembly
->ilt_offset
);
5472 value
= (assembly
->text_rva
+ assembly
->imp_names_offset
);
5473 *p
++ = (value
) & 0xff;
5474 *p
++ = (value
>> 8) & (0xff);
5475 *p
++ = (value
>> 16) & (0xff);
5476 *p
++ = (value
>> 24) & (0xff);
5478 /* the CLI header info */
5479 cli_header
= (MonoCLIHeader
*)(assembly
->code
.data
+ assembly
->cli_header_offset
);
5480 cli_header
->ch_size
= GUINT32_FROM_LE (72);
5481 cli_header
->ch_runtime_major
= GUINT16_FROM_LE (2);
5482 if (mono_framework_version () > 1)
5483 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (5);
5485 cli_header
->ch_runtime_minor
= GUINT16_FROM_LE (0);
5486 cli_header
->ch_flags
= GUINT32_FROM_LE (assemblyb
->pe_kind
);
5487 if (assemblyb
->entry_point
) {
5488 guint32 table_idx
= 0;
5489 if (!strcmp (assemblyb
->entry_point
->object
.vtable
->klass
->name
, "MethodBuilder")) {
5490 MonoReflectionMethodBuilder
*methodb
= (MonoReflectionMethodBuilder
*)assemblyb
->entry_point
;
5491 table_idx
= methodb
->table_idx
;
5493 table_idx
= GPOINTER_TO_UINT (g_hash_table_lookup (assembly
->method_to_table_idx
, assemblyb
->entry_point
->method
));
5495 cli_header
->ch_entry_point
= GUINT32_FROM_LE (table_idx
| MONO_TOKEN_METHOD_DEF
);
5497 cli_header
->ch_entry_point
= GUINT32_FROM_LE (0);
5499 /* The embedded managed resources */
5500 text_offset
= assembly
->text_rva
+ assembly
->code
.index
;
5501 cli_header
->ch_resources
.rva
= GUINT32_FROM_LE (text_offset
);
5502 cli_header
->ch_resources
.size
= GUINT32_FROM_LE (assembly
->resources
.index
);
5503 text_offset
+= assembly
->resources
.index
;
5504 cli_header
->ch_metadata
.rva
= GUINT32_FROM_LE (text_offset
);
5505 cli_header
->ch_metadata
.size
= GUINT32_FROM_LE (assembly
->meta_size
);
5506 text_offset
+= assembly
->meta_size
;
5507 if (assembly
->strong_name_size
) {
5508 cli_header
->ch_strong_name
.rva
= GUINT32_FROM_LE (text_offset
);
5509 cli_header
->ch_strong_name
.size
= GUINT32_FROM_LE (assembly
->strong_name_size
);
5510 text_offset
+= assembly
->strong_name_size
;
5513 /* write the section tables and section content */
5514 section
= (MonoSectionTable
*)(pefile
->data
+ section_start
);
5515 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5516 static const char section_names
[][7] = {
5517 ".text", ".rsrc", ".reloc"
5519 if (!assembly
->sections
[i
].size
)
5521 strcpy (section
->st_name
, section_names
[i
]);
5522 /*g_print ("output section %s (%d), size: %d\n", section->st_name, i, assembly->sections [i].size);*/
5523 section
->st_virtual_address
= GUINT32_FROM_LE (assembly
->sections
[i
].rva
);
5524 section
->st_virtual_size
= GUINT32_FROM_LE (assembly
->sections
[i
].size
);
5525 section
->st_raw_data_size
= GUINT32_FROM_LE (GUINT32_TO_LE (section
->st_virtual_size
) + (FILE_ALIGN
- 1));
5526 section
->st_raw_data_size
&= GUINT32_FROM_LE (~(FILE_ALIGN
- 1));
5527 section
->st_raw_data_ptr
= GUINT32_FROM_LE (assembly
->sections
[i
].offset
);
5528 section
->st_flags
= GUINT32_FROM_LE (assembly
->sections
[i
].attrs
);
5532 checked_write_file (file
, pefile
->data
, pefile
->index
);
5534 mono_dynamic_stream_reset (pefile
);
5536 for (i
= 0; i
< MONO_SECTION_MAX
; ++i
) {
5537 if (!assembly
->sections
[i
].size
)
5540 if (SetFilePointer (file
, assembly
->sections
[i
].offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5541 g_error ("SetFilePointer returned %d\n", GetLastError ());
5544 case MONO_SECTION_TEXT
:
5545 /* patch entry point */
5546 p
= (guchar
*)(assembly
->code
.data
+ 2);
5547 value
= (virtual_base
+ assembly
->text_rva
+ assembly
->iat_offset
);
5548 *p
++ = (value
) & 0xff;
5549 *p
++ = (value
>> 8) & 0xff;
5550 *p
++ = (value
>> 16) & 0xff;
5551 *p
++ = (value
>> 24) & 0xff;
5553 checked_write_file (file
, assembly
->code
.data
, assembly
->code
.index
);
5554 checked_write_file (file
, assembly
->resources
.data
, assembly
->resources
.index
);
5555 checked_write_file (file
, assembly
->image
.raw_metadata
, assembly
->meta_size
);
5556 checked_write_file (file
, assembly
->strong_name
, assembly
->strong_name_size
);
5559 g_free (assembly
->image
.raw_metadata
);
5561 case MONO_SECTION_RELOC
: {
5565 guint16 type_and_offset
;
5569 g_assert (sizeof (reloc
) == 12);
5571 reloc
.page_rva
= GUINT32_FROM_LE (assembly
->text_rva
);
5572 reloc
.block_size
= GUINT32_FROM_LE (12);
5575 * the entrypoint is always at the start of the text section
5576 * 3 is IMAGE_REL_BASED_HIGHLOW
5577 * 2 is patch_size_rva - text_rva
5579 reloc
.type_and_offset
= GUINT16_FROM_LE ((3 << 12) + (2));
5582 checked_write_file (file
, &reloc
, sizeof (reloc
));
5586 case MONO_SECTION_RSRC
:
5587 if (assembly
->win32_res
) {
5589 /* Fixup the offsets in the IMAGE_RESOURCE_DATA_ENTRY structures */
5590 fixup_resource_directory (assembly
->win32_res
, assembly
->win32_res
, assembly
->sections
[i
].rva
);
5591 checked_write_file (file
, assembly
->win32_res
, assembly
->win32_res_size
);
5595 g_assert_not_reached ();
5599 /* check that the file is properly padded */
5600 if (SetFilePointer (file
, file_offset
, NULL
, FILE_BEGIN
) == INVALID_SET_FILE_POINTER
)
5601 g_error ("SetFilePointer returned %d\n", GetLastError ());
5602 if (! SetEndOfFile (file
))
5603 g_error ("SetEndOfFile returned %d\n", GetLastError ());
5605 mono_dynamic_stream_reset (&assembly
->code
);
5606 mono_dynamic_stream_reset (&assembly
->us
);
5607 mono_dynamic_stream_reset (&assembly
->blob
);
5608 mono_dynamic_stream_reset (&assembly
->guid
);
5609 mono_dynamic_stream_reset (&assembly
->sheap
);
5611 g_hash_table_foreach (assembly
->blob_cache
, (GHFunc
)g_free
, NULL
);
5612 g_hash_table_destroy (assembly
->blob_cache
);
5613 assembly
->blob_cache
= NULL
;
5616 #else /* DISABLE_REFLECTION_EMIT_SAVE */
5619 mono_image_create_pefile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
5621 g_assert_not_reached ();
5624 #endif /* DISABLE_REFLECTION_EMIT_SAVE */
5626 #ifndef DISABLE_REFLECTION_EMIT
5628 MonoReflectionModule
*
5629 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
5633 MonoImageOpenStatus status
;
5634 MonoDynamicAssembly
*assembly
;
5635 guint32 module_count
;
5636 MonoImage
**new_modules
;
5637 gboolean
*new_modules_loaded
;
5639 name
= mono_string_to_utf8 (fileName
);
5641 image
= mono_image_open (name
, &status
);
5644 if (status
== MONO_IMAGE_ERROR_ERRNO
)
5645 exc
= mono_get_exception_file_not_found (fileName
);
5647 exc
= mono_get_exception_bad_image_format (name
);
5649 mono_raise_exception (exc
);
5654 assembly
= ab
->dynamic_assembly
;
5655 image
->assembly
= (MonoAssembly
*)assembly
;
5657 module_count
= image
->assembly
->image
->module_count
;
5658 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5659 new_modules_loaded
= g_new0 (gboolean
, module_count
+ 1);
5661 if (image
->assembly
->image
->modules
)
5662 memcpy (new_modules
, image
->assembly
->image
->modules
, module_count
* sizeof (MonoImage
*));
5663 if (image
->assembly
->image
->modules_loaded
)
5664 memcpy (new_modules_loaded
, image
->assembly
->image
->modules_loaded
, module_count
* sizeof (gboolean
));
5665 new_modules
[module_count
] = image
;
5666 new_modules_loaded
[module_count
] = TRUE
;
5667 mono_image_addref (image
);
5669 g_free (image
->assembly
->image
->modules
);
5670 image
->assembly
->image
->modules
= new_modules
;
5671 image
->assembly
->image
->modules_loaded
= new_modules_loaded
;
5672 image
->assembly
->image
->module_count
++;
5674 mono_assembly_load_references (image
, &status
);
5676 mono_image_close (image
);
5677 mono_raise_exception (mono_get_exception_file_not_found (fileName
));
5680 return mono_module_get_object (mono_domain_get (), image
);
5683 #endif /* DISABLE_REFLECTION_EMIT */
5686 * We need to return always the same object for MethodInfo, FieldInfo etc..
5687 * but we need to consider the reflected type.
5688 * type uses a different hash, since it uses custom hash/equal functions.
5693 MonoClass
*refclass
;
5697 reflected_equal (gconstpointer a
, gconstpointer b
) {
5698 const ReflectedEntry
*ea
= a
;
5699 const ReflectedEntry
*eb
= b
;
5701 return (ea
->item
== eb
->item
) && (ea
->refclass
== eb
->refclass
);
5705 reflected_hash (gconstpointer a
) {
5706 const ReflectedEntry
*ea
= a
;
5707 return mono_aligned_addr_hash (ea
->item
);
5710 #define CHECK_OBJECT(t,p,k) \
5716 mono_domain_lock (domain); \
5717 if (!domain->refobject_hash) \
5718 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5719 if ((_obj = mono_g_hash_table_lookup (domain->refobject_hash, &e))) { \
5720 mono_domain_unlock (domain); \
5723 mono_domain_unlock (domain); \
5726 #ifdef HAVE_BOEHM_GC
5727 /* ReflectedEntry doesn't need to be GC tracked */
5728 #define ALLOC_REFENTRY g_new0 (ReflectedEntry, 1)
5729 #define FREE_REFENTRY(entry) g_free ((entry))
5731 #define ALLOC_REFENTRY mono_mempool_alloc (domain->mp, sizeof (ReflectedEntry))
5733 #define FREE_REFENTRY(entry)
5736 #define CACHE_OBJECT(t,p,o,k) \
5739 ReflectedEntry pe; \
5741 pe.refclass = (k); \
5742 mono_domain_lock (domain); \
5743 if (!domain->refobject_hash) \
5744 domain->refobject_hash = mono_g_hash_table_new_type (reflected_hash, reflected_equal, MONO_HASH_VALUE_GC); \
5745 _obj = mono_g_hash_table_lookup (domain->refobject_hash, &pe); \
5747 ReflectedEntry *e = ALLOC_REFENTRY; \
5749 e->refclass = (k); \
5750 mono_g_hash_table_insert (domain->refobject_hash, e,o); \
5753 mono_domain_unlock (domain); \
5758 clear_cached_object (MonoDomain
*domain
, gpointer o
, MonoClass
*klass
)
5760 mono_domain_lock (domain
);
5761 if (domain
->refobject_hash
) {
5763 gpointer orig_pe
, orig_value
;
5766 pe
.refclass
= klass
;
5767 if (mono_g_hash_table_lookup_extended (domain
->refobject_hash
, &pe
, &orig_pe
, &orig_value
)) {
5768 mono_g_hash_table_remove (domain
->refobject_hash
, &pe
);
5769 FREE_REFENTRY (orig_pe
);
5772 mono_domain_unlock (domain
);
5776 register_assembly (MonoDomain
*domain
, MonoReflectionAssembly
*res
, MonoAssembly
*assembly
)
5778 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
5782 register_module (MonoDomain
*domain
, MonoReflectionModuleBuilder
*res
, MonoDynamicImage
*module
)
5784 CACHE_OBJECT (MonoReflectionModuleBuilder
*, module
, res
, NULL
);
5787 #ifndef DISABLE_REFLECTION_EMIT
5790 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
5792 MonoDynamicImage
*image
= moduleb
->dynamic_image
;
5793 MonoReflectionAssemblyBuilder
*ab
= moduleb
->assemblyb
;
5796 MonoImage
**new_modules
;
5799 * FIXME: we already created an image in mono_image_basic_init (), but
5800 * we don't know which module it belongs to, since that is only
5801 * determined at assembly save time.
5803 /*image = (MonoDynamicImage*)ab->dynamic_assembly->assembly.image; */
5804 image
= create_dynamic_mono_image (ab
->dynamic_assembly
, mono_string_to_utf8 (ab
->name
), mono_string_to_utf8 (moduleb
->module
.fqname
));
5806 moduleb
->module
.image
= &image
->image
;
5807 moduleb
->dynamic_image
= image
;
5808 register_module (mono_object_domain (moduleb
), moduleb
, image
);
5810 /* register the module with the assembly */
5811 ass
= ab
->dynamic_assembly
->assembly
.image
;
5812 module_count
= ass
->module_count
;
5813 new_modules
= g_new0 (MonoImage
*, module_count
+ 1);
5816 memcpy (new_modules
, ass
->modules
, module_count
* sizeof (MonoImage
*));
5817 new_modules
[module_count
] = &image
->image
;
5818 mono_image_addref (&image
->image
);
5820 g_free (ass
->modules
);
5821 ass
->modules
= new_modules
;
5822 ass
->module_count
++;
5829 * mono_assembly_get_object:
5830 * @domain: an app domain
5831 * @assembly: an assembly
5833 * Return an System.Reflection.Assembly object representing the MonoAssembly @assembly.
5835 MonoReflectionAssembly
*
5836 mono_assembly_get_object (MonoDomain
*domain
, MonoAssembly
*assembly
)
5838 static MonoClass
*System_Reflection_Assembly
;
5839 MonoReflectionAssembly
*res
;
5841 CHECK_OBJECT (MonoReflectionAssembly
*, assembly
, NULL
);
5842 if (!System_Reflection_Assembly
)
5843 System_Reflection_Assembly
= mono_class_from_name (
5844 mono_defaults
.corlib
, "System.Reflection", "Assembly");
5845 res
= (MonoReflectionAssembly
*)mono_object_new (domain
, System_Reflection_Assembly
);
5846 res
->assembly
= assembly
;
5848 CACHE_OBJECT (MonoReflectionAssembly
*, assembly
, res
, NULL
);
5853 MonoReflectionModule
*
5854 mono_module_get_object (MonoDomain
*domain
, MonoImage
*image
)
5856 static MonoClass
*System_Reflection_Module
;
5857 MonoReflectionModule
*res
;
5860 CHECK_OBJECT (MonoReflectionModule
*, image
, NULL
);
5861 if (!System_Reflection_Module
)
5862 System_Reflection_Module
= mono_class_from_name (
5863 mono_defaults
.corlib
, "System.Reflection", "Module");
5864 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
5867 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
5869 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, image
->name
));
5870 basename
= g_path_get_basename (image
->name
);
5871 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, basename
));
5872 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, image
->module_name
));
5876 if (image
->assembly
->image
== image
) {
5877 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULE
, 1);
5881 if (image
->assembly
->image
->modules
) {
5882 for (i
= 0; i
< image
->assembly
->image
->module_count
; i
++) {
5883 if (image
->assembly
->image
->modules
[i
] == image
)
5884 res
->token
= mono_metadata_make_token (MONO_TABLE_MODULEREF
, i
+ 1);
5886 g_assert (res
->token
);
5890 CACHE_OBJECT (MonoReflectionModule
*, image
, res
, NULL
);
5893 MonoReflectionModule
*
5894 mono_module_file_get_object (MonoDomain
*domain
, MonoImage
*image
, int table_index
)
5896 static MonoClass
*System_Reflection_Module
;
5897 MonoReflectionModule
*res
;
5898 MonoTableInfo
*table
;
5899 guint32 cols
[MONO_FILE_SIZE
];
5901 guint32 i
, name_idx
;
5904 if (!System_Reflection_Module
)
5905 System_Reflection_Module
= mono_class_from_name (
5906 mono_defaults
.corlib
, "System.Reflection", "Module");
5907 res
= (MonoReflectionModule
*)mono_object_new (domain
, System_Reflection_Module
);
5909 table
= &image
->tables
[MONO_TABLE_FILE
];
5910 g_assert (table_index
< table
->rows
);
5911 mono_metadata_decode_row (table
, table_index
, cols
, MONO_FILE_SIZE
);
5914 MONO_OBJECT_SETREF (res
, assembly
, (MonoReflectionAssembly
*) mono_assembly_get_object(domain
, image
->assembly
));
5915 name
= mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]);
5917 /* Check whenever the row has a corresponding row in the moduleref table */
5918 table
= &image
->tables
[MONO_TABLE_MODULEREF
];
5919 for (i
= 0; i
< table
->rows
; ++i
) {
5920 name_idx
= mono_metadata_decode_row_col (table
, i
, MONO_MODULEREF_NAME
);
5921 val
= mono_metadata_string_heap (image
, name_idx
);
5922 if (strcmp (val
, name
) == 0)
5923 res
->image
= image
->modules
[i
];
5926 MONO_OBJECT_SETREF (res
, fqname
, mono_string_new (domain
, name
));
5927 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, name
));
5928 MONO_OBJECT_SETREF (res
, scopename
, mono_string_new (domain
, name
));
5929 res
->is_resource
= cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
;
5930 res
->token
= mono_metadata_make_token (MONO_TABLE_FILE
, table_index
+ 1);
5936 mymono_metadata_type_equal (MonoType
*t1
, MonoType
*t2
)
5938 if ((t1
->type
!= t2
->type
) ||
5939 (t1
->byref
!= t2
->byref
))
5943 case MONO_TYPE_VOID
:
5944 case MONO_TYPE_BOOLEAN
:
5945 case MONO_TYPE_CHAR
:
5956 case MONO_TYPE_STRING
:
5959 case MONO_TYPE_OBJECT
:
5960 case MONO_TYPE_TYPEDBYREF
:
5962 case MONO_TYPE_VALUETYPE
:
5963 case MONO_TYPE_CLASS
:
5964 case MONO_TYPE_SZARRAY
:
5965 return t1
->data
.klass
== t2
->data
.klass
;
5967 return mymono_metadata_type_equal (t1
->data
.type
, t2
->data
.type
);
5968 case MONO_TYPE_ARRAY
:
5969 if (t1
->data
.array
->rank
!= t2
->data
.array
->rank
)
5971 return t1
->data
.array
->eklass
== t2
->data
.array
->eklass
;
5972 case MONO_TYPE_GENERICINST
: {
5974 MonoGenericInst
*i1
= t1
->data
.generic_class
->context
.class_inst
;
5975 MonoGenericInst
*i2
= t2
->data
.generic_class
->context
.class_inst
;
5976 if (i1
->type_argc
!= i2
->type_argc
)
5978 if (!mono_metadata_type_equal (&t1
->data
.generic_class
->container_class
->byval_arg
,
5979 &t2
->data
.generic_class
->container_class
->byval_arg
))
5981 /* FIXME: we should probably just compare the instance pointers directly. */
5982 for (i
= 0; i
< i1
->type_argc
; ++i
) {
5983 if (!mono_metadata_type_equal (i1
->type_argv
[i
], i2
->type_argv
[i
]))
5989 case MONO_TYPE_MVAR
:
5990 return t1
->data
.generic_param
== t2
->data
.generic_param
;
5992 g_error ("implement type compare for %0x!", t1
->type
);
6000 mymono_metadata_type_hash (MonoType
*t1
)
6006 hash
|= t1
->byref
<< 6; /* do not collide with t1->type values */
6008 case MONO_TYPE_VALUETYPE
:
6009 case MONO_TYPE_CLASS
:
6010 case MONO_TYPE_SZARRAY
:
6011 /* check if the distribution is good enough */
6012 return ((hash
<< 5) - hash
) ^ g_str_hash (t1
->data
.klass
->name
);
6014 return ((hash
<< 5) - hash
) ^ mymono_metadata_type_hash (t1
->data
.type
);
6015 case MONO_TYPE_GENERICINST
: {
6017 MonoGenericInst
*inst
= t1
->data
.generic_class
->context
.class_inst
;
6018 hash
+= g_str_hash (t1
->data
.generic_class
->container_class
->name
);
6020 for (i
= 0; i
< inst
->type_argc
; ++i
) {
6021 hash
+= mymono_metadata_type_hash (inst
->type_argv
[i
]);
6030 static MonoReflectionGenericClass
*
6031 mono_generic_class_get_object (MonoDomain
*domain
, MonoType
*geninst
)
6033 static MonoClass
*System_Reflection_MonoGenericClass
;
6034 MonoReflectionGenericClass
*res
;
6035 MonoClass
*klass
, *gklass
;
6037 if (!System_Reflection_MonoGenericClass
) {
6038 System_Reflection_MonoGenericClass
= mono_class_from_name (
6039 mono_defaults
.corlib
, "System.Reflection", "MonoGenericClass");
6040 g_assert (System_Reflection_MonoGenericClass
);
6043 klass
= mono_class_from_mono_type (geninst
);
6044 gklass
= klass
->generic_class
->container_class
;
6046 mono_class_init (klass
);
6049 res
= (MonoReflectionGenericClass
*) mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, System_Reflection_MonoGenericClass
), mono_class_instance_size (System_Reflection_MonoGenericClass
));
6051 res
= (MonoReflectionGenericClass
*) mono_object_new (domain
, System_Reflection_MonoGenericClass
);
6054 res
->type
.type
= geninst
;
6055 g_assert (gklass
->reflection_info
);
6056 g_assert (!strcmp (((MonoObject
*)gklass
->reflection_info
)->vtable
->klass
->name
, "TypeBuilder"));
6057 MONO_OBJECT_SETREF (res
, generic_type
, gklass
->reflection_info
);
6063 verify_safe_for_managed_space (MonoType
*type
)
6065 switch (type
->type
) {
6067 case MONO_TYPE_ARRAY
:
6068 return verify_safe_for_managed_space (&type
->data
.array
->eklass
->byval_arg
);
6070 return verify_safe_for_managed_space (type
->data
.type
);
6071 case MONO_TYPE_SZARRAY
:
6072 return verify_safe_for_managed_space (&type
->data
.klass
->byval_arg
);
6073 case MONO_TYPE_GENERICINST
: {
6074 MonoGenericInst
*inst
= type
->data
.generic_class
->inst
;
6078 for (i
= 0; i
< inst
->type_argc
; ++i
)
6079 if (!verify_safe_for_managed_space (inst
->type_argv
[i
]))
6085 case MONO_TYPE_MVAR
:
6092 * mono_type_get_object:
6093 * @domain: an app domain
6096 * Return an System.MonoType object representing the type @type.
6099 mono_type_get_object (MonoDomain
*domain
, MonoType
*type
)
6101 MonoReflectionType
*res
;
6102 MonoClass
*klass
= mono_class_from_mono_type (type
);
6104 /*we must avoid using @type as it might have come
6105 * from a mono_metadata_type_dup and the caller
6106 * expects that is can be freed.
6107 * Using the right type from
6109 type
= klass
->byval_arg
.byref
== type
->byref
? &klass
->byval_arg
: &klass
->this_arg
;
6111 /* void is very common */
6112 if (type
->type
== MONO_TYPE_VOID
&& domain
->typeof_void
)
6113 return (MonoReflectionType
*)domain
->typeof_void
;
6116 * If the vtable of the given class was already created, we can use
6117 * the MonoType from there and avoid all locking and hash table lookups.
6119 * We cannot do this for TypeBuilders as mono_reflection_create_runtime_class expects
6120 * that the resulting object is diferent.
6122 if (type
== &klass
->byval_arg
&& !klass
->image
->dynamic
) {
6123 MonoVTable
*vtable
= mono_class_try_get_vtable (domain
, klass
);
6124 if (vtable
&& vtable
->type
)
6125 return vtable
->type
;
6128 mono_loader_lock (); /*FIXME mono_class_init and mono_class_vtable acquire it*/
6129 mono_domain_lock (domain
);
6130 if (!domain
->type_hash
)
6131 domain
->type_hash
= mono_g_hash_table_new_type ((GHashFunc
)mymono_metadata_type_hash
,
6132 (GCompareFunc
)mymono_metadata_type_equal
, MONO_HASH_VALUE_GC
);
6133 if ((res
= mono_g_hash_table_lookup (domain
->type_hash
, type
))) {
6134 mono_domain_unlock (domain
);
6135 mono_loader_unlock ();
6138 /* Create a MonoGenericClass object for instantiations of not finished TypeBuilders */
6139 if ((type
->type
== MONO_TYPE_GENERICINST
) && type
->data
.generic_class
->is_dynamic
&& !type
->data
.generic_class
->container_class
->wastypebuilder
) {
6140 res
= (MonoReflectionType
*)mono_generic_class_get_object (domain
, type
);
6141 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6142 mono_domain_unlock (domain
);
6143 mono_loader_unlock ();
6147 if (!verify_safe_for_managed_space (type
)) {
6148 mono_domain_unlock (domain
);
6149 mono_loader_unlock ();
6150 mono_raise_exception (mono_get_exception_invalid_operation ("This type cannot be propagated to managed space"));
6153 if (klass
->reflection_info
&& !klass
->wastypebuilder
) {
6154 /* g_assert_not_reached (); */
6155 /* should this be considered an error condition? */
6157 mono_domain_unlock (domain
);
6158 mono_loader_unlock ();
6159 return klass
->reflection_info
;
6162 // FIXME: Get rid of this, do it in the icalls for Type
6163 mono_class_init (klass
);
6165 res
= (MonoReflectionType
*)mono_gc_alloc_pinned_obj (mono_class_vtable (domain
, mono_defaults
.monotype_class
), mono_class_instance_size (mono_defaults
.monotype_class
));
6167 res
= (MonoReflectionType
*)mono_object_new (domain
, mono_defaults
.monotype_class
);
6170 mono_g_hash_table_insert (domain
->type_hash
, type
, res
);
6172 if (type
->type
== MONO_TYPE_VOID
)
6173 MONO_OBJECT_SETREF (domain
, typeof_void
, res
);
6175 mono_domain_unlock (domain
);
6176 mono_loader_unlock ();
6181 * mono_method_get_object:
6182 * @domain: an app domain
6184 * @refclass: the reflected type (can be NULL)
6186 * Return an System.Reflection.MonoMethod object representing the method @method.
6188 MonoReflectionMethod
*
6189 mono_method_get_object (MonoDomain
*domain
, MonoMethod
*method
, MonoClass
*refclass
)
6192 * We use the same C representation for methods and constructors, but the type
6193 * name in C# is different.
6195 static MonoClass
*System_Reflection_MonoMethod
= NULL
;
6196 static MonoClass
*System_Reflection_MonoCMethod
= NULL
;
6197 static MonoClass
*System_Reflection_MonoGenericMethod
= NULL
;
6198 static MonoClass
*System_Reflection_MonoGenericCMethod
= NULL
;
6200 MonoReflectionMethod
*ret
;
6203 * Don't let static RGCTX invoke wrappers get into
6204 * MonoReflectionMethods.
6206 if (method
->wrapper_type
== MONO_WRAPPER_STATIC_RGCTX_INVOKE
)
6207 method
= mono_marshal_method_from_wrapper (method
);
6209 if (method
->is_inflated
) {
6210 MonoReflectionGenericMethod
*gret
;
6212 refclass
= method
->klass
;
6213 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6214 if ((*method
->name
== '.') && (!strcmp (method
->name
, ".ctor") || !strcmp (method
->name
, ".cctor"))) {
6215 if (!System_Reflection_MonoGenericCMethod
)
6216 System_Reflection_MonoGenericCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericCMethod");
6217 klass
= System_Reflection_MonoGenericCMethod
;
6219 if (!System_Reflection_MonoGenericMethod
)
6220 System_Reflection_MonoGenericMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoGenericMethod");
6221 klass
= System_Reflection_MonoGenericMethod
;
6223 gret
= (MonoReflectionGenericMethod
*)mono_object_new (domain
, klass
);
6224 gret
->method
.method
= method
;
6225 MONO_OBJECT_SETREF (gret
, method
.name
, mono_string_new (domain
, method
->name
));
6226 MONO_OBJECT_SETREF (gret
, method
.reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6227 CACHE_OBJECT (MonoReflectionMethod
*, method
, (MonoReflectionMethod
*)gret
, refclass
);
6231 refclass
= method
->klass
;
6233 CHECK_OBJECT (MonoReflectionMethod
*, method
, refclass
);
6234 if (*method
->name
== '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0)) {
6235 if (!System_Reflection_MonoCMethod
)
6236 System_Reflection_MonoCMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoCMethod");
6237 klass
= System_Reflection_MonoCMethod
;
6240 if (!System_Reflection_MonoMethod
)
6241 System_Reflection_MonoMethod
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoMethod");
6242 klass
= System_Reflection_MonoMethod
;
6244 ret
= (MonoReflectionMethod
*)mono_object_new (domain
, klass
);
6245 ret
->method
= method
;
6246 MONO_OBJECT_SETREF (ret
, reftype
, mono_type_get_object (domain
, &refclass
->byval_arg
));
6247 CACHE_OBJECT (MonoReflectionMethod
*, method
, ret
, refclass
);
6251 * mono_method_clear_object:
6253 * Clear the cached reflection objects for the dynamic method METHOD.
6256 mono_method_clear_object (MonoDomain
*domain
, MonoMethod
*method
)
6258 g_assert (method
->dynamic
);
6260 clear_cached_object (domain
, method
, method
->klass
);
6261 /* Added by mono_param_get_objects () */
6262 clear_cached_object (domain
, &(method
->signature
), NULL
);
6266 * mono_field_get_object:
6267 * @domain: an app domain
6271 * Return an System.Reflection.MonoField object representing the field @field
6274 MonoReflectionField
*
6275 mono_field_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoClassField
*field
)
6277 MonoReflectionField
*res
;
6278 static MonoClass
*monofield_klass
;
6280 CHECK_OBJECT (MonoReflectionField
*, field
, klass
);
6281 if (!monofield_klass
)
6282 monofield_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoField");
6283 res
= (MonoReflectionField
*)mono_object_new (domain
, monofield_klass
);
6286 MONO_OBJECT_SETREF (res
, name
, mono_string_new (domain
, mono_field_get_name (field
)));
6287 if (is_field_on_inst (field
))
6288 res
->attrs
= get_field_on_inst_generic_type (field
)->attrs
;
6290 res
->attrs
= field
->type
->attrs
;
6291 MONO_OBJECT_SETREF (res
, type
, mono_type_get_object (domain
, field
->type
));
6292 CACHE_OBJECT (MonoReflectionField
*, field
, res
, klass
);
6296 * mono_property_get_object:
6297 * @domain: an app domain
6299 * @property: a property
6301 * Return an System.Reflection.MonoProperty object representing the property @property
6304 MonoReflectionProperty
*
6305 mono_property_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoProperty
*property
)
6307 MonoReflectionProperty
*res
;
6308 static MonoClass
*monoproperty_klass
;
6310 CHECK_OBJECT (MonoReflectionProperty
*, property
, klass
);
6311 if (!monoproperty_klass
)
6312 monoproperty_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoProperty");
6313 res
= (MonoReflectionProperty
*)mono_object_new (domain
, monoproperty_klass
);
6315 res
->property
= property
;
6316 CACHE_OBJECT (MonoReflectionProperty
*, property
, res
, klass
);
6320 * mono_event_get_object:
6321 * @domain: an app domain
6325 * Return an System.Reflection.MonoEvent object representing the event @event
6328 MonoReflectionEvent
*
6329 mono_event_get_object (MonoDomain
*domain
, MonoClass
*klass
, MonoEvent
*event
)
6331 MonoReflectionEvent
*res
;
6332 MonoReflectionMonoEvent
*mono_event
;
6333 static MonoClass
*monoevent_klass
;
6335 CHECK_OBJECT (MonoReflectionEvent
*, event
, klass
);
6336 if (!monoevent_klass
)
6337 monoevent_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MonoEvent");
6338 mono_event
= (MonoReflectionMonoEvent
*)mono_object_new (domain
, monoevent_klass
);
6339 mono_event
->klass
= klass
;
6340 mono_event
->event
= event
;
6341 res
= (MonoReflectionEvent
*)mono_event
;
6342 CACHE_OBJECT (MonoReflectionEvent
*, event
, res
, klass
);
6346 * mono_get_reflection_missing_object:
6347 * @domain: Domain where the object lives
6349 * Returns the System.Reflection.Missing.Value singleton object
6350 * (of type System.Reflection.Missing).
6352 * Used as the value for ParameterInfo.DefaultValue when Optional
6356 mono_get_reflection_missing_object (MonoDomain
*domain
)
6359 static MonoClassField
*missing_value_field
= NULL
;
6361 if (!missing_value_field
) {
6362 MonoClass
*missing_klass
;
6363 missing_klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Missing");
6364 mono_class_init (missing_klass
);
6365 missing_value_field
= mono_class_get_field_from_name (missing_klass
, "Value");
6366 g_assert (missing_value_field
);
6368 obj
= mono_field_get_value_object (domain
, missing_value_field
, NULL
);
6374 get_dbnull (MonoDomain
*domain
, MonoObject
**dbnull
)
6377 *dbnull
= mono_get_dbnull_object (domain
);
6382 get_reflection_missing (MonoDomain
*domain
, MonoObject
**reflection_missing
)
6384 if (!*reflection_missing
)
6385 *reflection_missing
= mono_get_reflection_missing_object (domain
);
6386 return *reflection_missing
;
6390 * mono_param_get_objects:
6391 * @domain: an app domain
6394 * Return an System.Reflection.ParameterInfo array object representing the parameters
6395 * in the method @method.
6398 mono_param_get_objects (MonoDomain
*domain
, MonoMethod
*method
)
6400 static MonoClass
*System_Reflection_ParameterInfo
;
6401 static MonoClass
*System_Reflection_ParameterInfo_array
;
6402 MonoArray
*res
= NULL
;
6403 MonoReflectionMethod
*member
= NULL
;
6404 MonoReflectionParameter
*param
= NULL
;
6405 char **names
, **blobs
= NULL
;
6406 guint32
*types
= NULL
;
6407 MonoType
*type
= NULL
;
6408 MonoObject
*dbnull
= NULL
;
6409 MonoObject
*missing
= NULL
;
6410 MonoMarshalSpec
**mspecs
;
6411 MonoMethodSignature
*sig
;
6412 MonoVTable
*pinfo_vtable
;
6415 if (!System_Reflection_ParameterInfo_array
) {
6418 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ParameterInfo");
6419 mono_memory_barrier ();
6420 System_Reflection_ParameterInfo
= klass
;
6422 klass
= mono_array_class_get (klass
, 1);
6423 mono_memory_barrier ();
6424 System_Reflection_ParameterInfo_array
= klass
;
6427 if (!mono_method_signature (method
)->param_count
)
6428 return mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), 0);
6430 /* Note: the cache is based on the address of the signature into the method
6431 * since we already cache MethodInfos with the method as keys.
6433 CHECK_OBJECT (MonoArray
*, &(method
->signature
), NULL
);
6435 sig
= mono_method_signature (method
);
6436 member
= mono_method_get_object (domain
, method
, NULL
);
6437 names
= g_new (char *, sig
->param_count
);
6438 mono_method_get_param_names (method
, (const char **) names
);
6440 mspecs
= g_new (MonoMarshalSpec
*, sig
->param_count
+ 1);
6441 mono_method_get_marshal_info (method
, mspecs
);
6443 res
= mono_array_new_specific (mono_class_vtable (domain
, System_Reflection_ParameterInfo_array
), sig
->param_count
);
6444 pinfo_vtable
= mono_class_vtable (domain
, System_Reflection_ParameterInfo
);
6445 for (i
= 0; i
< sig
->param_count
; ++i
) {
6446 param
= (MonoReflectionParameter
*)mono_object_new_specific (pinfo_vtable
);
6447 MONO_OBJECT_SETREF (param
, ClassImpl
, mono_type_get_object (domain
, sig
->params
[i
]));
6448 MONO_OBJECT_SETREF (param
, MemberImpl
, (MonoObject
*)member
);
6449 MONO_OBJECT_SETREF (param
, NameImpl
, mono_string_new (domain
, names
[i
]));
6450 param
->PositionImpl
= i
;
6451 param
->AttrsImpl
= sig
->params
[i
]->attrs
;
6453 if (!(param
->AttrsImpl
& PARAM_ATTRIBUTE_HAS_DEFAULT
)) {
6454 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6455 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6457 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6461 blobs
= g_new0 (char *, sig
->param_count
);
6462 types
= g_new0 (guint32
, sig
->param_count
);
6463 get_default_param_value_blobs (method
, blobs
, types
);
6466 /* Build MonoType for the type from the Constant Table */
6468 type
= g_new0 (MonoType
, 1);
6469 type
->type
= types
[i
];
6470 type
->data
.klass
= NULL
;
6471 if (types
[i
] == MONO_TYPE_CLASS
)
6472 type
->data
.klass
= mono_defaults
.object_class
;
6473 else if ((sig
->params
[i
]->type
== MONO_TYPE_VALUETYPE
) && sig
->params
[i
]->data
.klass
->enumtype
) {
6474 /* For enums, types [i] contains the base type */
6476 type
->type
= MONO_TYPE_VALUETYPE
;
6477 type
->data
.klass
= mono_class_from_mono_type (sig
->params
[i
]);
6479 type
->data
.klass
= mono_class_from_mono_type (type
);
6481 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, mono_get_object_from_blob (domain
, type
, blobs
[i
]));
6483 /* Type in the Constant table is MONO_TYPE_CLASS for nulls */
6484 if (types
[i
] != MONO_TYPE_CLASS
&& !param
->DefaultValueImpl
) {
6485 if (param
->AttrsImpl
& PARAM_ATTRIBUTE_OPTIONAL
)
6486 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_reflection_missing (domain
, &missing
));
6488 MONO_OBJECT_SETREF (param
, DefaultValueImpl
, get_dbnull (domain
, &dbnull
));
6494 MONO_OBJECT_SETREF (param
, MarshalAsImpl
, (MonoObject
*)mono_reflection_marshal_from_marshal_spec (domain
, method
->klass
, mspecs
[i
+ 1]));
6496 mono_array_setref (res
, i
, param
);
6503 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
6505 mono_metadata_free_marshal_spec (mspecs
[i
]);
6508 CACHE_OBJECT (MonoArray
*, &(method
->signature
), res
, NULL
);
6512 * mono_method_body_get_object:
6513 * @domain: an app domain
6516 * Return an System.Reflection.MethodBody object representing the method @method.
6518 MonoReflectionMethodBody
*
6519 mono_method_body_get_object (MonoDomain
*domain
, MonoMethod
*method
)
6521 static MonoClass
*System_Reflection_MethodBody
= NULL
;
6522 static MonoClass
*System_Reflection_LocalVariableInfo
= NULL
;
6523 static MonoClass
*System_Reflection_ExceptionHandlingClause
= NULL
;
6524 MonoReflectionMethodBody
*ret
;
6525 MonoMethodNormal
*mn
;
6526 MonoMethodHeader
*header
;
6527 guint32 method_rva
, local_var_sig_token
;
6529 unsigned char format
, flags
;
6532 if (!System_Reflection_MethodBody
)
6533 System_Reflection_MethodBody
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "MethodBody");
6534 if (!System_Reflection_LocalVariableInfo
)
6535 System_Reflection_LocalVariableInfo
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "LocalVariableInfo");
6536 if (!System_Reflection_ExceptionHandlingClause
)
6537 System_Reflection_ExceptionHandlingClause
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "ExceptionHandlingClause");
6539 CHECK_OBJECT (MonoReflectionMethodBody
*, method
, NULL
);
6541 if ((method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
6542 (method
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) ||
6543 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) ||
6544 (method
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
))
6546 mn
= (MonoMethodNormal
*)method
;
6547 header
= mono_method_get_header (method
);
6549 /* Obtain local vars signature token */
6550 method_rva
= mono_metadata_decode_row_col (&method
->klass
->image
->tables
[MONO_TABLE_METHOD
], mono_metadata_token_index (method
->token
) - 1, MONO_METHOD_RVA
);
6551 ptr
= mono_image_rva_map (method
->klass
->image
, method_rva
);
6552 flags
= *(const unsigned char *) ptr
;
6553 format
= flags
& METHOD_HEADER_FORMAT_MASK
;
6555 case METHOD_HEADER_TINY_FORMAT
:
6556 case METHOD_HEADER_TINY_FORMAT1
:
6557 local_var_sig_token
= 0;
6559 case METHOD_HEADER_FAT_FORMAT
:
6563 local_var_sig_token
= read32 (ptr
);
6566 g_assert_not_reached ();
6569 ret
= (MonoReflectionMethodBody
*)mono_object_new (domain
, System_Reflection_MethodBody
);
6571 ret
->init_locals
= header
->init_locals
;
6572 ret
->max_stack
= header
->max_stack
;
6573 ret
->local_var_sig_token
= local_var_sig_token
;
6574 MONO_OBJECT_SETREF (ret
, il
, mono_array_new_cached (domain
, mono_defaults
.byte_class
, header
->code_size
));
6575 memcpy (mono_array_addr (ret
->il
, guint8
, 0), header
->code
, header
->code_size
);
6578 MONO_OBJECT_SETREF (ret
, locals
, mono_array_new_cached (domain
, System_Reflection_LocalVariableInfo
, header
->num_locals
));
6579 for (i
= 0; i
< header
->num_locals
; ++i
) {
6580 MonoReflectionLocalVariableInfo
*info
= (MonoReflectionLocalVariableInfo
*)mono_object_new (domain
, System_Reflection_LocalVariableInfo
);
6581 MONO_OBJECT_SETREF (info
, local_type
, mono_type_get_object (domain
, header
->locals
[i
]));
6582 info
->is_pinned
= header
->locals
[i
]->pinned
;
6583 info
->local_index
= i
;
6584 mono_array_setref (ret
->locals
, i
, info
);
6588 MONO_OBJECT_SETREF (ret
, clauses
, mono_array_new_cached (domain
, System_Reflection_ExceptionHandlingClause
, header
->num_clauses
));
6589 for (i
= 0; i
< header
->num_clauses
; ++i
) {
6590 MonoReflectionExceptionHandlingClause
*info
= (MonoReflectionExceptionHandlingClause
*)mono_object_new (domain
, System_Reflection_ExceptionHandlingClause
);
6591 MonoExceptionClause
*clause
= &header
->clauses
[i
];
6593 info
->flags
= clause
->flags
;
6594 info
->try_offset
= clause
->try_offset
;
6595 info
->try_length
= clause
->try_len
;
6596 info
->handler_offset
= clause
->handler_offset
;
6597 info
->handler_length
= clause
->handler_len
;
6598 if (clause
->flags
== MONO_EXCEPTION_CLAUSE_FILTER
)
6599 info
->filter_offset
= clause
->data
.filter_offset
;
6600 else if (clause
->data
.catch_class
)
6601 MONO_OBJECT_SETREF (info
, catch_type
, mono_type_get_object (mono_domain_get (), &clause
->data
.catch_class
->byval_arg
));
6603 mono_array_setref (ret
->clauses
, i
, info
);
6606 CACHE_OBJECT (MonoReflectionMethodBody
*, method
, ret
, NULL
);
6611 * mono_get_dbnull_object:
6612 * @domain: Domain where the object lives
6614 * Returns the System.DBNull.Value singleton object
6616 * Used as the value for ParameterInfo.DefaultValue
6619 mono_get_dbnull_object (MonoDomain
*domain
)
6622 static MonoClassField
*dbnull_value_field
= NULL
;
6624 if (!dbnull_value_field
) {
6625 MonoClass
*dbnull_klass
;
6626 dbnull_klass
= mono_class_from_name (mono_defaults
.corlib
, "System", "DBNull");
6627 mono_class_init (dbnull_klass
);
6628 dbnull_value_field
= mono_class_get_field_from_name (dbnull_klass
, "Value");
6629 g_assert (dbnull_value_field
);
6631 obj
= mono_field_get_value_object (domain
, dbnull_value_field
, NULL
);
6637 get_default_param_value_blobs (MonoMethod
*method
, char **blobs
, guint32
*types
)
6639 guint32 param_index
, i
, lastp
, crow
= 0;
6640 guint32 param_cols
[MONO_PARAM_SIZE
], const_cols
[MONO_CONSTANT_SIZE
];
6643 MonoClass
*klass
= method
->klass
;
6644 MonoImage
*image
= klass
->image
;
6645 MonoMethodSignature
*methodsig
= mono_method_signature (method
);
6647 MonoTableInfo
*constt
;
6648 MonoTableInfo
*methodt
;
6649 MonoTableInfo
*paramt
;
6651 if (!methodsig
->param_count
)
6654 mono_class_init (klass
);
6656 if (klass
->image
->dynamic
) {
6657 MonoReflectionMethodAux
*aux
;
6658 if (method
->is_inflated
)
6659 method
= ((MonoMethodInflated
*)method
)->declaring
;
6660 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
6661 if (aux
&& aux
->param_defaults
) {
6662 memcpy (blobs
, &(aux
->param_defaults
[1]), methodsig
->param_count
* sizeof (char*));
6663 memcpy (types
, &(aux
->param_default_types
[1]), methodsig
->param_count
* sizeof (guint32
));
6668 methodt
= &klass
->image
->tables
[MONO_TABLE_METHOD
];
6669 paramt
= &klass
->image
->tables
[MONO_TABLE_PARAM
];
6670 constt
= &image
->tables
[MONO_TABLE_CONSTANT
];
6672 idx
= mono_method_get_index (method
) - 1;
6673 g_assert (idx
!= -1);
6675 param_index
= mono_metadata_decode_row_col (methodt
, idx
, MONO_METHOD_PARAMLIST
);
6676 if (idx
+ 1 < methodt
->rows
)
6677 lastp
= mono_metadata_decode_row_col (methodt
, idx
+ 1, MONO_METHOD_PARAMLIST
);
6679 lastp
= paramt
->rows
+ 1;
6681 for (i
= param_index
; i
< lastp
; ++i
) {
6684 mono_metadata_decode_row (paramt
, i
- 1, param_cols
, MONO_PARAM_SIZE
);
6685 paramseq
= param_cols
[MONO_PARAM_SEQUENCE
];
6687 if (!param_cols
[MONO_PARAM_FLAGS
] & PARAM_ATTRIBUTE_HAS_DEFAULT
)
6690 crow
= mono_metadata_get_constant_index (image
, MONO_TOKEN_PARAM_DEF
| i
, crow
+ 1);
6695 mono_metadata_decode_row (constt
, crow
- 1, const_cols
, MONO_CONSTANT_SIZE
);
6696 blobs
[paramseq
- 1] = (gpointer
) mono_metadata_blob_heap (image
, const_cols
[MONO_CONSTANT_VALUE
]);
6697 types
[paramseq
- 1] = const_cols
[MONO_CONSTANT_TYPE
];
6704 mono_get_object_from_blob (MonoDomain
*domain
, MonoType
*type
, const char *blob
)
6709 MonoType
*basetype
= type
;
6714 klass
= mono_class_from_mono_type (type
);
6715 if (klass
->valuetype
) {
6716 object
= mono_object_new (domain
, klass
);
6717 retval
= ((gchar
*) object
+ sizeof (MonoObject
));
6718 if (klass
->enumtype
)
6719 basetype
= mono_class_enum_basetype (klass
);
6724 if (!mono_get_constant_value_from_blob (domain
, basetype
->type
, blob
, retval
))
6731 assembly_name_to_aname (MonoAssemblyName
*assembly
, char *p
) {
6735 memset (assembly
, 0, sizeof (MonoAssemblyName
));
6737 assembly
->culture
= "";
6738 memset (assembly
->public_key_token
, 0, MONO_PUBLIC_KEY_TOKEN_LENGTH
);
6740 while (*p
&& (isalnum (*p
) || *p
== '.' || *p
== '-' || *p
== '_' || *p
== '$' || *p
== '@'))
6743 while (g_ascii_isspace (*p
) || *p
== ',') {
6752 if (*p
== 'V' && g_ascii_strncasecmp (p
, "Version=", 8) == 0) {
6754 assembly
->major
= strtoul (p
, &s
, 10);
6755 if (s
== p
|| *s
!= '.')
6758 assembly
->minor
= strtoul (p
, &s
, 10);
6759 if (s
== p
|| *s
!= '.')
6762 assembly
->build
= strtoul (p
, &s
, 10);
6763 if (s
== p
|| *s
!= '.')
6766 assembly
->revision
= strtoul (p
, &s
, 10);
6770 } else if (*p
== 'C' && g_ascii_strncasecmp (p
, "Culture=", 8) == 0) {
6772 if (g_ascii_strncasecmp (p
, "neutral", 7) == 0) {
6773 assembly
->culture
= "";
6776 assembly
->culture
= p
;
6777 while (*p
&& *p
!= ',') {
6781 } else if (*p
== 'P' && g_ascii_strncasecmp (p
, "PublicKeyToken=", 15) == 0) {
6783 if (strncmp (p
, "null", 4) == 0) {
6788 while (*p
&& *p
!= ',') {
6791 len
= (p
- start
+ 1);
6792 if (len
> MONO_PUBLIC_KEY_TOKEN_LENGTH
)
6793 len
= MONO_PUBLIC_KEY_TOKEN_LENGTH
;
6794 g_strlcpy ((char*)assembly
->public_key_token
, start
, len
);
6797 while (*p
&& *p
!= ',')
6801 while (g_ascii_isspace (*p
) || *p
== ',') {
6815 * mono_reflection_parse_type:
6818 * Parse a type name as accepted by the GetType () method and output the info
6819 * extracted in the info structure.
6820 * the name param will be mangled, so, make a copy before passing it to this function.
6821 * The fields in info will be valid until the memory pointed to by name is valid.
6823 * See also mono_type_get_name () below.
6825 * Returns: 0 on parse error.
6828 _mono_reflection_parse_type (char *name
, char **endptr
, gboolean is_recursed
,
6829 MonoTypeNameParse
*info
)
6831 char *start
, *p
, *w
, *temp
, *last_point
, *startn
;
6832 int in_modifiers
= 0;
6833 int isbyref
= 0, rank
, arity
= 0, i
;
6835 start
= p
= w
= name
;
6837 //FIXME could we just zero the whole struct? memset (&info, 0, sizeof (MonoTypeNameParse))
6838 memset (&info
->assembly
, 0, sizeof (MonoAssemblyName
));
6839 info
->name
= info
->name_space
= NULL
;
6840 info
->nested
= NULL
;
6841 info
->modifiers
= NULL
;
6842 info
->type_arguments
= NULL
;
6844 /* last_point separates the namespace from the name */
6847 while (*p
== ' ') p
++, start
++, w
++, name
++;
6852 *p
= 0; /* NULL terminate the name */
6854 info
->nested
= g_list_append (info
->nested
, startn
);
6855 /* we have parsed the nesting namespace + name */
6859 info
->name_space
= start
;
6861 info
->name
= last_point
+ 1;
6863 info
->name_space
= (char *)"";
6882 i
= strtol (p
, &temp
, 10);
6899 info
->name_space
= start
;
6901 info
->name
= last_point
+ 1;
6903 info
->name_space
= (char *)"";
6910 if (isbyref
) /* only one level allowed by the spec */
6913 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (0));
6917 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-1));
6923 info
->type_arguments
= g_ptr_array_new ();
6924 for (i
= 0; i
< arity
; i
++) {
6925 MonoTypeNameParse
*subinfo
= g_new0 (MonoTypeNameParse
, 1);
6926 gboolean fqname
= FALSE
;
6928 g_ptr_array_add (info
->type_arguments
, subinfo
);
6935 if (!_mono_reflection_parse_type (p
, &p
, TRUE
, subinfo
))
6946 while (*p
&& (*p
!= ']'))
6954 if (g_ascii_isspace (*aname
)) {
6961 !assembly_name_to_aname (&subinfo
->assembly
, aname
))
6965 if (i
+ 1 < arity
) {
6985 else if (*p
== '*') /* '*' means unknown lower bound */
6986 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (-2));
6993 info
->modifiers
= g_list_append (info
->modifiers
, GUINT_TO_POINTER (rank
));
7004 if (g_ascii_isspace (*p
)) {
7011 return 0; /* missing assembly name */
7012 if (!assembly_name_to_aname (&info
->assembly
, p
))
7018 if (info
->assembly
.name
)
7021 // *w = 0; /* terminate class name */
7023 if (!info
->name
|| !*info
->name
)
7027 /* add other consistency checks */
7032 mono_reflection_parse_type (char *name
, MonoTypeNameParse
*info
)
7034 return _mono_reflection_parse_type (name
, NULL
, FALSE
, info
);
7038 _mono_reflection_get_type_from_info (MonoTypeNameParse
*info
, MonoImage
*image
, gboolean ignorecase
)
7040 gboolean type_resolve
= FALSE
;
7042 MonoImage
*rootimage
= image
;
7044 if (info
->assembly
.name
) {
7045 MonoAssembly
*assembly
= mono_assembly_loaded (&info
->assembly
);
7046 if (!assembly
&& image
&& image
->assembly
&& mono_assembly_names_equal (&info
->assembly
, &image
->assembly
->aname
))
7048 * This could happen in the AOT compiler case when the search hook is not
7051 assembly
= image
->assembly
;
7053 /* then we must load the assembly ourselve - see #60439 */
7054 assembly
= mono_assembly_load (&info
->assembly
, NULL
, NULL
);
7058 image
= assembly
->image
;
7059 } else if (!image
) {
7060 image
= mono_defaults
.corlib
;
7063 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7064 if (type
== NULL
&& !info
->assembly
.name
&& image
!= mono_defaults
.corlib
) {
7065 image
= mono_defaults
.corlib
;
7066 type
= mono_reflection_get_type_with_rootimage (rootimage
, image
, info
, ignorecase
, &type_resolve
);
7073 mono_reflection_get_type_internal (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7078 gboolean bounded
= FALSE
;
7081 image
= mono_defaults
.corlib
;
7084 klass
= mono_class_from_name_case (image
, info
->name_space
, info
->name
);
7086 klass
= mono_class_from_name (image
, info
->name_space
, info
->name
);
7089 for (mod
= info
->nested
; mod
; mod
= mod
->next
) {
7090 gpointer iter
= NULL
;
7094 mono_class_init (parent
);
7096 while ((klass
= mono_class_get_nested_types (parent
, &iter
))) {
7098 if (g_strcasecmp (klass
->name
, mod
->data
) == 0)
7101 if (strcmp (klass
->name
, mod
->data
) == 0)
7110 mono_class_init (klass
);
7112 if (info
->type_arguments
) {
7113 MonoType
**type_args
= g_new0 (MonoType
*, info
->type_arguments
->len
);
7114 MonoReflectionType
*the_type
;
7118 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7119 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7121 type_args
[i
] = _mono_reflection_get_type_from_info (subinfo
, rootimage
, ignorecase
);
7122 if (!type_args
[i
]) {
7128 the_type
= mono_type_get_object (mono_domain_get (), &klass
->byval_arg
);
7130 instance
= mono_reflection_bind_generic_parameters (
7131 the_type
, info
->type_arguments
->len
, type_args
);
7137 klass
= mono_class_from_mono_type (instance
);
7140 for (mod
= info
->modifiers
; mod
; mod
= mod
->next
) {
7141 modval
= GPOINTER_TO_UINT (mod
->data
);
7142 if (!modval
) { /* byref: must be last modifier */
7143 return &klass
->this_arg
;
7144 } else if (modval
== -1) {
7145 klass
= mono_ptr_class_get (&klass
->byval_arg
);
7146 } else if (modval
== -2) {
7148 } else { /* array rank */
7149 klass
= mono_bounded_array_class_get (klass
, modval
, bounded
);
7151 mono_class_init (klass
);
7154 return &klass
->byval_arg
;
7158 * mono_reflection_get_type:
7159 * @image: a metadata context
7160 * @info: type description structure
7161 * @ignorecase: flag for case-insensitive string compares
7162 * @type_resolve: whenever type resolve was already tried
7164 * Build a MonoType from the type description in @info.
7169 mono_reflection_get_type (MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
) {
7170 return mono_reflection_get_type_with_rootimage(image
, image
, info
, ignorecase
, type_resolve
);
7174 mono_reflection_get_type_internal_dynamic (MonoImage
*rootimage
, MonoAssembly
*assembly
, MonoTypeNameParse
*info
, gboolean ignorecase
)
7176 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)mono_assembly_get_object (mono_domain_get (), assembly
);
7180 g_assert (assembly
->dynamic
);
7182 /* Enumerate all modules */
7185 if (abuilder
->modules
) {
7186 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
7187 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
7188 type
= mono_reflection_get_type_internal (rootimage
, &mb
->dynamic_image
->image
, info
, ignorecase
);
7194 if (!type
&& abuilder
->loaded_modules
) {
7195 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
7196 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
7197 type
= mono_reflection_get_type_internal (rootimage
, mod
->image
, info
, ignorecase
);
7207 mono_reflection_get_type_with_rootimage (MonoImage
*rootimage
, MonoImage
* image
, MonoTypeNameParse
*info
, gboolean ignorecase
, gboolean
*type_resolve
)
7210 MonoReflectionAssembly
*assembly
;
7214 if (image
&& image
->dynamic
)
7215 type
= mono_reflection_get_type_internal_dynamic (rootimage
, image
->assembly
, info
, ignorecase
);
7217 type
= mono_reflection_get_type_internal (rootimage
, image
, info
, ignorecase
);
7220 if (!mono_domain_has_type_resolve (mono_domain_get ()))
7227 *type_resolve
= TRUE
;
7230 /* Reconstruct the type name */
7231 fullName
= g_string_new ("");
7232 if (info
->name_space
&& (info
->name_space
[0] != '\0'))
7233 g_string_printf (fullName
, "%s.%s", info
->name_space
, info
->name
);
7235 g_string_printf (fullName
, info
->name
);
7236 for (mod
= info
->nested
; mod
; mod
= mod
->next
)
7237 g_string_append_printf (fullName
, "+%s", (char*)mod
->data
);
7239 assembly
= mono_domain_try_type_resolve ( mono_domain_get (), fullName
->str
, NULL
);
7241 if (assembly
->assembly
->dynamic
)
7242 type
= mono_reflection_get_type_internal_dynamic (rootimage
, assembly
->assembly
, info
, ignorecase
);
7244 type
= mono_reflection_get_type_internal (rootimage
, assembly
->assembly
->image
,
7247 g_string_free (fullName
, TRUE
);
7252 mono_reflection_free_type_info (MonoTypeNameParse
*info
)
7254 g_list_free (info
->modifiers
);
7255 g_list_free (info
->nested
);
7257 if (info
->type_arguments
) {
7260 for (i
= 0; i
< info
->type_arguments
->len
; i
++) {
7261 MonoTypeNameParse
*subinfo
= g_ptr_array_index (info
->type_arguments
, i
);
7263 mono_reflection_free_type_info (subinfo
);
7264 /*We free the subinfo since it is allocated by _mono_reflection_parse_type*/
7268 g_ptr_array_free (info
->type_arguments
, TRUE
);
7273 * mono_reflection_type_from_name:
7275 * @image: a metadata context (can be NULL).
7277 * Retrieves a MonoType from its @name. If the name is not fully qualified,
7278 * it defaults to get the type from @image or, if @image is NULL or loading
7279 * from it fails, uses corlib.
7283 mono_reflection_type_from_name (char *name
, MonoImage
*image
)
7285 MonoType
*type
= NULL
;
7286 MonoTypeNameParse info
;
7289 /* Make a copy since parse_type modifies its argument */
7290 tmp
= g_strdup (name
);
7292 /*g_print ("requested type %s\n", str);*/
7293 if (mono_reflection_parse_type (tmp
, &info
)) {
7294 type
= _mono_reflection_get_type_from_info (&info
, image
, FALSE
);
7298 mono_reflection_free_type_info (&info
);
7303 * mono_reflection_get_token:
7305 * Return the metadata token of OBJ which should be an object
7306 * representing a metadata element.
7309 mono_reflection_get_token (MonoObject
*obj
)
7314 klass
= obj
->vtable
->klass
;
7316 if (strcmp (klass
->name
, "MethodBuilder") == 0) {
7317 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
7319 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7320 } else if (strcmp (klass
->name
, "ConstructorBuilder") == 0) {
7321 MonoReflectionCtorBuilder
*mb
= (MonoReflectionCtorBuilder
*)obj
;
7323 token
= mb
->table_idx
| MONO_TOKEN_METHOD_DEF
;
7324 } else if (strcmp (klass
->name
, "FieldBuilder") == 0) {
7325 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
7327 /* Call mono_image_create_token so the object gets added to the tokens hash table */
7328 token
= mono_image_create_token (((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
, obj
, FALSE
, TRUE
);
7329 } else if (strcmp (klass
->name
, "TypeBuilder") == 0) {
7330 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
7331 token
= tb
->table_idx
| MONO_TOKEN_TYPE_DEF
;
7332 } else if (strcmp (klass
->name
, "MonoType") == 0) {
7333 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
7334 token
= mono_class_from_mono_type (tb
->type
)->type_token
;
7335 } else if (strcmp (klass
->name
, "MonoCMethod") == 0 ||
7336 strcmp (klass
->name
, "MonoMethod") == 0 ||
7337 strcmp (klass
->name
, "MonoGenericMethod") == 0 ||
7338 strcmp (klass
->name
, "MonoGenericCMethod") == 0) {
7339 MonoReflectionMethod
*m
= (MonoReflectionMethod
*)obj
;
7340 if (m
->method
->is_inflated
) {
7341 MonoMethodInflated
*inflated
= (MonoMethodInflated
*) m
->method
;
7342 return inflated
->declaring
->token
;
7344 token
= m
->method
->token
;
7346 } else if (strcmp (klass
->name
, "MonoField") == 0) {
7347 MonoReflectionField
*f
= (MonoReflectionField
*)obj
;
7349 if (is_field_on_inst (f
->field
)) {
7350 MonoDynamicGenericClass
*dgclass
= (MonoDynamicGenericClass
*)f
->field
->parent
->generic_class
;
7351 int field_index
= f
->field
- dgclass
->fields
;
7354 g_assert (field_index
>= 0 && field_index
< dgclass
->count_fields
);
7355 obj
= dgclass
->field_objects
[field_index
];
7356 return mono_reflection_get_token (obj
);
7358 token
= mono_class_get_field_token (f
->field
);
7359 } else if (strcmp (klass
->name
, "MonoProperty") == 0) {
7360 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)obj
;
7362 token
= mono_class_get_property_token (p
->property
);
7363 } else if (strcmp (klass
->name
, "MonoEvent") == 0) {
7364 MonoReflectionMonoEvent
*p
= (MonoReflectionMonoEvent
*)obj
;
7366 token
= mono_class_get_event_token (p
->event
);
7367 } else if (strcmp (klass
->name
, "ParameterInfo") == 0) {
7368 MonoReflectionParameter
*p
= (MonoReflectionParameter
*)obj
;
7370 token
= mono_method_get_param_token (((MonoReflectionMethod
*)p
->MemberImpl
)->method
, p
->PositionImpl
);
7371 } else if (strcmp (klass
->name
, "Module") == 0) {
7372 MonoReflectionModule
*m
= (MonoReflectionModule
*)obj
;
7375 } else if (strcmp (klass
->name
, "Assembly") == 0) {
7376 token
= mono_metadata_make_token (MONO_TABLE_ASSEMBLY
, 1);
7378 gchar
*msg
= g_strdup_printf ("MetadataToken is not supported for type '%s.%s'", klass
->name_space
, klass
->name
);
7379 MonoException
*ex
= mono_get_exception_not_implemented (msg
);
7381 mono_raise_exception (ex
);
7388 load_cattr_value (MonoImage
*image
, MonoType
*t
, const char *p
, const char **end
)
7390 int slen
, type
= t
->type
;
7391 MonoClass
*tklass
= t
->data
.klass
;
7397 case MONO_TYPE_BOOLEAN
: {
7398 MonoBoolean
*bval
= g_malloc (sizeof (MonoBoolean
));
7403 case MONO_TYPE_CHAR
:
7405 case MONO_TYPE_I2
: {
7406 guint16
*val
= g_malloc (sizeof (guint16
));
7411 #if SIZEOF_VOID_P == 4
7417 case MONO_TYPE_I4
: {
7418 guint32
*val
= g_malloc (sizeof (guint32
));
7423 #if SIZEOF_VOID_P == 8
7424 case MONO_TYPE_U
: /* error out instead? this should probably not happen */
7428 case MONO_TYPE_I8
: {
7429 guint64
*val
= g_malloc (sizeof (guint64
));
7434 case MONO_TYPE_R8
: {
7435 double *val
= g_malloc (sizeof (double));
7440 case MONO_TYPE_VALUETYPE
:
7441 if (t
->data
.klass
->enumtype
) {
7442 type
= mono_class_enum_basetype (t
->data
.klass
)->type
;
7445 g_error ("generic valutype %s not handled in custom attr value decoding", t
->data
.klass
->name
);
7448 case MONO_TYPE_STRING
:
7449 if (*p
== (char)0xFF) {
7453 slen
= mono_metadata_decode_value (p
, &p
);
7455 return mono_string_new_len (mono_domain_get (), p
, slen
);
7456 case MONO_TYPE_CLASS
: {
7459 if (*p
== (char)0xFF) {
7464 slen
= mono_metadata_decode_value (p
, &p
);
7465 n
= g_memdup (p
, slen
+ 1);
7467 t
= mono_reflection_type_from_name (n
, image
);
7469 g_warning ("Cannot load type '%s'", n
);
7473 return mono_type_get_object (mono_domain_get (), t
);
7477 case MONO_TYPE_OBJECT
: {
7480 MonoClass
*subc
= NULL
;
7485 } else if (subt
== 0x0E) {
7486 type
= MONO_TYPE_STRING
;
7488 } else if (subt
== 0x1D) {
7489 MonoType simple_type
= {{0}};
7494 /* See Partition II, Appendix B3 */
7495 etype
= MONO_TYPE_OBJECT
;
7496 type
= MONO_TYPE_SZARRAY
;
7497 simple_type
.type
= etype
;
7498 tklass
= mono_class_from_mono_type (&simple_type
);
7500 } else if (subt
== 0x55) {
7503 slen
= mono_metadata_decode_value (p
, &p
);
7504 n
= g_memdup (p
, slen
+ 1);
7506 t
= mono_reflection_type_from_name (n
, image
);
7508 g_error ("Cannot load type '%s'", n
);
7511 subc
= mono_class_from_mono_type (t
);
7512 } else if (subt
>= MONO_TYPE_BOOLEAN
&& subt
<= MONO_TYPE_R8
) {
7513 MonoType simple_type
= {{0}};
7514 simple_type
.type
= subt
;
7515 subc
= mono_class_from_mono_type (&simple_type
);
7517 g_error ("Unknown type 0x%02x for object type encoding in custom attr", subt
);
7519 val
= load_cattr_value (image
, &subc
->byval_arg
, p
, end
);
7520 obj
= mono_object_new (mono_domain_get (), subc
);
7521 memcpy ((char*)obj
+ sizeof (MonoObject
), val
, mono_class_value_size (subc
, NULL
));
7525 case MONO_TYPE_SZARRAY
: {
7527 guint32 i
, alen
, basetype
;
7530 if (alen
== 0xffffffff) {
7534 arr
= mono_array_new (mono_domain_get(), tklass
, alen
);
7535 basetype
= tklass
->byval_arg
.type
;
7536 if (basetype
== MONO_TYPE_VALUETYPE
&& tklass
->enumtype
)
7537 basetype
= mono_class_enum_basetype (tklass
)->type
;
7542 case MONO_TYPE_BOOLEAN
:
7543 for (i
= 0; i
< alen
; i
++) {
7544 MonoBoolean val
= *p
++;
7545 mono_array_set (arr
, MonoBoolean
, i
, val
);
7548 case MONO_TYPE_CHAR
:
7551 for (i
= 0; i
< alen
; i
++) {
7552 guint16 val
= read16 (p
);
7553 mono_array_set (arr
, guint16
, i
, val
);
7560 for (i
= 0; i
< alen
; i
++) {
7561 guint32 val
= read32 (p
);
7562 mono_array_set (arr
, guint32
, i
, val
);
7567 for (i
= 0; i
< alen
; i
++) {
7570 mono_array_set (arr
, double, i
, val
);
7576 for (i
= 0; i
< alen
; i
++) {
7577 guint64 val
= read64 (p
);
7578 mono_array_set (arr
, guint64
, i
, val
);
7582 case MONO_TYPE_CLASS
:
7583 case MONO_TYPE_OBJECT
:
7584 case MONO_TYPE_STRING
:
7585 for (i
= 0; i
< alen
; i
++) {
7586 MonoObject
*item
= load_cattr_value (image
, &tklass
->byval_arg
, p
, &p
);
7587 mono_array_setref (arr
, i
, item
);
7591 g_error ("Type 0x%02x not handled in custom attr array decoding", basetype
);
7597 g_error ("Type 0x%02x not handled in custom attr value decoding", type
);
7603 create_cattr_typed_arg (MonoType
*t
, MonoObject
*val
)
7605 static MonoClass
*klass
;
7606 static MonoMethod
*ctor
;
7608 void *params
[2], *unboxed
;
7611 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeTypedArgument");
7613 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7615 params
[0] = mono_type_get_object (mono_domain_get (), t
);
7617 retval
= mono_object_new (mono_domain_get (), klass
);
7618 unboxed
= mono_object_unbox (retval
);
7619 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7625 create_cattr_named_arg (void *minfo
, MonoObject
*typedarg
)
7627 static MonoClass
*klass
;
7628 static MonoMethod
*ctor
;
7630 void *unboxed
, *params
[2];
7633 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "CustomAttributeNamedArgument");
7635 ctor
= mono_class_get_method_from_name (klass
, ".ctor", 2);
7638 params
[1] = typedarg
;
7639 retval
= mono_object_new (mono_domain_get (), klass
);
7640 unboxed
= mono_object_unbox (retval
);
7641 mono_runtime_invoke (ctor
, unboxed
, params
, NULL
);
7647 type_is_reference (MonoType
*type
)
7649 switch (type
->type
) {
7650 case MONO_TYPE_BOOLEAN
:
7651 case MONO_TYPE_CHAR
:
7664 case MONO_TYPE_VALUETYPE
:
7672 free_param_data (MonoMethodSignature
*sig
, void **params
) {
7674 for (i
= 0; i
< sig
->param_count
; ++i
) {
7675 if (!type_is_reference (sig
->params
[i
]))
7676 g_free (params
[i
]);
7681 * Find the field index in the metadata FieldDef table.
7684 find_field_index (MonoClass
*klass
, MonoClassField
*field
) {
7687 for (i
= 0; i
< klass
->field
.count
; ++i
) {
7688 if (field
== &klass
->fields
[i
])
7689 return klass
->field
.first
+ 1 + i
;
7695 * Find the property index in the metadata Property table.
7698 find_property_index (MonoClass
*klass
, MonoProperty
*property
) {
7701 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
7702 if (property
== &klass
->ext
->properties
[i
])
7703 return klass
->ext
->property
.first
+ 1 + i
;
7709 * Find the event index in the metadata Event table.
7712 find_event_index (MonoClass
*klass
, MonoEvent
*event
) {
7715 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
7716 if (event
== &klass
->ext
->events
[i
])
7717 return klass
->ext
->event
.first
+ 1 + i
;
7723 create_custom_attr (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
7725 const char *p
= (const char*)data
;
7727 guint32 i
, j
, num_named
;
7729 void *params_buf
[32];
7731 MonoMethodSignature
*sig
;
7733 mono_class_init (method
->klass
);
7736 attr
= mono_object_new (mono_domain_get (), method
->klass
);
7737 mono_runtime_invoke (method
, attr
, NULL
, NULL
);
7741 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
7744 /*g_print ("got attr %s\n", method->klass->name);*/
7746 sig
= mono_method_signature (method
);
7747 if (sig
->param_count
< 32)
7748 params
= params_buf
;
7750 /* Allocate using GC so it gets GC tracking */
7751 params
= mono_gc_alloc_fixed (sig
->param_count
* sizeof (void*), NULL
);
7755 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
7756 params
[i
] = load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
7760 attr
= mono_object_new (mono_domain_get (), method
->klass
);
7761 mono_runtime_invoke (method
, attr
, params
, NULL
);
7762 free_param_data (method
->signature
, params
);
7763 num_named
= read16 (named
);
7765 for (j
= 0; j
< num_named
; j
++) {
7767 char *name
, named_type
, data_type
;
7768 named_type
= *named
++;
7769 data_type
= *named
++; /* type of data */
7770 if (data_type
== MONO_TYPE_SZARRAY
)
7771 data_type
= *named
++;
7772 if (data_type
== MONO_TYPE_ENUM
) {
7775 type_len
= mono_metadata_decode_blob_size (named
, &named
);
7776 type_name
= g_malloc (type_len
+ 1);
7777 memcpy (type_name
, named
, type_len
);
7778 type_name
[type_len
] = 0;
7780 /* FIXME: lookup the type and check type consistency */
7783 name_len
= mono_metadata_decode_blob_size (named
, &named
);
7784 name
= g_malloc (name_len
+ 1);
7785 memcpy (name
, named
, name_len
);
7786 name
[name_len
] = 0;
7788 if (named_type
== 0x53) {
7789 MonoClassField
*field
= mono_class_get_field_from_name (mono_object_class (attr
), name
);
7790 void *val
= load_cattr_value (image
, field
->type
, named
, &named
);
7791 mono_field_set_value (attr
, field
, val
);
7792 if (!type_is_reference (field
->type
))
7794 } else if (named_type
== 0x54) {
7797 MonoType
*prop_type
;
7799 prop
= mono_class_get_property_from_name (mono_object_class (attr
), name
);
7800 /* can we have more that 1 arg in a custom attr named property? */
7801 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
7802 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
7803 pparams
[0] = load_cattr_value (image
, prop_type
, named
, &named
);
7804 mono_property_set_value (prop
, attr
, pparams
, NULL
);
7805 if (!type_is_reference (prop_type
))
7806 g_free (pparams
[0]);
7811 if (params
!= params_buf
)
7812 mono_gc_free_fixed (params
);
7818 create_custom_attr_data (MonoImage
*image
, MonoMethod
*method
, const guchar
*data
, guint32 len
)
7820 MonoArray
*typedargs
, *namedargs
;
7821 MonoClass
*attrklass
;
7822 static MonoMethod
*ctor
;
7825 const char *p
= (const char*)data
;
7827 guint32 i
, j
, num_named
;
7830 mono_class_init (method
->klass
);
7833 ctor
= mono_class_get_method_from_name (mono_defaults
.customattribute_data_class
, ".ctor", 3);
7835 domain
= mono_domain_get ();
7837 /* This is for Attributes with no parameters */
7838 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
7839 params
[0] = mono_method_get_object (domain
, method
, NULL
);
7840 params
[1] = params
[2] = NULL
;
7841 mono_runtime_invoke (method
, attr
, params
, NULL
);
7845 if (len
< 2 || read16 (p
) != 0x0001) /* Prolog */
7848 typedargs
= mono_array_new (domain
, mono_get_object_class (), mono_method_signature (method
)->param_count
);
7852 for (i
= 0; i
< mono_method_signature (method
)->param_count
; ++i
) {
7853 MonoObject
*obj
, *typedarg
;
7856 val
= load_cattr_value (image
, mono_method_signature (method
)->params
[i
], p
, &p
);
7857 obj
= type_is_reference (mono_method_signature (method
)->params
[i
]) ?
7858 val
: mono_value_box (domain
, mono_class_from_mono_type (mono_method_signature (method
)->params
[i
]), val
);
7859 typedarg
= create_cattr_typed_arg (mono_method_signature (method
)->params
[i
], obj
);
7860 mono_array_setref (typedargs
, i
, typedarg
);
7862 if (!type_is_reference (mono_method_signature (method
)->params
[i
]))
7867 num_named
= read16 (named
);
7868 namedargs
= mono_array_new (domain
, mono_get_object_class (), num_named
);
7870 attrklass
= method
->klass
;
7871 for (j
= 0; j
< num_named
; j
++) {
7873 char *name
, named_type
, data_type
;
7874 named_type
= *named
++;
7875 data_type
= *named
++; /* type of data */
7876 if (data_type
== MONO_TYPE_SZARRAY
)
7877 data_type
= *named
++;
7878 if (data_type
== MONO_TYPE_ENUM
) {
7881 type_len
= mono_metadata_decode_blob_size (named
, &named
);
7882 type_name
= g_malloc (type_len
+ 1);
7883 memcpy (type_name
, named
, type_len
);
7884 type_name
[type_len
] = 0;
7886 /* FIXME: lookup the type and check type consistency */
7889 name_len
= mono_metadata_decode_blob_size (named
, &named
);
7890 name
= g_malloc (name_len
+ 1);
7891 memcpy (name
, named
, name_len
);
7892 name
[name_len
] = 0;
7894 if (named_type
== 0x53) {
7895 MonoObject
*obj
, *typedarg
, *namedarg
;
7896 MonoClassField
*field
= mono_class_get_field_from_name (attrklass
, name
);
7897 void *minfo
, *val
= load_cattr_value (image
, field
->type
, named
, &named
);
7899 minfo
= mono_field_get_object (domain
, NULL
, field
);
7900 obj
= type_is_reference (field
->type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (field
->type
), val
);
7901 typedarg
= create_cattr_typed_arg (field
->type
, obj
);
7902 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
7903 mono_array_setref (namedargs
, j
, namedarg
);
7904 if (!type_is_reference (field
->type
))
7906 } else if (named_type
== 0x54) {
7907 MonoObject
*obj
, *typedarg
, *namedarg
;
7908 MonoType
*prop_type
;
7910 MonoProperty
*prop
= mono_class_get_property_from_name (attrklass
, name
);
7912 prop_type
= prop
->get
? mono_method_signature (prop
->get
)->ret
:
7913 mono_method_signature (prop
->set
)->params
[mono_method_signature (prop
->set
)->param_count
- 1];
7914 minfo
= mono_property_get_object (domain
, NULL
, prop
);
7915 val
= load_cattr_value (image
, prop_type
, named
, &named
);
7916 obj
= type_is_reference (prop_type
) ? val
: mono_value_box (domain
, mono_class_from_mono_type (prop_type
), val
);
7917 typedarg
= create_cattr_typed_arg (prop_type
, obj
);
7918 namedarg
= create_cattr_named_arg (minfo
, typedarg
);
7919 mono_array_setref (namedargs
, j
, namedarg
);
7920 if (!type_is_reference (prop_type
))
7925 attr
= mono_object_new (domain
, mono_defaults
.customattribute_data_class
);
7926 params
[0] = mono_method_get_object (domain
, method
, NULL
);
7927 params
[1] = typedargs
;
7928 params
[2] = namedargs
;
7929 mono_runtime_invoke (ctor
, attr
, params
, NULL
);
7934 mono_custom_attrs_construct (MonoCustomAttrInfo
*cinfo
)
7940 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, cinfo
->num_attrs
);
7941 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7942 if (!cinfo
->attrs
[i
].ctor
)
7943 /* The cattr type is not finished yet */
7944 /* We should include the type name but cinfo doesn't contain it */
7945 mono_raise_exception (mono_get_exception_type_load (NULL
, NULL
));
7946 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
7947 mono_array_setref (result
, i
, attr
);
7953 mono_custom_attrs_construct_by_type (MonoCustomAttrInfo
*cinfo
, MonoClass
*attr_klass
)
7960 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7961 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
))
7965 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, n
);
7967 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7968 if (mono_class_is_assignable_from (attr_klass
, cinfo
->attrs
[i
].ctor
->klass
)) {
7969 attr
= create_custom_attr (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
7970 mono_array_setref (result
, n
, attr
);
7978 mono_custom_attrs_data_construct (MonoCustomAttrInfo
*cinfo
)
7984 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, cinfo
->num_attrs
);
7985 for (i
= 0; i
< cinfo
->num_attrs
; ++i
) {
7986 attr
= create_custom_attr_data (cinfo
->image
, cinfo
->attrs
[i
].ctor
, cinfo
->attrs
[i
].data
, cinfo
->attrs
[i
].data_size
);
7987 mono_array_setref (result
, i
, attr
);
7993 * mono_custom_attrs_from_index:
7995 * Returns: NULL if no attributes are found or if a loading error occurs.
7998 mono_custom_attrs_from_index (MonoImage
*image
, guint32 idx
)
8000 guint32 mtoken
, i
, len
;
8001 guint32 cols
[MONO_CUSTOM_ATTR_SIZE
];
8003 MonoCustomAttrInfo
*ainfo
;
8004 GList
*tmp
, *list
= NULL
;
8007 ca
= &image
->tables
[MONO_TABLE_CUSTOMATTRIBUTE
];
8009 i
= mono_metadata_custom_attrs_from_index (image
, idx
);
8013 while (i
< ca
->rows
) {
8014 if (mono_metadata_decode_row_col (ca
, i
, MONO_CUSTOM_ATTR_PARENT
) != idx
)
8016 list
= g_list_prepend (list
, GUINT_TO_POINTER (i
));
8019 len
= g_list_length (list
);
8022 ainfo
= g_malloc0 (sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (len
- MONO_ZERO_LEN_ARRAY
));
8023 ainfo
->num_attrs
= len
;
8024 ainfo
->image
= image
;
8025 for (i
= 0, tmp
= list
; i
< len
; ++i
, tmp
= tmp
->next
) {
8026 mono_metadata_decode_row (ca
, GPOINTER_TO_UINT (tmp
->data
), cols
, MONO_CUSTOM_ATTR_SIZE
);
8027 mtoken
= cols
[MONO_CUSTOM_ATTR_TYPE
] >> MONO_CUSTOM_ATTR_TYPE_BITS
;
8028 switch (cols
[MONO_CUSTOM_ATTR_TYPE
] & MONO_CUSTOM_ATTR_TYPE_MASK
) {
8029 case MONO_CUSTOM_ATTR_TYPE_METHODDEF
:
8030 mtoken
|= MONO_TOKEN_METHOD_DEF
;
8032 case MONO_CUSTOM_ATTR_TYPE_MEMBERREF
:
8033 mtoken
|= MONO_TOKEN_MEMBER_REF
;
8036 g_error ("Unknown table for custom attr type %08x", cols
[MONO_CUSTOM_ATTR_TYPE
]);
8039 ainfo
->attrs
[i
].ctor
= mono_get_method (image
, mtoken
, NULL
);
8040 if (!ainfo
->attrs
[i
].ctor
) {
8041 g_warning ("Can't find custom attr constructor image: %s mtoken: 0x%08x", image
->name
, mtoken
);
8046 data
= mono_metadata_blob_heap (image
, cols
[MONO_CUSTOM_ATTR_VALUE
]);
8047 ainfo
->attrs
[i
].data_size
= mono_metadata_decode_value (data
, &data
);
8048 ainfo
->attrs
[i
].data
= (guchar
*)data
;
8056 mono_custom_attrs_from_method (MonoMethod
*method
)
8061 * An instantiated method has the same cattrs as the generic method definition.
8063 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8064 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8066 if (method
->is_inflated
)
8067 method
= ((MonoMethodInflated
*) method
)->declaring
;
8069 if (method
->dynamic
|| method
->klass
->image
->dynamic
)
8070 return lookup_custom_attr (method
->klass
->image
, method
);
8072 idx
= mono_method_get_index (method
);
8073 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8074 idx
|= MONO_CUSTOM_ATTR_METHODDEF
;
8075 return mono_custom_attrs_from_index (method
->klass
->image
, idx
);
8079 mono_custom_attrs_from_class (MonoClass
*klass
)
8083 if (klass
->generic_class
)
8084 klass
= klass
->generic_class
->container_class
;
8086 if (klass
->image
->dynamic
)
8087 return lookup_custom_attr (klass
->image
, klass
);
8089 if (klass
->byval_arg
.type
== MONO_TYPE_VAR
|| klass
->byval_arg
.type
== MONO_TYPE_MVAR
) {
8090 idx
= mono_metadata_token_index (klass
->sizes
.generic_param_token
);
8091 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8092 idx
|= MONO_CUSTOM_ATTR_GENERICPAR
;
8094 idx
= mono_metadata_token_index (klass
->type_token
);
8095 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8096 idx
|= MONO_CUSTOM_ATTR_TYPEDEF
;
8098 return mono_custom_attrs_from_index (klass
->image
, idx
);
8102 mono_custom_attrs_from_assembly (MonoAssembly
*assembly
)
8106 if (assembly
->image
->dynamic
)
8107 return lookup_custom_attr (assembly
->image
, assembly
);
8108 idx
= 1; /* there is only one assembly */
8109 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8110 idx
|= MONO_CUSTOM_ATTR_ASSEMBLY
;
8111 return mono_custom_attrs_from_index (assembly
->image
, idx
);
8114 static MonoCustomAttrInfo
*
8115 mono_custom_attrs_from_module (MonoImage
*image
)
8120 return lookup_custom_attr (image
, image
);
8121 idx
= 1; /* there is only one module */
8122 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8123 idx
|= MONO_CUSTOM_ATTR_MODULE
;
8124 return mono_custom_attrs_from_index (image
, idx
);
8128 mono_custom_attrs_from_property (MonoClass
*klass
, MonoProperty
*property
)
8132 if (klass
->image
->dynamic
) {
8133 property
= mono_metadata_get_corresponding_property_from_generic_type_definition (property
);
8134 return lookup_custom_attr (klass
->image
, property
);
8136 idx
= find_property_index (klass
, property
);
8137 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8138 idx
|= MONO_CUSTOM_ATTR_PROPERTY
;
8139 return mono_custom_attrs_from_index (klass
->image
, idx
);
8143 mono_custom_attrs_from_event (MonoClass
*klass
, MonoEvent
*event
)
8147 if (klass
->image
->dynamic
) {
8148 event
= mono_metadata_get_corresponding_event_from_generic_type_definition (event
);
8149 return lookup_custom_attr (klass
->image
, event
);
8151 idx
= find_event_index (klass
, event
);
8152 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8153 idx
|= MONO_CUSTOM_ATTR_EVENT
;
8154 return mono_custom_attrs_from_index (klass
->image
, idx
);
8158 mono_custom_attrs_from_field (MonoClass
*klass
, MonoClassField
*field
)
8161 if (klass
->image
->dynamic
) {
8162 field
= mono_metadata_get_corresponding_field_from_generic_type_definition (field
);
8163 return lookup_custom_attr (klass
->image
, field
);
8165 idx
= find_field_index (klass
, field
);
8166 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8167 idx
|= MONO_CUSTOM_ATTR_FIELDDEF
;
8168 return mono_custom_attrs_from_index (klass
->image
, idx
);
8172 mono_custom_attrs_from_param (MonoMethod
*method
, guint32 param
)
8175 guint32 i
, idx
, method_index
;
8176 guint32 param_list
, param_last
, param_pos
, found
;
8178 MonoReflectionMethodAux
*aux
;
8181 * An instantiated method has the same cattrs as the generic method definition.
8183 * LAMESPEC: The .NET SRE throws an exception for instantiations of generic method builders
8184 * Note that this stanza is not necessary for non-SRE types, but it's a micro-optimization
8186 if (method
->is_inflated
)
8187 method
= ((MonoMethodInflated
*) method
)->declaring
;
8189 if (method
->klass
->image
->dynamic
) {
8190 MonoCustomAttrInfo
*res
, *ainfo
;
8193 aux
= g_hash_table_lookup (((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
8194 if (!aux
|| !aux
->param_cattr
)
8197 /* Need to copy since it will be freed later */
8198 ainfo
= aux
->param_cattr
[param
];
8199 size
= sizeof (MonoCustomAttrInfo
) + sizeof (MonoCustomAttrEntry
) * (ainfo
->num_attrs
- MONO_ZERO_LEN_ARRAY
);
8200 res
= g_malloc0 (size
);
8201 memcpy (res
, ainfo
, size
);
8205 image
= method
->klass
->image
;
8206 method_index
= mono_method_get_index (method
);
8207 ca
= &image
->tables
[MONO_TABLE_METHOD
];
8209 param_list
= mono_metadata_decode_row_col (ca
, method_index
- 1, MONO_METHOD_PARAMLIST
);
8210 if (method_index
== ca
->rows
) {
8211 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8212 param_last
= ca
->rows
+ 1;
8214 param_last
= mono_metadata_decode_row_col (ca
, method_index
, MONO_METHOD_PARAMLIST
);
8215 ca
= &image
->tables
[MONO_TABLE_PARAM
];
8218 for (i
= param_list
; i
< param_last
; ++i
) {
8219 param_pos
= mono_metadata_decode_row_col (ca
, i
- 1, MONO_PARAM_SEQUENCE
);
8220 if (param_pos
== param
) {
8228 idx
<<= MONO_CUSTOM_ATTR_BITS
;
8229 idx
|= MONO_CUSTOM_ATTR_PARAMDEF
;
8230 return mono_custom_attrs_from_index (image
, idx
);
8234 mono_custom_attrs_has_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8238 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8239 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8240 if (mono_class_has_parent (klass
, attr_klass
) || (MONO_CLASS_IS_INTERFACE (attr_klass
) && mono_class_is_assignable_from (attr_klass
, klass
)))
8247 mono_custom_attrs_get_attr (MonoCustomAttrInfo
*ainfo
, MonoClass
*attr_klass
)
8254 for (i
= 0; i
< ainfo
->num_attrs
; ++i
) {
8255 klass
= ainfo
->attrs
[i
].ctor
->klass
;
8256 if (mono_class_has_parent (klass
, attr_klass
)) {
8261 if (attr_index
== -1)
8264 attrs
= mono_custom_attrs_construct (ainfo
);
8266 return mono_array_get (attrs
, MonoObject
*, attr_index
);
8272 * mono_reflection_get_custom_attrs_info:
8273 * @obj: a reflection object handle
8275 * Return the custom attribute info for attributes defined for the
8276 * reflection handle @obj. The objects.
8278 * FIXME this function leaks like a sieve for SRE objects.
8281 mono_reflection_get_custom_attrs_info (MonoObject
*obj
)
8284 MonoCustomAttrInfo
*cinfo
= NULL
;
8286 klass
= obj
->vtable
->klass
;
8287 if (klass
== mono_defaults
.monotype_class
) {
8288 MonoReflectionType
*rtype
= (MonoReflectionType
*)obj
;
8289 klass
= mono_class_from_mono_type (rtype
->type
);
8290 cinfo
= mono_custom_attrs_from_class (klass
);
8291 } else if (strcmp ("Assembly", klass
->name
) == 0) {
8292 MonoReflectionAssembly
*rassembly
= (MonoReflectionAssembly
*)obj
;
8293 cinfo
= mono_custom_attrs_from_assembly (rassembly
->assembly
);
8294 } else if (strcmp ("Module", klass
->name
) == 0) {
8295 MonoReflectionModule
*module
= (MonoReflectionModule
*)obj
;
8296 cinfo
= mono_custom_attrs_from_module (module
->image
);
8297 } else if (strcmp ("MonoProperty", klass
->name
) == 0) {
8298 MonoReflectionProperty
*rprop
= (MonoReflectionProperty
*)obj
;
8299 cinfo
= mono_custom_attrs_from_property (rprop
->property
->parent
, rprop
->property
);
8300 } else if (strcmp ("MonoEvent", klass
->name
) == 0) {
8301 MonoReflectionMonoEvent
*revent
= (MonoReflectionMonoEvent
*)obj
;
8302 cinfo
= mono_custom_attrs_from_event (revent
->event
->parent
, revent
->event
);
8303 } else if (strcmp ("MonoField", klass
->name
) == 0) {
8304 MonoReflectionField
*rfield
= (MonoReflectionField
*)obj
;
8305 cinfo
= mono_custom_attrs_from_field (rfield
->field
->parent
, rfield
->field
);
8306 } else if ((strcmp ("MonoMethod", klass
->name
) == 0) || (strcmp ("MonoCMethod", klass
->name
) == 0)) {
8307 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8308 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8309 } else if ((strcmp ("MonoGenericMethod", klass
->name
) == 0) || (strcmp ("MonoGenericCMethod", klass
->name
) == 0)) {
8310 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)obj
;
8311 cinfo
= mono_custom_attrs_from_method (rmethod
->method
);
8312 } else if (strcmp ("ParameterInfo", klass
->name
) == 0) {
8313 MonoReflectionParameter
*param
= (MonoReflectionParameter
*)obj
;
8314 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
8315 cinfo
= mono_custom_attrs_from_param (rmethod
->method
, param
->PositionImpl
+ 1);
8316 } else if (strcmp ("AssemblyBuilder", klass
->name
) == 0) {
8317 MonoReflectionAssemblyBuilder
*assemblyb
= (MonoReflectionAssemblyBuilder
*)obj
;
8318 cinfo
= mono_custom_attrs_from_builders (NULL
, assemblyb
->assembly
.assembly
->image
, assemblyb
->cattrs
);
8319 } else if (strcmp ("TypeBuilder", klass
->name
) == 0) {
8320 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
8321 cinfo
= mono_custom_attrs_from_builders (NULL
, &tb
->module
->dynamic_image
->image
, tb
->cattrs
);
8322 } else if (strcmp ("ModuleBuilder", klass
->name
) == 0) {
8323 MonoReflectionModuleBuilder
*mb
= (MonoReflectionModuleBuilder
*)obj
;
8324 cinfo
= mono_custom_attrs_from_builders (NULL
, &mb
->dynamic_image
->image
, mb
->cattrs
);
8325 } else if (strcmp ("ConstructorBuilder", klass
->name
) == 0) {
8326 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
8327 cinfo
= mono_custom_attrs_from_builders (NULL
, cb
->mhandle
->klass
->image
, cb
->cattrs
);
8328 } else if (strcmp ("MethodBuilder", klass
->name
) == 0) {
8329 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
8330 cinfo
= mono_custom_attrs_from_builders (NULL
, mb
->mhandle
->klass
->image
, mb
->cattrs
);
8331 } else if (strcmp ("FieldBuilder", klass
->name
) == 0) {
8332 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
8333 cinfo
= mono_custom_attrs_from_builders (NULL
, &((MonoReflectionTypeBuilder
*)fb
->typeb
)->module
->dynamic_image
->image
, fb
->cattrs
);
8334 } else if (strcmp ("MonoGenericClass", klass
->name
) == 0) {
8335 MonoReflectionGenericClass
*gclass
= (MonoReflectionGenericClass
*)obj
;
8336 cinfo
= mono_reflection_get_custom_attrs_info ((MonoObject
*)gclass
->generic_type
);
8337 } else { /* handle other types here... */
8338 g_error ("get custom attrs not yet supported for %s", klass
->name
);
8345 * mono_reflection_get_custom_attrs_by_type:
8346 * @obj: a reflection object handle
8348 * Return an array with all the custom attributes defined of the
8349 * reflection handle @obj. If @attr_klass is non-NULL, only custom attributes
8350 * of that type are returned. The objects are fully build. Return NULL if a loading error
8354 mono_reflection_get_custom_attrs_by_type (MonoObject
*obj
, MonoClass
*attr_klass
)
8357 MonoCustomAttrInfo
*cinfo
;
8359 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8362 result
= mono_custom_attrs_construct_by_type (cinfo
, attr_klass
);
8364 result
= mono_custom_attrs_construct (cinfo
);
8366 mono_custom_attrs_free (cinfo
);
8368 if (mono_loader_get_last_error ())
8370 result
= mono_array_new_cached (mono_domain_get (), mono_defaults
.attribute_class
, 0);
8377 * mono_reflection_get_custom_attrs:
8378 * @obj: a reflection object handle
8380 * Return an array with all the custom attributes defined of the
8381 * reflection handle @obj. The objects are fully build. Return NULL if a loading error
8385 mono_reflection_get_custom_attrs (MonoObject
*obj
)
8387 return mono_reflection_get_custom_attrs_by_type (obj
, NULL
);
8391 * mono_reflection_get_custom_attrs_data:
8392 * @obj: a reflection obj handle
8394 * Returns an array of System.Reflection.CustomAttributeData,
8395 * which include information about attributes reflected on
8396 * types loaded using the Reflection Only methods
8399 mono_reflection_get_custom_attrs_data (MonoObject
*obj
)
8402 MonoCustomAttrInfo
*cinfo
;
8404 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
8406 result
= mono_custom_attrs_data_construct (cinfo
);
8408 mono_custom_attrs_free (cinfo
);
8410 result
= mono_array_new (mono_domain_get (), mono_defaults
.customattribute_data_class
, 0);
8415 static MonoReflectionType
*
8416 mono_reflection_type_get_underlying_system_type (MonoReflectionType
* t
)
8418 MonoMethod
*method_get_underlying_system_type
;
8420 method_get_underlying_system_type
= mono_object_get_virtual_method ((MonoObject
*) t
,
8421 mono_class_get_method_from_name (mono_object_class (t
),
8422 "get_UnderlyingSystemType",
8424 return (MonoReflectionType
*) mono_runtime_invoke (method_get_underlying_system_type
, t
, NULL
, NULL
);
8428 mono_reflection_type_get_handle (MonoReflectionType
* t
)
8433 t
= mono_reflection_type_get_underlying_system_type (t
);
8441 * LOCKING: Assumes the loader lock is held.
8443 static MonoMethodSignature
*
8444 parameters_to_signature (MonoImage
*image
, MonoArray
*parameters
) {
8445 MonoMethodSignature
*sig
;
8448 count
= parameters
? mono_array_length (parameters
): 0;
8450 sig
= image_g_malloc0 (image
, sizeof (MonoMethodSignature
) + sizeof (MonoType
*) * count
);
8451 sig
->param_count
= count
;
8452 sig
->sentinelpos
= -1; /* FIXME */
8453 for (i
= 0; i
< count
; ++i
) {
8454 MonoReflectionType
*pt
= mono_type_array_get (parameters
, i
);
8455 sig
->params
[i
] = mono_reflection_type_get_handle (pt
);
8461 * LOCKING: Assumes the loader lock is held.
8463 static MonoMethodSignature
*
8464 ctor_builder_to_signature (MonoImage
*image
, MonoReflectionCtorBuilder
*ctor
) {
8465 MonoMethodSignature
*sig
;
8467 sig
= parameters_to_signature (image
, ctor
->parameters
);
8468 sig
->hasthis
= ctor
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8469 sig
->ret
= &mono_defaults
.void_class
->byval_arg
;
8474 * LOCKING: Assumes the loader lock is held.
8476 static MonoMethodSignature
*
8477 method_builder_to_signature (MonoImage
*image
, MonoReflectionMethodBuilder
*method
) {
8478 MonoMethodSignature
*sig
;
8480 sig
= parameters_to_signature (image
, method
->parameters
);
8481 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8482 sig
->ret
= method
->rtype
? monotype_cast (method
->rtype
)->type
: &mono_defaults
.void_class
->byval_arg
;
8483 sig
->generic_param_count
= method
->generic_params
? mono_array_length (method
->generic_params
) : 0;
8487 static MonoMethodSignature
*
8488 dynamic_method_to_signature (MonoReflectionDynamicMethod
*method
) {
8489 MonoMethodSignature
*sig
;
8491 sig
= parameters_to_signature (NULL
, method
->parameters
);
8492 sig
->hasthis
= method
->attrs
& METHOD_ATTRIBUTE_STATIC
? 0: 1;
8493 sig
->ret
= method
->rtype
? method
->rtype
->type
: &mono_defaults
.void_class
->byval_arg
;
8494 sig
->generic_param_count
= 0;
8499 get_prop_name_and_type (MonoObject
*prop
, char **name
, MonoType
**type
)
8501 MonoClass
*klass
= mono_object_class (prop
);
8502 if (strcmp (klass
->name
, "PropertyBuilder") == 0) {
8503 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*)prop
;
8504 *name
= mono_string_to_utf8 (pb
->name
);
8505 *type
= monotype_cast (pb
->type
)->type
;
8507 MonoReflectionProperty
*p
= (MonoReflectionProperty
*)prop
;
8508 *name
= g_strdup (p
->property
->name
);
8509 if (p
->property
->get
)
8510 *type
= mono_method_signature (p
->property
->get
)->ret
;
8512 *type
= mono_method_signature (p
->property
->set
)->params
[mono_method_signature (p
->property
->set
)->param_count
- 1];
8517 get_field_name_and_type (MonoObject
*field
, char **name
, MonoType
**type
)
8519 MonoClass
*klass
= mono_object_class (field
);
8520 if (strcmp (klass
->name
, "FieldBuilder") == 0) {
8521 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)field
;
8522 *name
= mono_string_to_utf8 (fb
->name
);
8523 *type
= monotype_cast (fb
->type
)->type
;
8525 MonoReflectionField
*f
= (MonoReflectionField
*)field
;
8526 *name
= g_strdup (mono_field_get_name (f
->field
));
8527 *type
= f
->field
->type
;
8532 * Encode a value in a custom attribute stream of bytes.
8533 * The value to encode is either supplied as an object in argument val
8534 * (valuetypes are boxed), or as a pointer to the data in the
8536 * @type represents the type of the value
8537 * @buffer is the start of the buffer
8538 * @p the current position in the buffer
8539 * @buflen contains the size of the buffer and is used to return the new buffer size
8540 * if this needs to be realloced.
8541 * @retbuffer and @retp return the start and the position of the buffer
8544 encode_cattr_value (MonoAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, MonoObject
*arg
, char *argval
)
8546 MonoTypeEnum simple_type
;
8548 if ((p
-buffer
) + 10 >= *buflen
) {
8551 newbuf
= g_realloc (buffer
, *buflen
);
8552 p
= newbuf
+ (p
-buffer
);
8556 argval
= ((char*)arg
+ sizeof (MonoObject
));
8557 simple_type
= type
->type
;
8559 switch (simple_type
) {
8560 case MONO_TYPE_BOOLEAN
:
8565 case MONO_TYPE_CHAR
:
8568 swap_with_size (p
, argval
, 2, 1);
8574 swap_with_size (p
, argval
, 4, 1);
8578 #if defined(ARM_FPU_FPA) && G_BYTE_ORDER == G_LITTLE_ENDIAN
8588 swap_with_size (p
, argval
, 8, 1);
8594 swap_with_size (p
, argval
, 8, 1);
8597 case MONO_TYPE_VALUETYPE
:
8598 if (type
->data
.klass
->enumtype
) {
8599 simple_type
= mono_class_enum_basetype (type
->data
.klass
)->type
;
8602 g_warning ("generic valutype %s not handled in custom attr value decoding", type
->data
.klass
->name
);
8605 case MONO_TYPE_STRING
: {
8612 str
= mono_string_to_utf8 ((MonoString
*)arg
);
8613 slen
= strlen (str
);
8614 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8618 newbuf
= g_realloc (buffer
, *buflen
);
8619 p
= newbuf
+ (p
-buffer
);
8622 mono_metadata_encode_value (slen
, p
, &p
);
8623 memcpy (p
, str
, slen
);
8628 case MONO_TYPE_CLASS
: {
8636 k
= mono_object_class (arg
);
8637 if (!mono_object_isinst (arg
, mono_defaults
.monotype_class
) &&
8638 (strcmp (k
->name
, "TypeBuilder") || strcmp (k
->name_space
, "System.Reflection.Emit"))) {
8639 MonoReflectionType
* rt
= mono_reflection_type_get_underlying_system_type ((MonoReflectionType
*) arg
);
8642 if (rt
&& (rtc
= mono_object_class (rt
)) &&
8643 (mono_object_isinst ((MonoObject
*) rt
, mono_defaults
.monotype_class
) ||
8644 !strcmp (rtc
->name
, "TypeBuilder") || !strcmp (rtc
->name_space
, "System.Reflection.Emit"))) {
8645 arg
= (MonoObject
*) rt
;
8648 g_error ("Only System.Type allowed, not %s.%s", k
->name_space
, k
->name
);
8651 str
= type_get_qualified_name (((MonoReflectionType
*)arg
)->type
, NULL
);
8652 slen
= strlen (str
);
8653 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8657 newbuf
= g_realloc (buffer
, *buflen
);
8658 p
= newbuf
+ (p
-buffer
);
8661 mono_metadata_encode_value (slen
, p
, &p
);
8662 memcpy (p
, str
, slen
);
8667 case MONO_TYPE_SZARRAY
: {
8669 MonoClass
*eclass
, *arg_eclass
;
8672 *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff; *p
++ = 0xff;
8675 len
= mono_array_length ((MonoArray
*)arg
);
8677 *p
++ = (len
>> 8) & 0xff;
8678 *p
++ = (len
>> 16) & 0xff;
8679 *p
++ = (len
>> 24) & 0xff;
8681 *retbuffer
= buffer
;
8682 eclass
= type
->data
.klass
;
8683 arg_eclass
= mono_object_class (arg
)->element_class
;
8686 /* Happens when we are called from the MONO_TYPE_OBJECT case below */
8687 eclass
= mono_defaults
.object_class
;
8689 if (eclass
== mono_defaults
.object_class
&& arg_eclass
->valuetype
) {
8690 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
8691 int elsize
= mono_class_array_element_size (arg_eclass
);
8692 for (i
= 0; i
< len
; ++i
) {
8693 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &arg_eclass
->byval_arg
, NULL
, elptr
);
8696 } else if (eclass
->valuetype
&& arg_eclass
->valuetype
) {
8697 char *elptr
= mono_array_addr ((MonoArray
*)arg
, char, 0);
8698 int elsize
= mono_class_array_element_size (eclass
);
8699 for (i
= 0; i
< len
; ++i
) {
8700 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, NULL
, elptr
);
8704 for (i
= 0; i
< len
; ++i
) {
8705 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &eclass
->byval_arg
, mono_array_get ((MonoArray
*)arg
, MonoObject
*, i
), NULL
);
8710 case MONO_TYPE_OBJECT
: {
8716 * The parameter type is 'object' but the type of the actual
8717 * argument is not. So we have to add type information to the blob
8718 * too. This is completely undocumented in the spec.
8722 *p
++ = MONO_TYPE_STRING
; // It's same hack as MS uses
8727 klass
= mono_object_class (arg
);
8729 if (mono_object_isinst (arg
, mono_defaults
.systemtype_class
)) {
8732 } else if (klass
->enumtype
) {
8734 } else if (klass
== mono_defaults
.string_class
) {
8735 simple_type
= MONO_TYPE_STRING
;
8738 } else if (klass
->rank
== 1) {
8740 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_OBJECT
)
8741 /* See Partition II, Appendix B3 */
8744 *p
++ = klass
->element_class
->byval_arg
.type
;
8745 encode_cattr_value (assembly
, buffer
, p
, &buffer
, &p
, buflen
, &klass
->byval_arg
, arg
, NULL
);
8747 } else if (klass
->byval_arg
.type
>= MONO_TYPE_BOOLEAN
&& klass
->byval_arg
.type
<= MONO_TYPE_R8
) {
8748 *p
++ = simple_type
= klass
->byval_arg
.type
;
8751 g_error ("unhandled type in custom attr");
8753 str
= type_get_qualified_name (mono_class_get_type(klass
), NULL
);
8754 slen
= strlen (str
);
8755 if ((p
-buffer
) + 10 + slen
>= *buflen
) {
8759 newbuf
= g_realloc (buffer
, *buflen
);
8760 p
= newbuf
+ (p
-buffer
);
8763 mono_metadata_encode_value (slen
, p
, &p
);
8764 memcpy (p
, str
, slen
);
8767 simple_type
= mono_class_enum_basetype (klass
)->type
;
8771 g_error ("type 0x%02x not yet supported in custom attr encoder", simple_type
);
8774 *retbuffer
= buffer
;
8778 encode_field_or_prop_type (MonoType
*type
, char *p
, char **retp
)
8780 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
8781 char *str
= type_get_qualified_name (type
, NULL
);
8782 int slen
= strlen (str
);
8786 * This seems to be optional...
8789 mono_metadata_encode_value (slen
, p
, &p
);
8790 memcpy (p
, str
, slen
);
8793 } else if (type
->type
== MONO_TYPE_OBJECT
) {
8795 } else if (type
->type
== MONO_TYPE_CLASS
) {
8796 /* it should be a type: encode_cattr_value () has the check */
8799 mono_metadata_encode_value (type
->type
, p
, &p
);
8800 if (type
->type
== MONO_TYPE_SZARRAY
)
8801 /* See the examples in Partition VI, Annex B */
8802 encode_field_or_prop_type (&type
->data
.klass
->byval_arg
, p
, &p
);
8809 encode_named_val (MonoReflectionAssembly
*assembly
, char *buffer
, char *p
, char **retbuffer
, char **retp
, guint32
*buflen
, MonoType
*type
, char *name
, MonoObject
*value
)
8812 /* Preallocate a large enough buffer */
8813 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
) {
8814 char *str
= type_get_qualified_name (type
, NULL
);
8817 } else if (type
->type
== MONO_TYPE_SZARRAY
&& type
->data
.klass
->enumtype
) {
8818 char *str
= type_get_qualified_name (&type
->data
.klass
->byval_arg
, NULL
);
8824 len
+= strlen (name
);
8826 if ((p
-buffer
) + 20 + len
>= *buflen
) {
8830 newbuf
= g_realloc (buffer
, *buflen
);
8831 p
= newbuf
+ (p
-buffer
);
8835 encode_field_or_prop_type (type
, p
, &p
);
8837 len
= strlen (name
);
8838 mono_metadata_encode_value (len
, p
, &p
);
8839 memcpy (p
, name
, len
);
8841 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, buflen
, type
, value
, NULL
);
8843 *retbuffer
= buffer
;
8846 #ifndef DISABLE_REFLECTION_EMIT
8849 * mono_reflection_get_custom_attrs_blob:
8850 * @ctor: custom attribute constructor
8851 * @ctorArgs: arguments o the constructor
8857 * Creates the blob of data that needs to be saved in the metadata and that represents
8858 * the custom attributed described by @ctor, @ctorArgs etc.
8859 * Returns: a Byte array representing the blob of data.
8862 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
8865 MonoMethodSignature
*sig
;
8870 MONO_ARCH_SAVE_REGS
;
8872 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod")) {
8873 /* sig is freed later so allocate it in the heap */
8874 sig
= ctor_builder_to_signature (NULL
, (MonoReflectionCtorBuilder
*)ctor
);
8876 sig
= mono_method_signature (((MonoReflectionMethod
*)ctor
)->method
);
8879 g_assert (mono_array_length (ctorArgs
) == sig
->param_count
);
8881 p
= buffer
= g_malloc (buflen
);
8882 /* write the prolog */
8885 for (i
= 0; i
< sig
->param_count
; ++i
) {
8886 arg
= mono_array_get (ctorArgs
, MonoObject
*, i
);
8887 encode_cattr_value (assembly
->assembly
, buffer
, p
, &buffer
, &p
, &buflen
, sig
->params
[i
], arg
, NULL
);
8891 i
+= mono_array_length (properties
);
8893 i
+= mono_array_length (fields
);
8895 *p
++ = (i
>> 8) & 0xff;
8898 for (i
= 0; i
< mono_array_length (properties
); ++i
) {
8902 prop
= mono_array_get (properties
, gpointer
, i
);
8903 get_prop_name_and_type (prop
, &pname
, &ptype
);
8904 *p
++ = 0x54; /* PROPERTY signature */
8905 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ptype
, pname
, (MonoObject
*)mono_array_get (propValues
, gpointer
, i
));
8912 for (i
= 0; i
< mono_array_length (fields
); ++i
) {
8916 field
= mono_array_get (fields
, gpointer
, i
);
8917 get_field_name_and_type (field
, &fname
, &ftype
);
8918 *p
++ = 0x53; /* FIELD signature */
8919 encode_named_val (assembly
, buffer
, p
, &buffer
, &p
, &buflen
, ftype
, fname
, (MonoObject
*)mono_array_get (fieldValues
, gpointer
, i
));
8924 g_assert (p
- buffer
<= buflen
);
8925 buflen
= p
- buffer
;
8926 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
8927 p
= mono_array_addr (result
, char, 0);
8928 memcpy (p
, buffer
, buflen
);
8930 if (strcmp (ctor
->vtable
->klass
->name
, "MonoCMethod"))
8936 * mono_reflection_setup_internal_class:
8937 * @tb: a TypeBuilder object
8939 * Creates a MonoClass that represents the TypeBuilder.
8940 * This is a trick that lets us simplify a lot of reflection code
8941 * (and will allow us to support Build and Run assemblies easier).
8944 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
8946 MonoClass
*klass
, *parent
;
8948 MONO_ARCH_SAVE_REGS
;
8950 CHECK_MONOTYPE (tb
->parent
);
8952 mono_loader_lock ();
8955 /* check so we can compile corlib correctly */
8956 if (strcmp (mono_object_class (tb
->parent
)->name
, "TypeBuilder") == 0) {
8957 /* mono_class_setup_mono_type () guaranteess type->data.klass is valid */
8958 parent
= monotype_cast (tb
->parent
)->type
->data
.klass
;
8960 parent
= my_mono_class_from_mono_type (monotype_cast (tb
->parent
)->type
);
8966 /* the type has already being created: it means we just have to change the parent */
8967 if (tb
->type
.type
) {
8968 klass
= mono_class_from_mono_type (tb
->type
.type
);
8969 klass
->parent
= NULL
;
8970 /* fool mono_class_setup_parent */
8971 klass
->supertypes
= NULL
;
8972 mono_class_setup_parent (klass
, parent
);
8973 mono_class_setup_mono_type (klass
);
8974 mono_loader_unlock ();
8978 klass
= mono_image_alloc0 (&tb
->module
->dynamic_image
->image
, sizeof (MonoClass
));
8980 klass
->image
= &tb
->module
->dynamic_image
->image
;
8982 klass
->inited
= 1; /* we lie to the runtime */
8983 klass
->name
= mono_string_to_utf8_image (klass
->image
, tb
->name
);
8984 klass
->name_space
= mono_string_to_utf8_image (klass
->image
, tb
->nspace
);
8985 klass
->type_token
= MONO_TOKEN_TYPE_DEF
| tb
->table_idx
;
8986 klass
->flags
= tb
->attrs
;
8988 mono_profiler_class_event (klass
, MONO_PROFILE_START_LOAD
);
8990 klass
->element_class
= klass
;
8992 MOVING_GC_REGISTER (&klass
->reflection_info
);
8993 klass
->reflection_info
= tb
;
8995 /* Put into cache so mono_class_get () will find it */
8996 mono_image_add_to_name_cache (klass
->image
, klass
->name_space
, klass
->name
, tb
->table_idx
);
8998 mono_g_hash_table_insert (tb
->module
->dynamic_image
->tokens
,
8999 GUINT_TO_POINTER (MONO_TOKEN_TYPE_DEF
| tb
->table_idx
), tb
);
9001 if (parent
!= NULL
) {
9002 mono_class_setup_parent (klass
, parent
);
9003 } else if (strcmp (klass
->name
, "Object") == 0 && strcmp (klass
->name_space
, "System") == 0) {
9004 const char *old_n
= klass
->name
;
9005 /* trick to get relative numbering right when compiling corlib */
9006 klass
->name
= "BuildingObject";
9007 mono_class_setup_parent (klass
, mono_defaults
.object_class
);
9008 klass
->name
= old_n
;
9011 if ((!strcmp (klass
->name
, "ValueType") && !strcmp (klass
->name_space
, "System")) ||
9012 (!strcmp (klass
->name
, "Object") && !strcmp (klass
->name_space
, "System")) ||
9013 (!strcmp (klass
->name
, "Enum") && !strcmp (klass
->name_space
, "System"))) {
9014 klass
->instance_size
= sizeof (MonoObject
);
9015 klass
->size_inited
= 1;
9016 mono_class_setup_vtable_general (klass
, NULL
, 0);
9019 mono_class_setup_mono_type (klass
);
9021 mono_class_setup_supertypes (klass
);
9024 * FIXME: handle interfaces.
9027 tb
->type
.type
= &klass
->byval_arg
;
9029 if (tb
->nesting_type
) {
9030 g_assert (tb
->nesting_type
->type
);
9031 klass
->nested_in
= mono_class_from_mono_type (tb
->nesting_type
->type
);
9034 /*g_print ("setup %s as %s (%p)\n", klass->name, ((MonoObject*)tb)->vtable->klass->name, tb);*/
9036 mono_profiler_class_loaded (klass
, MONO_PROFILE_OK
);
9038 mono_loader_unlock ();
9042 * mono_reflection_setup_generic_class:
9043 * @tb: a TypeBuilder object
9045 * Setup the generic class before adding the first generic parameter.
9048 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
9053 * mono_reflection_create_generic_class:
9054 * @tb: a TypeBuilder object
9056 * Creates the generic class after all generic parameters have been added.
9059 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
9064 MONO_ARCH_SAVE_REGS
;
9066 klass
= my_mono_class_from_mono_type (tb
->type
.type
);
9068 count
= tb
->generic_params
? mono_array_length (tb
->generic_params
) : 0;
9070 if (klass
->generic_container
|| (count
== 0))
9073 g_assert (tb
->generic_container
&& (tb
->generic_container
->owner
.klass
== klass
));
9075 klass
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
9077 klass
->generic_container
->owner
.klass
= klass
;
9078 klass
->generic_container
->type_argc
= count
;
9079 klass
->generic_container
->type_params
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericParam
) * count
);
9081 klass
->is_generic
= 1;
9083 for (i
= 0; i
< count
; i
++) {
9084 MonoReflectionGenericParam
*gparam
= mono_array_get (tb
->generic_params
, gpointer
, i
);
9085 klass
->generic_container
->type_params
[i
] = *gparam
->type
.type
->data
.generic_param
;
9086 /*Make sure we are a diferent type instance */
9087 klass
->generic_container
->type_params
[i
].owner
= klass
->generic_container
;
9088 klass
->generic_container
->type_params
[i
].pklass
= NULL
;
9090 g_assert (klass
->generic_container
->type_params
[i
].owner
);
9093 klass
->generic_container
->context
.class_inst
= mono_get_shared_generic_inst (klass
->generic_container
);
9097 * mono_reflection_create_internal_class:
9098 * @tb: a TypeBuilder object
9100 * Actually create the MonoClass that is associated with the TypeBuilder.
9103 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
9107 MONO_ARCH_SAVE_REGS
;
9109 klass
= my_mono_class_from_mono_type (tb
->type
.type
);
9111 mono_loader_lock ();
9112 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) == NULL
) {
9113 MonoReflectionFieldBuilder
*fb
;
9115 MonoType
*enum_basetype
;
9117 g_assert (tb
->fields
!= NULL
);
9118 g_assert (mono_array_length (tb
->fields
) >= 1);
9120 fb
= mono_array_get (tb
->fields
, MonoReflectionFieldBuilder
*, 0);
9122 if (!mono_type_is_valid_enum_basetype (monotype_cast (fb
->type
)->type
)) {
9123 mono_loader_unlock ();
9127 enum_basetype
= monotype_cast (fb
->type
)->type
;
9128 klass
->element_class
= my_mono_class_from_mono_type (enum_basetype
);
9129 if (!klass
->element_class
)
9130 klass
->element_class
= mono_class_from_mono_type (enum_basetype
);
9133 * get the element_class from the current corlib.
9135 ec
= default_class_from_mono_type (enum_basetype
);
9136 klass
->instance_size
= ec
->instance_size
;
9137 klass
->size_inited
= 1;
9139 * this is almost safe to do with enums and it's needed to be able
9140 * to create objects of the enum type (for use in SetConstant).
9142 /* FIXME: Does this mean enums can't have method overrides ? */
9143 mono_class_setup_vtable_general (klass
, NULL
, 0);
9145 mono_loader_unlock ();
9148 #endif /* DISABLE_REFLECTION_EMIT */
9150 static MonoMarshalSpec
*
9151 mono_marshal_spec_from_builder (MonoImage
*image
, MonoAssembly
*assembly
,
9152 MonoReflectionMarshal
*minfo
)
9154 MonoMarshalSpec
*res
;
9156 res
= image_g_new0 (image
, MonoMarshalSpec
, 1);
9157 res
->native
= minfo
->type
;
9159 switch (minfo
->type
) {
9160 case MONO_NATIVE_LPARRAY
:
9161 res
->data
.array_data
.elem_type
= minfo
->eltype
;
9162 if (minfo
->has_size
) {
9163 res
->data
.array_data
.param_num
= minfo
->param_num
;
9164 res
->data
.array_data
.num_elem
= minfo
->count
;
9165 res
->data
.array_data
.elem_mult
= minfo
->param_num
== -1 ? 0 : 1;
9168 res
->data
.array_data
.param_num
= -1;
9169 res
->data
.array_data
.num_elem
= -1;
9170 res
->data
.array_data
.elem_mult
= -1;
9174 case MONO_NATIVE_BYVALTSTR
:
9175 case MONO_NATIVE_BYVALARRAY
:
9176 res
->data
.array_data
.num_elem
= minfo
->count
;
9179 case MONO_NATIVE_CUSTOM
:
9180 if (minfo
->marshaltyperef
)
9181 res
->data
.custom_data
.custom_name
=
9182 type_get_fully_qualified_name (monotype_cast (minfo
->marshaltyperef
)->type
);
9184 res
->data
.custom_data
.cookie
= mono_string_to_utf8 (minfo
->mcookie
);
9194 MonoReflectionMarshal
*
9195 mono_reflection_marshal_from_marshal_spec (MonoDomain
*domain
, MonoClass
*klass
,
9196 MonoMarshalSpec
*spec
)
9198 static MonoClass
*System_Reflection_Emit_UnmanagedMarshalClass
;
9199 MonoReflectionMarshal
*minfo
;
9202 if (!System_Reflection_Emit_UnmanagedMarshalClass
) {
9203 System_Reflection_Emit_UnmanagedMarshalClass
= mono_class_from_name (
9204 mono_defaults
.corlib
, "System.Reflection.Emit", "UnmanagedMarshal");
9205 g_assert (System_Reflection_Emit_UnmanagedMarshalClass
);
9208 minfo
= (MonoReflectionMarshal
*)mono_object_new (domain
, System_Reflection_Emit_UnmanagedMarshalClass
);
9209 minfo
->type
= spec
->native
;
9211 switch (minfo
->type
) {
9212 case MONO_NATIVE_LPARRAY
:
9213 minfo
->eltype
= spec
->data
.array_data
.elem_type
;
9214 minfo
->count
= spec
->data
.array_data
.num_elem
;
9215 minfo
->param_num
= spec
->data
.array_data
.param_num
;
9218 case MONO_NATIVE_BYVALTSTR
:
9219 case MONO_NATIVE_BYVALARRAY
:
9220 minfo
->count
= spec
->data
.array_data
.num_elem
;
9223 case MONO_NATIVE_CUSTOM
:
9224 if (spec
->data
.custom_data
.custom_name
) {
9225 mtype
= mono_reflection_type_from_name (spec
->data
.custom_data
.custom_name
, klass
->image
);
9227 MONO_OBJECT_SETREF (minfo
, marshaltyperef
, mono_type_get_object (domain
, mtype
));
9229 MONO_OBJECT_SETREF (minfo
, marshaltype
, mono_string_new (domain
, spec
->data
.custom_data
.custom_name
));
9231 if (spec
->data
.custom_data
.cookie
)
9232 MONO_OBJECT_SETREF (minfo
, mcookie
, mono_string_new (domain
, spec
->data
.custom_data
.cookie
));
9243 reflection_methodbuilder_to_mono_method (MonoClass
*klass
,
9244 ReflectionMethodBuilder
*rmb
,
9245 MonoMethodSignature
*sig
)
9248 MonoMethodNormal
*pm
;
9249 MonoMarshalSpec
**specs
;
9250 MonoReflectionMethodAux
*method_aux
;
9256 * Methods created using a MethodBuilder should have their memory allocated
9257 * inside the image mempool, while dynamic methods should have their memory
9260 dynamic
= rmb
->refs
!= NULL
;
9261 image
= dynamic
? NULL
: klass
->image
;
9264 g_assert (!klass
->generic_class
);
9266 mono_loader_lock ();
9268 if ((rmb
->attrs
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) ||
9269 (rmb
->iattrs
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
))
9270 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodPInvoke
, 1);
9272 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodWrapper
, 1);
9274 m
= (MonoMethod
*)image_g_new0 (image
, MonoMethodNormal
, 1);
9276 pm
= (MonoMethodNormal
*)m
;
9278 m
->dynamic
= dynamic
;
9280 m
->flags
= rmb
->attrs
;
9281 m
->iflags
= rmb
->iattrs
;
9282 m
->name
= mono_string_to_utf8_image (image
, rmb
->name
);
9285 m
->skip_visibility
= rmb
->skip_visibility
;
9287 m
->token
= MONO_TOKEN_METHOD_DEF
| (*rmb
->table_idx
);
9289 if (m
->iflags
& METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL
) {
9290 if (klass
== mono_defaults
.string_class
&& !strcmp (m
->name
, ".ctor"))
9293 m
->signature
->pinvoke
= 1;
9294 } else if (m
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
) {
9295 m
->signature
->pinvoke
= 1;
9297 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9299 method_aux
->dllentry
= rmb
->dllentry
? mono_string_to_utf8_image (image
, rmb
->dllentry
) : image_strdup (image
, m
->name
);
9300 method_aux
->dll
= mono_string_to_utf8_image (image
, rmb
->dll
);
9302 ((MonoMethodPInvoke
*)m
)->piflags
= (rmb
->native_cc
<< 8) | (rmb
->charset
? (rmb
->charset
- 1) * 2 : 0) | rmb
->extra_flags
;
9304 if (klass
->image
->dynamic
)
9305 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
9307 mono_loader_unlock ();
9310 } else if (!(m
->flags
& METHOD_ATTRIBUTE_ABSTRACT
) &&
9311 !(m
->iflags
& METHOD_IMPL_ATTRIBUTE_RUNTIME
)) {
9312 MonoMethodHeader
*header
;
9314 gint32 max_stack
, i
;
9315 gint32 num_locals
= 0;
9316 gint32 num_clauses
= 0;
9320 code
= mono_array_addr (rmb
->ilgen
->code
, guint8
, 0);
9321 code_size
= rmb
->ilgen
->code_len
;
9322 max_stack
= rmb
->ilgen
->max_stack
;
9323 num_locals
= rmb
->ilgen
->locals
? mono_array_length (rmb
->ilgen
->locals
) : 0;
9324 if (rmb
->ilgen
->ex_handlers
)
9325 num_clauses
= method_count_clauses (rmb
->ilgen
);
9328 code
= mono_array_addr (rmb
->code
, guint8
, 0);
9329 code_size
= mono_array_length (rmb
->code
);
9330 /* we probably need to run a verifier on the code... */
9340 header
= image_g_malloc0 (image
, sizeof (MonoMethodHeader
) +
9341 (num_locals
- MONO_ZERO_LEN_ARRAY
) * sizeof (MonoType
*));
9342 header
->code_size
= code_size
;
9343 header
->code
= image_g_malloc (image
, code_size
);
9344 memcpy ((char*)header
->code
, code
, code_size
);
9345 header
->max_stack
= max_stack
;
9346 header
->init_locals
= rmb
->init_locals
;
9347 header
->num_locals
= num_locals
;
9349 for (i
= 0; i
< num_locals
; ++i
) {
9350 MonoReflectionLocalBuilder
*lb
=
9351 mono_array_get (rmb
->ilgen
->locals
, MonoReflectionLocalBuilder
*, i
);
9353 header
->locals
[i
] = image_g_new0 (image
, MonoType
, 1);
9354 memcpy (header
->locals
[i
], monotype_cast (lb
->type
)->type
, sizeof (MonoType
));
9357 header
->num_clauses
= num_clauses
;
9359 header
->clauses
= method_encode_clauses (image
, (MonoDynamicImage
*)klass
->image
,
9360 rmb
->ilgen
, num_clauses
);
9363 pm
->header
= header
;
9366 if (rmb
->generic_params
) {
9367 int count
= mono_array_length (rmb
->generic_params
);
9368 MonoGenericContainer
*container
;
9370 container
= rmb
->generic_container
;
9372 m
->is_generic
= TRUE
;
9373 mono_method_set_generic_container (m
, container
);
9375 container
->type_argc
= count
;
9376 container
->type_params
= image_g_new0 (image
, MonoGenericParam
, count
);
9377 container
->owner
.method
= m
;
9379 for (i
= 0; i
< count
; i
++) {
9380 MonoReflectionGenericParam
*gp
=
9381 mono_array_get (rmb
->generic_params
, MonoReflectionGenericParam
*, i
);
9383 container
->type_params
[i
] = *gp
->type
.type
->data
.generic_param
;
9386 if (klass
->generic_container
) {
9387 container
->parent
= klass
->generic_container
;
9388 container
->context
.class_inst
= klass
->generic_container
->context
.class_inst
;
9390 container
->context
.method_inst
= mono_get_shared_generic_inst (container
);
9394 MonoMethodWrapper
*mw
= (MonoMethodWrapper
*)m
;
9398 m
->wrapper_type
= MONO_WRAPPER_DYNAMIC_METHOD
;
9400 mw
->method_data
= data
= image_g_new (image
, gpointer
, rmb
->nrefs
+ 1);
9401 data
[0] = GUINT_TO_POINTER (rmb
->nrefs
);
9402 for (i
= 0; i
< rmb
->nrefs
; ++i
)
9403 data
[i
+ 1] = rmb
->refs
[i
];
9408 /* Parameter info */
9411 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9412 method_aux
->param_names
= image_g_new0 (image
, char *, mono_method_signature (m
)->param_count
+ 1);
9413 for (i
= 0; i
<= m
->signature
->param_count
; ++i
) {
9414 MonoReflectionParamBuilder
*pb
;
9415 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
9416 if ((i
> 0) && (pb
->attrs
)) {
9417 /* Make a copy since it might point to a shared type structure */
9418 m
->signature
->params
[i
- 1] = mono_metadata_type_dup (klass
->image
, m
->signature
->params
[i
- 1]);
9419 m
->signature
->params
[i
- 1]->attrs
= pb
->attrs
;
9422 if (pb
->attrs
& PARAM_ATTRIBUTE_HAS_DEFAULT
) {
9423 MonoDynamicImage
*assembly
;
9424 guint32 idx
, def_type
, len
;
9428 if (!method_aux
->param_defaults
) {
9429 method_aux
->param_defaults
= image_g_new0 (image
, guint8
*, m
->signature
->param_count
+ 1);
9430 method_aux
->param_default_types
= image_g_new0 (image
, guint32
, m
->signature
->param_count
+ 1);
9432 assembly
= (MonoDynamicImage
*)klass
->image
;
9433 idx
= encode_constant (assembly
, pb
->def_value
, &def_type
);
9434 /* Copy the data from the blob since it might get realloc-ed */
9435 p
= assembly
->blob
.data
+ idx
;
9436 len
= mono_metadata_decode_blob_size (p
, &p2
);
9438 method_aux
->param_defaults
[i
] = image_g_malloc (image
, len
);
9439 method_aux
->param_default_types
[i
] = def_type
;
9440 memcpy ((gpointer
)method_aux
->param_defaults
[i
], p
, len
);
9444 method_aux
->param_names
[i
] = mono_string_to_utf8_image (image
, pb
->name
);
9446 if (!method_aux
->param_cattr
)
9447 method_aux
->param_cattr
= image_g_new0 (image
, MonoCustomAttrInfo
*, m
->signature
->param_count
+ 1);
9448 method_aux
->param_cattr
[i
] = mono_custom_attrs_from_builders (image
, klass
->image
, pb
->cattrs
);
9454 /* Parameter marshalling */
9457 for (i
= 0; i
< mono_array_length (rmb
->pinfo
); ++i
) {
9458 MonoReflectionParamBuilder
*pb
;
9459 if ((pb
= mono_array_get (rmb
->pinfo
, MonoReflectionParamBuilder
*, i
))) {
9460 if (pb
->marshal_info
) {
9462 specs
= image_g_new0 (image
, MonoMarshalSpec
*, sig
->param_count
+ 1);
9463 specs
[pb
->position
] =
9464 mono_marshal_spec_from_builder (image
, klass
->image
->assembly
, pb
->marshal_info
);
9468 if (specs
!= NULL
) {
9470 method_aux
= image_g_new0 (image
, MonoReflectionMethodAux
, 1);
9471 method_aux
->param_marshall
= specs
;
9474 if (klass
->image
->dynamic
&& method_aux
)
9475 g_hash_table_insert (((MonoDynamicImage
*)klass
->image
)->method_aux_hash
, m
, method_aux
);
9477 mono_loader_unlock ();
9483 ctorbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionCtorBuilder
* mb
)
9485 ReflectionMethodBuilder rmb
;
9486 MonoMethodSignature
*sig
;
9488 mono_loader_lock ();
9489 sig
= ctor_builder_to_signature (klass
->image
, mb
);
9490 mono_loader_unlock ();
9492 reflection_methodbuilder_from_ctor_builder (&rmb
, mb
);
9494 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
9495 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
9497 /* If we are in a generic class, we might be called multiple times from inflate_method */
9498 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
9499 /* ilgen is no longer needed */
9507 methodbuilder_to_mono_method (MonoClass
*klass
, MonoReflectionMethodBuilder
* mb
)
9509 ReflectionMethodBuilder rmb
;
9510 MonoMethodSignature
*sig
;
9512 mono_loader_lock ();
9513 sig
= method_builder_to_signature (klass
->image
, mb
);
9514 mono_loader_unlock ();
9516 reflection_methodbuilder_from_method_builder (&rmb
, mb
);
9518 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
9519 mono_save_custom_attrs (klass
->image
, mb
->mhandle
, mb
->cattrs
);
9521 /* If we are in a generic class, we might be called multiple times from inflate_method */
9522 if (!((MonoDynamicImage
*)(MonoDynamicImage
*)klass
->image
)->save
&& !klass
->generic_container
) {
9523 /* ilgen is no longer needed */
9529 static MonoClassField
*
9530 fieldbuilder_to_mono_class_field (MonoClass
*klass
, MonoReflectionFieldBuilder
* fb
)
9532 MonoClassField
*field
;
9535 field
= g_new0 (MonoClassField
, 1);
9537 field
->name
= mono_string_to_utf8 (fb
->name
);
9538 if (fb
->attrs
|| fb
->modreq
|| fb
->modopt
) {
9539 field
->type
= mono_metadata_type_dup (NULL
, monotype_cast (fb
->type
)->type
);
9540 field
->type
->attrs
= fb
->attrs
;
9542 g_assert (klass
->image
->dynamic
);
9543 custom
= add_custom_modifiers ((MonoDynamicImage
*)klass
->image
, field
->type
, fb
->modreq
, fb
->modopt
);
9544 g_free (field
->type
);
9545 field
->type
= custom
;
9547 field
->type
= monotype_cast (fb
->type
)->type
;
9549 if (fb
->offset
!= -1)
9550 field
->offset
= fb
->offset
;
9551 field
->parent
= klass
;
9552 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
9554 // FIXME: Can't store fb->def_value/RVA, is it needed for field_on_insts ?
9560 mono_reflection_bind_generic_parameters (MonoReflectionType
*type
, int type_argc
, MonoType
**types
)
9563 MonoReflectionTypeBuilder
*tb
= NULL
;
9564 gboolean is_dynamic
= FALSE
;
9568 mono_loader_lock ();
9570 domain
= mono_object_domain (type
);
9572 if (!strcmp (((MonoObject
*) type
)->vtable
->klass
->name
, "TypeBuilder")) {
9573 tb
= (MonoReflectionTypeBuilder
*) type
;
9576 } else if (!strcmp (((MonoObject
*) type
)->vtable
->klass
->name
, "MonoGenericClass")) {
9577 MonoReflectionGenericClass
*rgi
= (MonoReflectionGenericClass
*) type
;
9579 tb
= rgi
->generic_type
;
9583 /* FIXME: fix the CreateGenericParameters protocol to avoid the two stage setup of TypeBuilders */
9584 if (tb
&& tb
->generic_container
)
9585 mono_reflection_create_generic_class (tb
);
9587 klass
= mono_class_from_mono_type (type
->type
);
9588 if (!klass
->generic_container
) {
9589 mono_loader_unlock ();
9593 if (klass
->wastypebuilder
) {
9594 tb
= (MonoReflectionTypeBuilder
*) klass
->reflection_info
;
9599 mono_loader_unlock ();
9601 geninst
= mono_class_bind_generic_parameters (klass
, type_argc
, types
, is_dynamic
);
9603 return &geninst
->byval_arg
;
9607 mono_class_bind_generic_parameters (MonoClass
*klass
, int type_argc
, MonoType
**types
, gboolean is_dynamic
)
9609 MonoGenericClass
*gclass
;
9610 MonoGenericInst
*inst
;
9612 g_assert (klass
->generic_container
);
9614 inst
= mono_metadata_get_generic_inst (type_argc
, types
);
9615 gclass
= mono_metadata_lookup_generic_class (klass
, inst
, is_dynamic
);
9617 return mono_generic_class_get_class (gclass
);
9620 MonoReflectionMethod
*
9621 mono_reflection_bind_generic_method_parameters (MonoReflectionMethod
*rmethod
, MonoArray
*types
)
9624 MonoMethod
*method
, *inflated
;
9625 MonoMethodInflated
*imethod
;
9626 MonoReflectionMethodBuilder
*mb
= NULL
;
9627 MonoGenericContext tmp_context
;
9628 MonoGenericInst
*ginst
;
9629 MonoType
**type_argv
;
9632 MONO_ARCH_SAVE_REGS
;
9634 if (!strcmp (rmethod
->object
.vtable
->klass
->name
, "MethodBuilder")) {
9635 #ifndef DISABLE_REFLECTION_EMIT
9636 MonoReflectionTypeBuilder
*tb
;
9639 mb
= (MonoReflectionMethodBuilder
*) rmethod
;
9640 tb
= (MonoReflectionTypeBuilder
*) mb
->type
;
9641 klass
= mono_class_from_mono_type (tb
->type
.type
);
9643 method
= methodbuilder_to_mono_method (klass
, mb
);
9645 g_assert_not_reached ();
9649 method
= rmethod
->method
;
9652 klass
= method
->klass
;
9654 if (method
->is_inflated
)
9655 method
= ((MonoMethodInflated
*) method
)->declaring
;
9657 count
= mono_method_signature (method
)->generic_param_count
;
9658 if (count
!= mono_array_length (types
))
9661 type_argv
= g_new0 (MonoType
*, count
);
9662 for (i
= 0; i
< count
; i
++) {
9663 MonoReflectionType
*garg
= mono_array_get (types
, gpointer
, i
);
9664 type_argv
[i
] = garg
->type
;
9666 ginst
= mono_metadata_get_generic_inst (count
, type_argv
);
9669 tmp_context
.class_inst
= klass
->generic_class
? klass
->generic_class
->context
.class_inst
: NULL
;
9670 tmp_context
.method_inst
= ginst
;
9672 inflated
= mono_class_inflate_generic_method (method
, &tmp_context
);
9673 imethod
= (MonoMethodInflated
*) inflated
;
9675 if (method
->klass
->image
->dynamic
) {
9676 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
9678 * This table maps metadata structures representing inflated methods/fields
9679 * to the reflection objects representing their generic definitions.
9681 mono_loader_lock ();
9682 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, rmethod
);
9683 mono_loader_unlock ();
9686 return mono_method_get_object (mono_object_domain (rmethod
), inflated
, NULL
);
9689 #ifndef DISABLE_REFLECTION_EMIT
9692 inflate_mono_method (MonoClass
*klass
, MonoMethod
*method
, MonoObject
*obj
)
9694 MonoMethodInflated
*imethod
;
9695 MonoGenericContext
*context
;
9699 * With generic code sharing the klass might not be inflated.
9700 * This can happen because classes inflated with their own
9701 * type arguments are "normalized" to the uninflated class.
9703 if (!klass
->generic_class
)
9706 context
= mono_class_get_context (klass
);
9708 if (klass
->method
.count
) {
9709 /* Find the already created inflated method */
9710 for (i
= 0; i
< klass
->method
.count
; ++i
) {
9711 g_assert (klass
->methods
[i
]->is_inflated
);
9712 if (((MonoMethodInflated
*)klass
->methods
[i
])->declaring
== method
)
9715 g_assert (i
< klass
->method
.count
);
9716 imethod
= (MonoMethodInflated
*)klass
->methods
[i
];
9718 imethod
= (MonoMethodInflated
*) mono_class_inflate_generic_method_full (method
, klass
, context
);
9721 if (method
->is_generic
&& method
->klass
->image
->dynamic
) {
9722 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->klass
->image
;
9724 mono_loader_lock ();
9725 mono_g_hash_table_insert (image
->generic_def_objects
, imethod
, obj
);
9726 mono_loader_unlock ();
9728 return (MonoMethod
*) imethod
;
9732 inflate_method (MonoReflectionGenericClass
*type
, MonoObject
*obj
)
9737 gklass
= mono_class_from_mono_type (type
->generic_type
->type
.type
);
9739 if (!strcmp (obj
->vtable
->klass
->name
, "MethodBuilder"))
9740 if (((MonoReflectionMethodBuilder
*)obj
)->mhandle
)
9741 method
= ((MonoReflectionMethodBuilder
*)obj
)->mhandle
;
9743 method
= methodbuilder_to_mono_method (gklass
, (MonoReflectionMethodBuilder
*) obj
);
9744 else if (!strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder"))
9745 method
= ctorbuilder_to_mono_method (gklass
, (MonoReflectionCtorBuilder
*) obj
);
9746 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoMethod") || !strcmp (obj
->vtable
->klass
->name
, "MonoCMethod"))
9747 method
= ((MonoReflectionMethod
*) obj
)->method
;
9749 method
= NULL
; /* prevent compiler warning */
9750 g_assert_not_reached ();
9753 return inflate_mono_method (mono_class_from_mono_type (type
->type
.type
), method
, obj
);
9756 /*TODO avoid saving custom attrs for generic classes as it's enough to have them on the generic type definition.*/
9758 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
9759 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
9762 MonoGenericClass
*gclass
;
9763 MonoDynamicGenericClass
*dgclass
;
9764 MonoClass
*klass
, *gklass
;
9767 MONO_ARCH_SAVE_REGS
;
9769 klass
= mono_class_from_mono_type (type
->type
.type
);
9770 g_assert (type
->type
.type
->type
== MONO_TYPE_GENERICINST
);
9771 gclass
= type
->type
.type
->data
.generic_class
;
9773 g_assert (gclass
->is_dynamic
);
9774 dgclass
= (MonoDynamicGenericClass
*) gclass
;
9776 if (dgclass
->initialized
)
9779 gklass
= gclass
->container_class
;
9780 mono_class_init (gklass
);
9782 dgclass
->count_methods
= methods
? mono_array_length (methods
) : 0;
9783 dgclass
->count_ctors
= ctors
? mono_array_length (ctors
) : 0;
9784 dgclass
->count_fields
= fields
? mono_array_length (fields
) : 0;
9785 dgclass
->count_properties
= properties
? mono_array_length (properties
) : 0;
9786 dgclass
->count_events
= events
? mono_array_length (events
) : 0;
9788 dgclass
->methods
= g_new0 (MonoMethod
*, dgclass
->count_methods
);
9789 dgclass
->ctors
= g_new0 (MonoMethod
*, dgclass
->count_ctors
);
9790 dgclass
->fields
= g_new0 (MonoClassField
, dgclass
->count_fields
);
9791 dgclass
->properties
= g_new0 (MonoProperty
, dgclass
->count_properties
);
9792 dgclass
->events
= g_new0 (MonoEvent
, dgclass
->count_events
);
9793 dgclass
->field_objects
= g_new0 (MonoObject
*, dgclass
->count_fields
);
9794 dgclass
->field_generic_types
= g_new0 (MonoType
*, dgclass
->count_fields
);
9796 for (i
= 0; i
< dgclass
->count_methods
; i
++) {
9797 MonoObject
*obj
= mono_array_get (methods
, gpointer
, i
);
9799 dgclass
->methods
[i
] = inflate_method (type
, obj
);
9802 for (i
= 0; i
< dgclass
->count_ctors
; i
++) {
9803 MonoObject
*obj
= mono_array_get (ctors
, gpointer
, i
);
9805 dgclass
->ctors
[i
] = inflate_method (type
, obj
);
9808 for (i
= 0; i
< dgclass
->count_fields
; i
++) {
9809 MonoObject
*obj
= mono_array_get (fields
, gpointer
, i
);
9810 MonoClassField
*field
, *inflated_field
= NULL
;
9812 if (!strcmp (obj
->vtable
->klass
->name
, "FieldBuilder"))
9813 inflated_field
= field
= fieldbuilder_to_mono_class_field (klass
, (MonoReflectionFieldBuilder
*) obj
);
9814 else if (!strcmp (obj
->vtable
->klass
->name
, "MonoField"))
9815 field
= ((MonoReflectionField
*) obj
)->field
;
9817 field
= NULL
; /* prevent compiler warning */
9818 g_assert_not_reached ();
9821 dgclass
->fields
[i
] = *field
;
9822 dgclass
->fields
[i
].parent
= klass
;
9823 dgclass
->fields
[i
].type
= mono_class_inflate_generic_type (
9824 field
->type
, mono_generic_class_get_context ((MonoGenericClass
*) dgclass
));
9825 dgclass
->field_generic_types
[i
] = field
->type
;
9826 MOVING_GC_REGISTER (&dgclass
->field_objects
[i
]);
9827 dgclass
->field_objects
[i
] = obj
;
9829 if (inflated_field
) {
9830 g_free (inflated_field
);
9832 dgclass
->fields
[i
].name
= g_strdup (dgclass
->fields
[i
].name
);
9836 for (i
= 0; i
< dgclass
->count_properties
; i
++) {
9837 MonoObject
*obj
= mono_array_get (properties
, gpointer
, i
);
9838 MonoProperty
*property
= &dgclass
->properties
[i
];
9840 if (!strcmp (obj
->vtable
->klass
->name
, "PropertyBuilder")) {
9841 MonoReflectionPropertyBuilder
*pb
= (MonoReflectionPropertyBuilder
*) obj
;
9843 property
->parent
= klass
;
9844 property
->attrs
= pb
->attrs
;
9845 property
->name
= mono_string_to_utf8 (pb
->name
);
9847 property
->get
= inflate_method (type
, (MonoObject
*) pb
->get_method
);
9849 property
->set
= inflate_method (type
, (MonoObject
*) pb
->set_method
);
9850 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoProperty")) {
9851 *property
= *((MonoReflectionProperty
*) obj
)->property
;
9852 property
->name
= g_strdup (property
->name
);
9855 property
->get
= inflate_mono_method (klass
, property
->get
, NULL
);
9857 property
->set
= inflate_mono_method (klass
, property
->set
, NULL
);
9859 g_assert_not_reached ();
9862 for (i
= 0; i
< dgclass
->count_events
; i
++) {
9863 MonoObject
*obj
= mono_array_get (events
, gpointer
, i
);
9864 MonoEvent
*event
= &dgclass
->events
[i
];
9866 if (!strcmp (obj
->vtable
->klass
->name
, "EventBuilder")) {
9867 MonoReflectionEventBuilder
*eb
= (MonoReflectionEventBuilder
*) obj
;
9869 event
->parent
= klass
;
9870 event
->attrs
= eb
->attrs
;
9871 event
->name
= mono_string_to_utf8 (eb
->name
);
9873 event
->add
= inflate_method (type
, (MonoObject
*) eb
->add_method
);
9874 if (eb
->remove_method
)
9875 event
->remove
= inflate_method (type
, (MonoObject
*) eb
->remove_method
);
9876 } else if (!strcmp (obj
->vtable
->klass
->name
, "MonoEvent")) {
9877 *event
= *((MonoReflectionMonoEvent
*) obj
)->event
;
9878 event
->name
= g_strdup (event
->name
);
9881 event
->add
= inflate_mono_method (klass
, event
->add
, NULL
);
9883 event
->remove
= inflate_mono_method (klass
, event
->remove
, NULL
);
9885 g_assert_not_reached ();
9888 dgclass
->initialized
= TRUE
;
9892 ensure_generic_class_runtime_vtable (MonoClass
*klass
)
9894 MonoClass
*gklass
= klass
->generic_class
->container_class
;
9897 if (klass
->wastypebuilder
)
9900 ensure_runtime_vtable (gklass
);
9902 klass
->method
.count
= gklass
->method
.count
;
9903 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * (klass
->method
.count
+ 1));
9905 for (i
= 0; i
< klass
->method
.count
; i
++) {
9906 klass
->methods
[i
] = mono_class_inflate_generic_method_full (
9907 gklass
->methods
[i
], klass
, mono_class_get_context (klass
));
9910 klass
->interface_count
= gklass
->interface_count
;
9911 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
9912 for (i
= 0; i
< klass
->interface_count
; ++i
) {
9913 MonoType
*iface_type
= mono_class_inflate_generic_type (&gklass
->interfaces
[i
]->byval_arg
, mono_class_get_context (klass
));
9914 klass
->interfaces
[i
] = mono_class_from_mono_type (iface_type
);
9915 mono_metadata_free_type (iface_type
);
9917 ensure_runtime_vtable (klass
->interfaces
[i
]);
9919 klass
->interfaces_inited
= 1;
9921 /*We can only finish with this klass once it's parent has as well*/
9922 if (gklass
->wastypebuilder
)
9923 klass
->wastypebuilder
= TRUE
;
9928 ensure_runtime_vtable (MonoClass
*klass
)
9930 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
9933 if (!klass
->image
->dynamic
|| (!tb
&& !klass
->generic_class
) || klass
->wastypebuilder
)
9936 ensure_runtime_vtable (klass
->parent
);
9939 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
9940 num
+= tb
->num_methods
;
9941 klass
->method
.count
= num
;
9942 klass
->methods
= mono_image_alloc (klass
->image
, sizeof (MonoMethod
*) * num
);
9943 num
= tb
->ctors
? mono_array_length (tb
->ctors
): 0;
9944 for (i
= 0; i
< num
; ++i
)
9945 klass
->methods
[i
] = ctorbuilder_to_mono_method (klass
, mono_array_get (tb
->ctors
, MonoReflectionCtorBuilder
*, i
));
9946 num
= tb
->num_methods
;
9948 for (i
= 0; i
< num
; ++i
)
9949 klass
->methods
[j
++] = methodbuilder_to_mono_method (klass
, mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
));
9951 if (tb
->interfaces
) {
9952 klass
->interface_count
= mono_array_length (tb
->interfaces
);
9953 klass
->interfaces
= mono_image_alloc (klass
->image
, sizeof (MonoClass
*) * klass
->interface_count
);
9954 for (i
= 0; i
< klass
->interface_count
; ++i
) {
9955 MonoReflectionType
*iface
= mono_type_array_get (tb
->interfaces
, i
);
9956 klass
->interfaces
[i
] = mono_class_from_mono_type (iface
->type
);
9957 ensure_runtime_vtable (klass
->interfaces
[i
]);
9959 klass
->interfaces_inited
= 1;
9961 } else if (klass
->generic_class
){
9962 ensure_generic_class_runtime_vtable (klass
);
9965 if (klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
9966 for (i
= 0; i
< klass
->method
.count
; ++i
)
9967 klass
->methods
[i
]->slot
= i
;
9969 mono_class_setup_interface_offsets (klass
);
9970 mono_class_setup_interface_id (klass
);
9974 * The generic vtable is needed even if image->run is not set since some
9975 * runtime code like ves_icall_Type_GetMethodsByName depends on
9976 * method->slot being defined.
9980 * tb->methods could not be freed since it is used for determining
9981 * overrides during dynamic vtable construction.
9986 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
9988 MonoReflectionTypeBuilder
*tb
;
9994 g_assert (klass
->image
->dynamic
);
9996 if (!klass
->reflection_info
)
9999 g_assert (strcmp (((MonoObject
*)klass
->reflection_info
)->vtable
->klass
->name
, "TypeBuilder") == 0);
10001 tb
= (MonoReflectionTypeBuilder
*)klass
->reflection_info
;
10005 for (i
= 0; i
< tb
->num_methods
; ++i
) {
10006 MonoReflectionMethodBuilder
*mb
=
10007 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
10008 if (mb
->override_method
)
10014 *overrides
= g_new0 (MonoMethod
*, onum
* 2);
10017 for (i
= 0; i
< tb
->num_methods
; ++i
) {
10018 MonoReflectionMethodBuilder
*mb
=
10019 mono_array_get (tb
->methods
, MonoReflectionMethodBuilder
*, i
);
10020 if (mb
->override_method
) {
10021 (*overrides
) [onum
* 2] =
10022 mb
->override_method
->method
;
10023 (*overrides
) [onum
* 2 + 1] =
10026 /* FIXME: What if 'override_method' is a MethodBuilder ? */
10027 g_assert (mb
->override_method
->method
);
10028 g_assert (mb
->mhandle
);
10035 *num_overrides
= onum
;
10039 typebuilder_setup_fields (MonoClass
*klass
)
10041 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10042 MonoReflectionFieldBuilder
*fb
;
10043 MonoClassField
*field
;
10044 MonoImage
*image
= klass
->image
;
10045 const char *p
, *p2
;
10047 guint32 len
, idx
, real_size
= 0;
10049 klass
->field
.count
= tb
->num_fields
;
10050 klass
->field
.first
= 0;
10052 if (tb
->class_size
) {
10053 g_assert ((tb
->packing_size
& 0xfffffff0) == 0);
10054 klass
->packing_size
= tb
->packing_size
;
10055 real_size
= klass
->instance_size
+ tb
->class_size
;
10058 if (!klass
->field
.count
) {
10059 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10063 klass
->fields
= image_g_new0 (image
, MonoClassField
, klass
->field
.count
);
10064 mono_class_alloc_ext (klass
);
10065 klass
->ext
->field_def_values
= image_g_new0 (image
, MonoFieldDefaultValue
, klass
->field
.count
);
10067 for (i
= 0; i
< klass
->field
.count
; ++i
) {
10068 fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10069 field
= &klass
->fields
[i
];
10070 field
->name
= mono_string_to_utf8_image (image
, fb
->name
);
10072 field
->type
= mono_metadata_type_dup (klass
->image
, monotype_cast (fb
->type
)->type
);
10073 field
->type
->attrs
= fb
->attrs
;
10075 field
->type
= monotype_cast (fb
->type
)->type
;
10077 if ((fb
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
) && fb
->rva_data
)
10078 klass
->ext
->field_def_values
[i
].data
= mono_array_addr (fb
->rva_data
, char, 0);
10079 if (fb
->offset
!= -1)
10080 field
->offset
= fb
->offset
;
10081 field
->parent
= klass
;
10082 fb
->handle
= field
;
10083 mono_save_custom_attrs (klass
->image
, field
, fb
->cattrs
);
10085 if (fb
->def_value
) {
10086 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)klass
->image
;
10087 field
->type
->attrs
|= FIELD_ATTRIBUTE_HAS_DEFAULT
;
10088 idx
= encode_constant (assembly
, fb
->def_value
, &klass
->ext
->field_def_values
[i
].def_type
);
10089 /* Copy the data from the blob since it might get realloc-ed */
10090 p
= assembly
->blob
.data
+ idx
;
10091 len
= mono_metadata_decode_blob_size (p
, &p2
);
10093 klass
->ext
->field_def_values
[i
].data
= mono_image_alloc (image
, len
);
10094 memcpy ((gpointer
)klass
->ext
->field_def_values
[i
].data
, p
, len
);
10098 klass
->instance_size
= MAX (klass
->instance_size
, real_size
);
10099 mono_class_layout_fields (klass
);
10103 typebuilder_setup_properties (MonoClass
*klass
)
10105 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10106 MonoReflectionPropertyBuilder
*pb
;
10107 MonoImage
*image
= klass
->image
;
10108 MonoProperty
*properties
;
10112 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
10114 klass
->ext
->property
.count
= tb
->properties
? mono_array_length (tb
->properties
) : 0;
10115 klass
->ext
->property
.first
= 0;
10117 properties
= image_g_new0 (image
, MonoProperty
, klass
->ext
->property
.count
);
10118 klass
->ext
->properties
= properties
;
10119 for (i
= 0; i
< klass
->ext
->property
.count
; ++i
) {
10120 pb
= mono_array_get (tb
->properties
, MonoReflectionPropertyBuilder
*, i
);
10121 properties
[i
].parent
= klass
;
10122 properties
[i
].attrs
= pb
->attrs
;
10123 properties
[i
].name
= mono_string_to_utf8_image (image
, pb
->name
);
10124 if (pb
->get_method
)
10125 properties
[i
].get
= pb
->get_method
->mhandle
;
10126 if (pb
->set_method
)
10127 properties
[i
].set
= pb
->set_method
->mhandle
;
10129 mono_save_custom_attrs (klass
->image
, &properties
[i
], pb
->cattrs
);
10133 MonoReflectionEvent
*
10134 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
10136 MonoEvent
*event
= g_new0 (MonoEvent
, 1);
10140 klass
= my_mono_class_from_mono_type (tb
->type
.type
);
10142 event
->parent
= klass
;
10143 event
->attrs
= eb
->attrs
;
10144 event
->name
= mono_string_to_utf8 (eb
->name
);
10145 if (eb
->add_method
)
10146 event
->add
= eb
->add_method
->mhandle
;
10147 if (eb
->remove_method
)
10148 event
->remove
= eb
->remove_method
->mhandle
;
10149 if (eb
->raise_method
)
10150 event
->raise
= eb
->raise_method
->mhandle
;
10152 if (eb
->other_methods
) {
10153 event
->other
= g_new0 (MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10154 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10155 MonoReflectionMethodBuilder
*mb
=
10156 mono_array_get (eb
->other_methods
,
10157 MonoReflectionMethodBuilder
*, j
);
10158 event
->other
[j
] = mb
->mhandle
;
10162 return mono_event_get_object (mono_object_domain (tb
), klass
, event
);
10166 typebuilder_setup_events (MonoClass
*klass
)
10168 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10169 MonoReflectionEventBuilder
*eb
;
10170 MonoImage
*image
= klass
->image
;
10175 klass
->ext
= image_g_new0 (image
, MonoClassExt
, 1);
10177 klass
->ext
->event
.count
= tb
->events
? mono_array_length (tb
->events
) : 0;
10178 klass
->ext
->event
.first
= 0;
10180 events
= image_g_new0 (image
, MonoEvent
, klass
->ext
->event
.count
);
10181 klass
->ext
->events
= events
;
10182 for (i
= 0; i
< klass
->ext
->event
.count
; ++i
) {
10183 eb
= mono_array_get (tb
->events
, MonoReflectionEventBuilder
*, i
);
10184 events
[i
].parent
= klass
;
10185 events
[i
].attrs
= eb
->attrs
;
10186 events
[i
].name
= mono_string_to_utf8_image (image
, eb
->name
);
10187 if (eb
->add_method
)
10188 events
[i
].add
= eb
->add_method
->mhandle
;
10189 if (eb
->remove_method
)
10190 events
[i
].remove
= eb
->remove_method
->mhandle
;
10191 if (eb
->raise_method
)
10192 events
[i
].raise
= eb
->raise_method
->mhandle
;
10194 if (eb
->other_methods
) {
10195 events
[i
].other
= image_g_new0 (image
, MonoMethod
*, mono_array_length (eb
->other_methods
) + 1);
10196 for (j
= 0; j
< mono_array_length (eb
->other_methods
); ++j
) {
10197 MonoReflectionMethodBuilder
*mb
=
10198 mono_array_get (eb
->other_methods
,
10199 MonoReflectionMethodBuilder
*, j
);
10200 events
[i
].other
[j
] = mb
->mhandle
;
10203 mono_save_custom_attrs (klass
->image
, &events
[i
], eb
->cattrs
);
10208 remove_instantiations_of (gpointer key
,
10210 gpointer user_data
)
10212 MonoType
*type
= (MonoType
*)key
;
10213 MonoClass
*klass
= (MonoClass
*)user_data
;
10215 if ((type
->type
== MONO_TYPE_GENERICINST
) && (type
->data
.generic_class
->container_class
== klass
))
10221 MonoReflectionType
*
10222 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
10225 MonoDomain
* domain
;
10226 MonoReflectionType
* res
;
10229 MONO_ARCH_SAVE_REGS
;
10231 domain
= mono_object_domain (tb
);
10232 klass
= my_mono_class_from_mono_type (tb
->type
.type
);
10235 * Check for user defined Type subclasses.
10237 CHECK_MONOTYPE (tb
->parent
);
10238 check_array_for_usertypes (tb
->interfaces
);
10240 for (i
= 0; i
< mono_array_length (tb
->fields
); ++i
) {
10241 MonoReflectionFieldBuilder
*fb
= mono_array_get (tb
->fields
, gpointer
, i
);
10243 CHECK_MONOTYPE (fb
->type
);
10244 check_array_for_usertypes (fb
->modreq
);
10245 check_array_for_usertypes (fb
->modopt
);
10246 if (fb
->marshal_info
&& fb
->marshal_info
->marshaltyperef
)
10247 CHECK_MONOTYPE (fb
->marshal_info
->marshaltyperef
);
10252 for (i
= 0; i
< mono_array_length (tb
->methods
); ++i
) {
10253 MonoReflectionMethodBuilder
*mb
= mono_array_get (tb
->methods
, gpointer
, i
);
10255 CHECK_MONOTYPE (mb
->rtype
);
10256 check_array_for_usertypes (mb
->return_modreq
);
10257 check_array_for_usertypes (mb
->return_modopt
);
10258 check_array_for_usertypes (mb
->parameters
);
10259 if (mb
->param_modreq
)
10260 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
)
10261 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
));
10262 if (mb
->param_modopt
)
10263 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
)
10264 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
));
10269 for (i
= 0; i
< mono_array_length (tb
->ctors
); ++i
) {
10270 MonoReflectionCtorBuilder
*mb
= mono_array_get (tb
->ctors
, gpointer
, i
);
10272 check_array_for_usertypes (mb
->parameters
);
10273 if (mb
->param_modreq
)
10274 for (j
= 0; j
< mono_array_length (mb
->param_modreq
); ++j
)
10275 check_array_for_usertypes (mono_array_get (mb
->param_modreq
, MonoArray
*, j
));
10276 if (mb
->param_modopt
)
10277 for (j
= 0; j
< mono_array_length (mb
->param_modopt
); ++j
)
10278 check_array_for_usertypes (mono_array_get (mb
->param_modopt
, MonoArray
*, j
));
10283 mono_save_custom_attrs (klass
->image
, klass
, tb
->cattrs
);
10286 * we need to lock the domain because the lock will be taken inside
10287 * So, we need to keep the locking order correct.
10289 mono_loader_lock ();
10290 mono_domain_lock (domain
);
10291 if (klass
->wastypebuilder
) {
10292 mono_domain_unlock (domain
);
10293 mono_loader_unlock ();
10294 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10297 * Fields to set in klass:
10298 * the various flags: delegate/unicode/contextbound etc.
10300 klass
->flags
= tb
->attrs
;
10301 klass
->has_cctor
= 1;
10302 klass
->has_finalize
= 1;
10305 if (!((MonoDynamicImage
*)klass
->image
)->run
) {
10306 if (klass
->generic_container
) {
10307 /* FIXME: The code below can't handle generic classes */
10308 klass
->wastypebuilder
= TRUE
;
10309 mono_loader_unlock ();
10310 mono_domain_unlock (domain
);
10311 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10316 /* enums are done right away */
10317 if (!klass
->enumtype
)
10318 ensure_runtime_vtable (klass
);
10320 if (tb
->subtypes
) {
10321 for (i
= 0; i
< mono_array_length (tb
->subtypes
); ++i
) {
10322 MonoReflectionTypeBuilder
*subtb
= mono_array_get (tb
->subtypes
, MonoReflectionTypeBuilder
*, i
);
10323 mono_class_alloc_ext (klass
);
10324 klass
->ext
->nested_classes
= g_list_prepend_image (klass
->image
, klass
->ext
->nested_classes
, my_mono_class_from_mono_type (subtb
->type
.type
));
10328 klass
->nested_classes_inited
= TRUE
;
10330 /* fields and object layout */
10331 if (klass
->parent
) {
10332 if (!klass
->parent
->size_inited
)
10333 mono_class_init (klass
->parent
);
10334 klass
->instance_size
= klass
->parent
->instance_size
;
10335 klass
->sizes
.class_size
= 0;
10336 klass
->min_align
= klass
->parent
->min_align
;
10337 /* if the type has no fields we won't call the field_setup
10338 * routine which sets up klass->has_references.
10340 klass
->has_references
|= klass
->parent
->has_references
;
10342 klass
->instance_size
= sizeof (MonoObject
);
10343 klass
->min_align
= 1;
10346 /* FIXME: handle packing_size and instance_size */
10347 typebuilder_setup_fields (klass
);
10349 typebuilder_setup_properties (klass
);
10351 typebuilder_setup_events (klass
);
10353 klass
->wastypebuilder
= TRUE
;
10356 * If we are a generic TypeBuilder, there might be instantiations in the type cache
10357 * which have type System.Reflection.MonoGenericClass, but after the type is created,
10358 * we want to return normal System.MonoType objects, so clear these out from the cache.
10360 if (domain
->type_hash
&& klass
->generic_container
)
10361 mono_g_hash_table_foreach_remove (domain
->type_hash
, remove_instantiations_of
, klass
);
10363 mono_domain_unlock (domain
);
10364 mono_loader_unlock ();
10366 if (klass
->enumtype
&& !mono_class_is_valid_enum (klass
)) {
10367 mono_class_set_failure (klass
, MONO_EXCEPTION_TYPE_LOAD
, NULL
);
10368 mono_raise_exception (mono_get_exception_type_load (tb
->name
, NULL
));
10371 res
= mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
10372 g_assert (res
!= (MonoReflectionType
*)tb
);
10378 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
10380 MonoGenericParam
*param
;
10383 MONO_ARCH_SAVE_REGS
;
10385 param
= g_new0 (MonoGenericParam
, 1);
10387 if (gparam
->mbuilder
) {
10388 if (!gparam
->mbuilder
->generic_container
) {
10389 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)gparam
->mbuilder
->type
;
10390 MonoClass
*klass
= my_mono_class_from_mono_type (tb
->type
.type
);
10391 gparam
->mbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
10392 gparam
->mbuilder
->generic_container
->is_method
= TRUE
;
10394 param
->owner
= gparam
->mbuilder
->generic_container
;
10395 } else if (gparam
->tbuilder
) {
10396 if (!gparam
->tbuilder
->generic_container
) {
10397 MonoClass
*klass
= my_mono_class_from_mono_type (gparam
->tbuilder
->type
.type
);
10398 gparam
->tbuilder
->generic_container
= mono_image_alloc0 (klass
->image
, sizeof (MonoGenericContainer
));
10399 gparam
->tbuilder
->generic_container
->owner
.klass
= klass
;
10401 param
->owner
= gparam
->tbuilder
->generic_container
;
10404 param
->name
= mono_string_to_utf8 (gparam
->name
);
10405 param
->num
= gparam
->index
;
10407 image
= &gparam
->tbuilder
->module
->dynamic_image
->image
;
10408 mono_class_from_generic_parameter (param
, image
, gparam
->mbuilder
!= NULL
);
10410 gparam
->type
.type
= ¶m
->pklass
->byval_arg
;
10412 MOVING_GC_REGISTER (¶m
->pklass
->reflection_info
);
10413 param
->pklass
->reflection_info
= gparam
; /* FIXME: GC pin gparam */
10417 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
10419 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
10420 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
10425 check_array_for_usertypes (sig
->arguments
);
10427 sigbuffer_init (&buf
, 32);
10429 sigbuffer_add_value (&buf
, 0x07);
10430 sigbuffer_add_value (&buf
, na
);
10431 for (i
= 0; i
< na
; ++i
) {
10432 MonoReflectionType
*type
= mono_type_array_get (sig
->arguments
, i
);
10433 encode_reflection_type (assembly
, type
, &buf
);
10436 buflen
= buf
.p
- buf
.buf
;
10437 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
10438 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
10439 sigbuffer_free (&buf
);
10445 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
10447 MonoDynamicImage
*assembly
= sig
->module
->dynamic_image
;
10448 guint32 na
= sig
->arguments
? mono_array_length (sig
->arguments
) : 0;
10453 check_array_for_usertypes (sig
->arguments
);
10455 sigbuffer_init (&buf
, 32);
10457 sigbuffer_add_value (&buf
, 0x06);
10458 for (i
= 0; i
< na
; ++i
) {
10459 MonoReflectionType
*type
= mono_type_array_get (sig
->arguments
, i
);
10460 encode_reflection_type (assembly
, type
, &buf
);
10463 buflen
= buf
.p
- buf
.buf
;
10464 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, buflen
);
10465 memcpy (mono_array_addr (result
, char, 0), buf
.buf
, buflen
);
10466 sigbuffer_free (&buf
);
10472 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10474 ReflectionMethodBuilder rmb
;
10475 MonoMethodSignature
*sig
;
10480 sig
= dynamic_method_to_signature (mb
);
10482 reflection_methodbuilder_from_dynamic_method (&rmb
, mb
);
10485 * Resolve references.
10488 * Every second entry in the refs array is reserved for storing handle_class,
10489 * which is needed by the ldtoken implementation in the JIT.
10491 rmb
.nrefs
= mb
->nrefs
;
10492 rmb
.refs
= g_new0 (gpointer
, mb
->nrefs
+ 1);
10493 for (i
= 0; i
< mb
->nrefs
; i
+= 2) {
10494 MonoClass
*handle_class
;
10496 MonoObject
*obj
= mono_array_get (mb
->refs
, MonoObject
*, i
);
10498 if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
10499 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
10501 * The referenced DynamicMethod should already be created by the managed
10502 * code, except in the case of circular references. In that case, we store
10503 * method in the refs array, and fix it up later when the referenced
10504 * DynamicMethod is created.
10506 if (method
->mhandle
) {
10507 ref
= method
->mhandle
;
10509 /* FIXME: GC object stored in unmanaged memory */
10512 /* FIXME: GC object stored in unmanaged memory */
10513 method
->referenced_by
= g_slist_append (method
->referenced_by
, mb
);
10515 handle_class
= mono_defaults
.methodhandle_class
;
10517 ref
= resolve_object (mb
->module
->image
, obj
, &handle_class
, NULL
);
10520 mono_raise_exception (mono_get_exception_type_load (NULL
, NULL
));
10525 rmb
.refs
[i
] = ref
; /* FIXME: GC object stored in unmanaged memory (change also resolve_object() signature) */
10526 rmb
.refs
[i
+ 1] = handle_class
;
10529 klass
= mb
->owner
? mono_class_from_mono_type (mb
->owner
->type
) : mono_defaults
.object_class
;
10531 mb
->mhandle
= reflection_methodbuilder_to_mono_method (klass
, &rmb
, sig
);
10533 /* Fix up refs entries pointing at us */
10534 for (l
= mb
->referenced_by
; l
; l
= l
->next
) {
10535 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)l
->data
;
10536 MonoMethodWrapper
*wrapper
= (MonoMethodWrapper
*)method
->mhandle
;
10539 g_assert (method
->mhandle
);
10541 data
= (gpointer
*)wrapper
->method_data
;
10542 for (i
= 0; i
< GPOINTER_TO_UINT (data
[0]); i
+= 2) {
10543 if ((data
[i
+ 1] == mb
) && (data
[i
+ 1 + 1] == mono_defaults
.methodhandle_class
))
10544 data
[i
+ 1] = mb
->mhandle
;
10547 g_slist_free (mb
->referenced_by
);
10551 /* ilgen is no longer needed */
10555 #endif /* DISABLE_REFLECTION_EMIT */
10558 mono_reflection_destroy_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10563 mono_runtime_free_method (
10564 mono_object_get_domain ((MonoObject
*)mb
), mb
->mhandle
);
10569 * mono_reflection_is_valid_dynamic_token:
10571 * Returns TRUE if token is valid.
10575 mono_reflection_is_valid_dynamic_token (MonoDynamicImage
*image
, guint32 token
)
10577 return mono_g_hash_table_lookup (image
->tokens
, GUINT_TO_POINTER (token
)) != NULL
;
10580 #ifndef DISABLE_REFLECTION_EMIT
10583 * mono_reflection_lookup_dynamic_token:
10585 * Finish the Builder object pointed to by TOKEN and return the corresponding
10586 * runtime structure. If HANDLE_CLASS is not NULL, it is set to the class required by
10587 * mono_ldtoken. If valid_token is TRUE, assert if it is not found in the token->object
10590 * LOCKING: Take the loader lock
10593 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10595 MonoDynamicImage
*assembly
= (MonoDynamicImage
*)image
;
10599 mono_loader_lock ();
10600 obj
= mono_g_hash_table_lookup (assembly
->tokens
, GUINT_TO_POINTER (token
));
10601 mono_loader_unlock ();
10604 g_assert_not_reached ();
10610 handle_class
= &klass
;
10611 return resolve_object (image
, obj
, handle_class
, context
);
10615 * ensure_complete_type:
10617 * Ensure that KLASS is completed if it is a dynamic type, or references
10621 ensure_complete_type (MonoClass
*klass
)
10623 if (klass
->image
->dynamic
&& !klass
->wastypebuilder
) {
10624 MonoReflectionTypeBuilder
*tb
= klass
->reflection_info
;
10626 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10628 // Asserting here could break a lot of code
10629 //g_assert (klass->wastypebuilder);
10632 if (klass
->generic_class
) {
10633 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
10636 for (i
= 0; i
< inst
->type_argc
; ++i
) {
10637 ensure_complete_type (mono_class_from_mono_type (inst
->type_argv
[i
]));
10643 resolve_object (MonoImage
*image
, MonoObject
*obj
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10645 gpointer result
= NULL
;
10647 if (strcmp (obj
->vtable
->klass
->name
, "String") == 0) {
10648 result
= mono_string_intern ((MonoString
*)obj
);
10649 *handle_class
= NULL
;
10651 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoType") == 0) {
10652 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
10654 MonoType
*inflated
= mono_class_inflate_generic_type (tb
->type
, context
);
10655 result
= mono_class_from_mono_type (inflated
);
10656 mono_metadata_free_type (inflated
);
10658 result
= mono_class_from_mono_type (tb
->type
);
10660 *handle_class
= mono_defaults
.typehandle_class
;
10662 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoMethod") == 0 ||
10663 strcmp (obj
->vtable
->klass
->name
, "MonoCMethod") == 0 ||
10664 strcmp (obj
->vtable
->klass
->name
, "MonoGenericCMethod") == 0 ||
10665 strcmp (obj
->vtable
->klass
->name
, "MonoGenericMethod") == 0) {
10666 result
= ((MonoReflectionMethod
*)obj
)->method
;
10668 result
= mono_class_inflate_generic_method (result
, context
);
10669 *handle_class
= mono_defaults
.methodhandle_class
;
10671 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodBuilder") == 0) {
10672 MonoReflectionMethodBuilder
*mb
= (MonoReflectionMethodBuilder
*)obj
;
10673 result
= mb
->mhandle
;
10675 /* Type is not yet created */
10676 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)mb
->type
;
10678 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10681 * Hopefully this has been filled in by calling CreateType() on the
10685 * TODO: This won't work if the application finishes another
10686 * TypeBuilder instance instead of this one.
10688 result
= mb
->mhandle
;
10691 result
= mono_class_inflate_generic_method (result
, context
);
10692 *handle_class
= mono_defaults
.methodhandle_class
;
10693 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorBuilder") == 0) {
10694 MonoReflectionCtorBuilder
*cb
= (MonoReflectionCtorBuilder
*)obj
;
10696 result
= cb
->mhandle
;
10698 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)cb
->type
;
10700 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10701 result
= cb
->mhandle
;
10704 result
= mono_class_inflate_generic_method (result
, context
);
10705 *handle_class
= mono_defaults
.methodhandle_class
;
10706 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoField") == 0) {
10707 MonoClassField
*field
= ((MonoReflectionField
*)obj
)->field
;
10709 ensure_complete_type (field
->parent
);
10711 MonoType
*inflated
= mono_class_inflate_generic_type (&field
->parent
->byval_arg
, context
);
10712 MonoClass
*class = mono_class_from_mono_type (inflated
);
10713 MonoClassField
*inflated_field
;
10714 gpointer iter
= NULL
;
10715 mono_metadata_free_type (inflated
);
10716 while ((inflated_field
= mono_class_get_fields (class, &iter
))) {
10717 if (!strcmp (field
->name
, inflated_field
->name
))
10720 g_assert (inflated_field
&& !strcmp (field
->name
, inflated_field
->name
));
10721 result
= inflated_field
;
10725 *handle_class
= mono_defaults
.fieldhandle_class
;
10727 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldBuilder") == 0) {
10728 MonoReflectionFieldBuilder
*fb
= (MonoReflectionFieldBuilder
*)obj
;
10729 result
= fb
->handle
;
10732 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)fb
->typeb
;
10734 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10735 result
= fb
->handle
;
10738 if (fb
->handle
&& fb
->handle
->parent
->generic_container
) {
10739 MonoClass
*klass
= fb
->handle
->parent
;
10740 MonoType
*type
= mono_class_inflate_generic_type (&klass
->byval_arg
, context
);
10741 MonoClass
*inflated
= mono_class_from_mono_type (type
);
10743 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (fb
->handle
));
10745 mono_metadata_free_type (type
);
10747 *handle_class
= mono_defaults
.fieldhandle_class
;
10748 } else if (strcmp (obj
->vtable
->klass
->name
, "TypeBuilder") == 0) {
10749 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)obj
;
10752 klass
= tb
->type
.type
->data
.klass
;
10753 if (klass
->wastypebuilder
) {
10754 /* Already created */
10758 mono_domain_try_type_resolve (mono_domain_get (), NULL
, (MonoObject
*)tb
);
10759 result
= tb
->type
.type
->data
.klass
;
10762 *handle_class
= mono_defaults
.typehandle_class
;
10763 } else if (strcmp (obj
->vtable
->klass
->name
, "SignatureHelper") == 0) {
10764 MonoReflectionSigHelper
*helper
= (MonoReflectionSigHelper
*)obj
;
10765 MonoMethodSignature
*sig
;
10768 if (helper
->arguments
)
10769 nargs
= mono_array_length (helper
->arguments
);
10773 sig
= mono_metadata_signature_alloc (image
, nargs
);
10774 sig
->explicit_this
= helper
->call_conv
& 64 ? 1 : 0;
10775 sig
->hasthis
= helper
->call_conv
& 32 ? 1 : 0;
10777 if (helper
->call_conv
== 0) /* unmanaged */
10778 sig
->call_convention
= helper
->unmanaged_call_conv
- 1;
10780 if (helper
->call_conv
& 0x02)
10781 sig
->call_convention
= MONO_CALL_VARARG
;
10783 sig
->call_convention
= MONO_CALL_DEFAULT
;
10785 sig
->param_count
= nargs
;
10786 /* TODO: Copy type ? */
10787 sig
->ret
= helper
->return_type
->type
;
10788 for (i
= 0; i
< nargs
; ++i
) {
10789 MonoReflectionType
*rt
= mono_type_array_get (helper
->arguments
, i
);
10790 sig
->params
[i
] = rt
->type
;
10794 *handle_class
= NULL
;
10795 } else if (strcmp (obj
->vtable
->klass
->name
, "DynamicMethod") == 0) {
10796 MonoReflectionDynamicMethod
*method
= (MonoReflectionDynamicMethod
*)obj
;
10797 /* Already created by the managed code */
10798 g_assert (method
->mhandle
);
10799 result
= method
->mhandle
;
10800 *handle_class
= mono_defaults
.methodhandle_class
;
10801 } else if (strcmp (obj
->vtable
->klass
->name
, "GenericTypeParameterBuilder") == 0) {
10802 MonoReflectionType
*tb
= (MonoReflectionType
*)obj
;
10803 MonoType
*type
= mono_class_inflate_generic_type (tb
->type
, context
);
10804 result
= mono_class_from_mono_type (type
);
10805 *handle_class
= mono_defaults
.typehandle_class
;
10807 mono_metadata_free_type (type
);
10808 } else if (strcmp (obj
->vtable
->klass
->name
, "MonoGenericClass") == 0) {
10809 MonoReflectionGenericClass
*ref
= (MonoReflectionGenericClass
*)obj
;
10810 MonoType
*type
= mono_class_inflate_generic_type (ref
->type
.type
, context
);
10811 result
= mono_class_from_mono_type (type
);
10812 *handle_class
= mono_defaults
.typehandle_class
;
10814 mono_metadata_free_type (type
);
10815 } else if (strcmp (obj
->vtable
->klass
->name
, "FieldOnTypeBuilderInst") == 0) {
10816 MonoReflectionFieldOnTypeBuilderInst
*f
= (MonoReflectionFieldOnTypeBuilderInst
*)obj
;
10817 MonoClass
*inflated
;
10820 type
= mono_class_inflate_generic_type (f
->inst
->type
.type
, context
);
10821 inflated
= mono_class_from_mono_type (type
);
10823 g_assert (f
->fb
->handle
);
10824 result
= mono_class_get_field_from_name (inflated
, mono_field_get_name (f
->fb
->handle
));
10826 mono_metadata_free_type (type
);
10827 *handle_class
= mono_defaults
.fieldhandle_class
;
10828 } else if (strcmp (obj
->vtable
->klass
->name
, "ConstructorOnTypeBuilderInst") == 0) {
10829 MonoReflectionCtorOnTypeBuilderInst
*c
= (MonoReflectionCtorOnTypeBuilderInst
*)obj
;
10830 MonoType
*type
= mono_class_inflate_generic_type (c
->inst
->type
.type
, context
);
10831 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
10832 g_assert (c
->cb
->mhandle
);
10833 result
= inflate_mono_method (inflated_klass
, c
->cb
->mhandle
, (MonoObject
*)c
->cb
);
10834 *handle_class
= mono_defaults
.methodhandle_class
;
10835 mono_metadata_free_type (type
);
10836 } else if (strcmp (obj
->vtable
->klass
->name
, "MethodOnTypeBuilderInst") == 0) {
10837 MonoReflectionMethodOnTypeBuilderInst
*m
= (MonoReflectionMethodOnTypeBuilderInst
*)obj
;
10838 MonoType
*type
= mono_class_inflate_generic_type (m
->inst
->type
.type
, context
);
10839 MonoClass
*inflated_klass
= mono_class_from_mono_type (type
);
10840 g_assert (m
->mb
->mhandle
);
10841 result
= inflate_mono_method (inflated_klass
, m
->mb
->mhandle
, (MonoObject
*)m
->mb
);
10842 *handle_class
= mono_defaults
.methodhandle_class
;
10843 mono_metadata_free_type (type
);
10845 g_print (obj
->vtable
->klass
->name
);
10846 g_assert_not_reached ();
10851 #else /* DISABLE_REFLECTION_EMIT */
10854 mono_reflection_get_custom_attrs_blob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
10856 g_assert_not_reached ();
10861 mono_reflection_setup_internal_class (MonoReflectionTypeBuilder
*tb
)
10863 g_assert_not_reached ();
10867 mono_reflection_setup_generic_class (MonoReflectionTypeBuilder
*tb
)
10869 g_assert_not_reached ();
10873 mono_reflection_create_generic_class (MonoReflectionTypeBuilder
*tb
)
10875 g_assert_not_reached ();
10879 mono_reflection_create_internal_class (MonoReflectionTypeBuilder
*tb
)
10881 g_assert_not_reached ();
10885 mono_image_basic_init (MonoReflectionAssemblyBuilder
*assemblyb
)
10887 g_error ("This mono runtime was configured with --enable-minimal=reflection_emit, so System.Reflection.Emit is not supported.");
10891 mono_image_module_basic_init (MonoReflectionModuleBuilder
*moduleb
)
10893 g_assert_not_reached ();
10896 MonoReflectionModule
*
10897 mono_image_load_module_dynamic (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
10899 g_assert_not_reached ();
10904 mono_image_insert_string (MonoReflectionModuleBuilder
*module
, MonoString
*str
)
10906 g_assert_not_reached ();
10911 mono_image_create_method_token (MonoDynamicImage
*assembly
, MonoObject
*obj
, MonoArray
*opt_param_types
)
10913 g_assert_not_reached ();
10918 mono_image_create_token (MonoDynamicImage
*assembly
, MonoObject
*obj
,
10919 gboolean create_methodspec
, gboolean register_token
)
10921 g_assert_not_reached ();
10926 mono_image_register_token (MonoDynamicImage
*assembly
, guint32 token
, MonoObject
*obj
)
10931 mono_reflection_generic_class_initialize (MonoReflectionGenericClass
*type
, MonoArray
*methods
,
10932 MonoArray
*ctors
, MonoArray
*fields
, MonoArray
*properties
,
10935 g_assert_not_reached ();
10939 mono_reflection_get_dynamic_overrides (MonoClass
*klass
, MonoMethod
***overrides
, int *num_overrides
)
10942 *num_overrides
= 0;
10945 MonoReflectionEvent
*
10946 mono_reflection_event_builder_get_event_info (MonoReflectionTypeBuilder
*tb
, MonoReflectionEventBuilder
*eb
)
10948 g_assert_not_reached ();
10952 MonoReflectionType
*
10953 mono_reflection_create_runtime_class (MonoReflectionTypeBuilder
*tb
)
10955 g_assert_not_reached ();
10960 mono_reflection_initialize_generic_parameter (MonoReflectionGenericParam
*gparam
)
10962 g_assert_not_reached ();
10966 mono_reflection_sighelper_get_signature_local (MonoReflectionSigHelper
*sig
)
10968 g_assert_not_reached ();
10973 mono_reflection_sighelper_get_signature_field (MonoReflectionSigHelper
*sig
)
10975 g_assert_not_reached ();
10980 mono_reflection_create_dynamic_method (MonoReflectionDynamicMethod
*mb
)
10985 mono_reflection_lookup_dynamic_token (MonoImage
*image
, guint32 token
, gboolean valid_token
, MonoClass
**handle_class
, MonoGenericContext
*context
)
10990 #endif /* DISABLE_REFLECTION_EMIT */
10992 /* SECURITY_ACTION_* are defined in mono/metadata/tabledefs.h */
10993 const static guint32 declsec_flags_map
[] = {
10994 0x00000000, /* empty */
10995 MONO_DECLSEC_FLAG_REQUEST
, /* SECURITY_ACTION_REQUEST (x01) */
10996 MONO_DECLSEC_FLAG_DEMAND
, /* SECURITY_ACTION_DEMAND (x02) */
10997 MONO_DECLSEC_FLAG_ASSERT
, /* SECURITY_ACTION_ASSERT (x03) */
10998 MONO_DECLSEC_FLAG_DENY
, /* SECURITY_ACTION_DENY (x04) */
10999 MONO_DECLSEC_FLAG_PERMITONLY
, /* SECURITY_ACTION_PERMITONLY (x05) */
11000 MONO_DECLSEC_FLAG_LINKDEMAND
, /* SECURITY_ACTION_LINKDEMAND (x06) */
11001 MONO_DECLSEC_FLAG_INHERITANCEDEMAND
, /* SECURITY_ACTION_INHERITANCEDEMAND (x07) */
11002 MONO_DECLSEC_FLAG_REQUEST_MINIMUM
, /* SECURITY_ACTION_REQUEST_MINIMUM (x08) */
11003 MONO_DECLSEC_FLAG_REQUEST_OPTIONAL
, /* SECURITY_ACTION_REQUEST_OPTIONAL (x09) */
11004 MONO_DECLSEC_FLAG_REQUEST_REFUSE
, /* SECURITY_ACTION_REQUEST_REFUSE (x0A) */
11005 MONO_DECLSEC_FLAG_PREJIT_GRANT
, /* SECURITY_ACTION_PREJIT_GRANT (x0B) */
11006 MONO_DECLSEC_FLAG_PREJIT_DENY
, /* SECURITY_ACTION_PREJIT_DENY (x0C) */
11007 MONO_DECLSEC_FLAG_NONCAS_DEMAND
, /* SECURITY_ACTION_NONCAS_DEMAND (x0D) */
11008 MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
, /* SECURITY_ACTION_NONCAS_LINKDEMAND (x0E) */
11009 MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
, /* SECURITY_ACTION_NONCAS_INHERITANCEDEMAND (x0F) */
11010 MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
, /* SECURITY_ACTION_LINKDEMAND_CHOICE (x10) */
11011 MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
, /* SECURITY_ACTION_INHERITANCEDEMAND_CHOICE (x11) */
11012 MONO_DECLSEC_FLAG_DEMAND_CHOICE
, /* SECURITY_ACTION_DEMAND_CHOICE (x12) */
11016 * Returns flags that includes all available security action associated to the handle.
11017 * @token: metadata token (either for a class or a method)
11018 * @image: image where resides the metadata.
11021 mono_declsec_get_flags (MonoImage
*image
, guint32 token
)
11023 int index
= mono_metadata_declsec_from_index (image
, token
);
11024 MonoTableInfo
*t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11025 guint32 result
= 0;
11029 /* HasSecurity can be present for other, not specially encoded, attributes,
11030 e.g. SuppressUnmanagedCodeSecurityAttribute */
11034 for (i
= index
; i
< t
->rows
; i
++) {
11035 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11037 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11038 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
11041 action
= cols
[MONO_DECL_SECURITY_ACTION
];
11042 if ((action
>= MONO_DECLSEC_ACTION_MIN
) && (action
<= MONO_DECLSEC_ACTION_MAX
)) {
11043 result
|= declsec_flags_map
[action
];
11045 g_assert_not_reached ();
11052 * Get the security actions (in the form of flags) associated with the specified method.
11054 * @method: The method for which we want the declarative security flags.
11055 * Return the declarative security flags for the method (only).
11057 * Note: To keep MonoMethod size down we do not cache the declarative security flags
11058 * (except for the stack modifiers which are kept in the MonoJitInfo structure)
11061 mono_declsec_flags_from_method (MonoMethod
*method
)
11063 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11064 /* FIXME: No cache (for the moment) */
11065 guint32 idx
= mono_method_get_index (method
);
11066 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11067 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11068 return mono_declsec_get_flags (method
->klass
->image
, idx
);
11074 * Get the security actions (in the form of flags) associated with the specified class.
11076 * @klass: The class for which we want the declarative security flags.
11077 * Return the declarative security flags for the class.
11079 * Note: We cache the flags inside the MonoClass structure as this will get
11080 * called very often (at least for each method).
11083 mono_declsec_flags_from_class (MonoClass
*klass
)
11085 if (klass
->flags
& TYPE_ATTRIBUTE_HAS_SECURITY
) {
11086 if (!klass
->ext
|| !klass
->ext
->declsec_flags
) {
11089 idx
= mono_metadata_token_index (klass
->type_token
);
11090 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11091 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11092 mono_loader_lock ();
11093 mono_class_alloc_ext (klass
);
11094 mono_loader_unlock ();
11095 /* we cache the flags on classes */
11096 klass
->ext
->declsec_flags
= mono_declsec_get_flags (klass
->image
, idx
);
11098 return klass
->ext
->declsec_flags
;
11104 * Get the security actions (in the form of flags) associated with the specified assembly.
11106 * @assembly: The assembly for which we want the declarative security flags.
11107 * Return the declarative security flags for the assembly.
11110 mono_declsec_flags_from_assembly (MonoAssembly
*assembly
)
11112 guint32 idx
= 1; /* there is only one assembly */
11113 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11114 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
11115 return mono_declsec_get_flags (assembly
->image
, idx
);
11120 * Fill actions for the specific index (which may either be an encoded class token or
11121 * an encoded method token) from the metadata image.
11122 * Returns TRUE if some actions requiring code generation are present, FALSE otherwise.
11125 fill_actions_from_index (MonoImage
*image
, guint32 token
, MonoDeclSecurityActions
* actions
,
11126 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11128 MonoBoolean result
= FALSE
;
11130 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11131 int index
= mono_metadata_declsec_from_index (image
, token
);
11134 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11135 for (i
= index
; i
< t
->rows
; i
++) {
11136 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11138 if (cols
[MONO_DECL_SECURITY_PARENT
] != token
)
11141 /* if present only replace (class) permissions with method permissions */
11142 /* if empty accept either class or method permissions */
11143 if (cols
[MONO_DECL_SECURITY_ACTION
] == id_std
) {
11144 if (!actions
->demand
.blob
) {
11145 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11146 actions
->demand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11147 actions
->demand
.blob
= (char*) (blob
+ 2);
11148 actions
->demand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11151 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_noncas
) {
11152 if (!actions
->noncasdemand
.blob
) {
11153 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11154 actions
->noncasdemand
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11155 actions
->noncasdemand
.blob
= (char*) (blob
+ 2);
11156 actions
->noncasdemand
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11159 } else if (cols
[MONO_DECL_SECURITY_ACTION
] == id_choice
) {
11160 if (!actions
->demandchoice
.blob
) {
11161 const char *blob
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11162 actions
->demandchoice
.index
= cols
[MONO_DECL_SECURITY_PERMISSIONSET
];
11163 actions
->demandchoice
.blob
= (char*) (blob
+ 2);
11164 actions
->demandchoice
.size
= mono_metadata_decode_blob_size (blob
, &blob
);
11174 mono_declsec_get_class_demands_params (MonoClass
*klass
, MonoDeclSecurityActions
* demands
,
11175 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11177 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
11178 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11179 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11180 return fill_actions_from_index (klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
11184 mono_declsec_get_method_demands_params (MonoMethod
*method
, MonoDeclSecurityActions
* demands
,
11185 guint32 id_std
, guint32 id_noncas
, guint32 id_choice
)
11187 guint32 idx
= mono_method_get_index (method
);
11188 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11189 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11190 return fill_actions_from_index (method
->klass
->image
, idx
, demands
, id_std
, id_noncas
, id_choice
);
11194 * Collect all actions (that requires to generate code in mini) assigned for
11195 * the specified method.
11196 * Note: Don't use the content of actions if the function return FALSE.
11199 mono_declsec_get_demands (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
11201 guint32 mask
= MONO_DECLSEC_FLAG_DEMAND
| MONO_DECLSEC_FLAG_NONCAS_DEMAND
|
11202 MONO_DECLSEC_FLAG_DEMAND_CHOICE
;
11203 MonoBoolean result
= FALSE
;
11206 /* quick exit if no declarative security is present in the metadata */
11207 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11210 /* we want the original as the wrapper is "free" of the security informations */
11211 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11212 method
= mono_marshal_method_from_wrapper (method
);
11217 /* First we look for method-level attributes */
11218 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11219 mono_class_init (method
->klass
);
11220 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11222 result
= mono_declsec_get_method_demands_params (method
, demands
,
11223 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
11226 /* Here we use (or create) the class declarative cache to look for demands */
11227 flags
= mono_declsec_flags_from_class (method
->klass
);
11228 if (flags
& mask
) {
11230 mono_class_init (method
->klass
);
11231 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11233 result
|= mono_declsec_get_class_demands_params (method
->klass
, demands
,
11234 SECURITY_ACTION_DEMAND
, SECURITY_ACTION_NONCASDEMAND
, SECURITY_ACTION_DEMANDCHOICE
);
11237 /* The boolean return value is used as a shortcut in case nothing needs to
11238 be generated (e.g. LinkDemand[Choice] and InheritanceDemand[Choice]) */
11244 * Collect all Link actions: LinkDemand, NonCasLinkDemand and LinkDemandChoice (2.0).
11246 * Note: Don't use the content of actions if the function return FALSE.
11249 mono_declsec_get_linkdemands (MonoMethod
*method
, MonoDeclSecurityActions
* klass
, MonoDeclSecurityActions
*cmethod
)
11251 MonoBoolean result
= FALSE
;
11254 /* quick exit if no declarative security is present in the metadata */
11255 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11258 /* we want the original as the wrapper is "free" of the security informations */
11259 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11260 method
= mono_marshal_method_from_wrapper (method
);
11265 /* results are independant - zeroize both */
11266 memset (cmethod
, 0, sizeof (MonoDeclSecurityActions
));
11267 memset (klass
, 0, sizeof (MonoDeclSecurityActions
));
11269 /* First we look for method-level attributes */
11270 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11271 mono_class_init (method
->klass
);
11273 result
= mono_declsec_get_method_demands_params (method
, cmethod
,
11274 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
11277 /* Here we use (or create) the class declarative cache to look for demands */
11278 flags
= mono_declsec_flags_from_class (method
->klass
);
11279 if (flags
& (MONO_DECLSEC_FLAG_LINKDEMAND
| MONO_DECLSEC_FLAG_NONCAS_LINKDEMAND
| MONO_DECLSEC_FLAG_LINKDEMAND_CHOICE
)) {
11280 mono_class_init (method
->klass
);
11282 result
|= mono_declsec_get_class_demands_params (method
->klass
, klass
,
11283 SECURITY_ACTION_LINKDEMAND
, SECURITY_ACTION_NONCASLINKDEMAND
, SECURITY_ACTION_LINKDEMANDCHOICE
);
11290 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11292 * @klass The inherited class - this is the class that provides the security check (attributes)
11294 * return TRUE if inheritance demands (any kind) are present, FALSE otherwise.
11296 * Note: Don't use the content of actions if the function return FALSE.
11299 mono_declsec_get_inheritdemands_class (MonoClass
*klass
, MonoDeclSecurityActions
* demands
)
11301 MonoBoolean result
= FALSE
;
11304 /* quick exit if no declarative security is present in the metadata */
11305 if (!klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11308 /* Here we use (or create) the class declarative cache to look for demands */
11309 flags
= mono_declsec_flags_from_class (klass
);
11310 if (flags
& (MONO_DECLSEC_FLAG_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_NONCAS_INHERITANCEDEMAND
| MONO_DECLSEC_FLAG_INHERITANCEDEMAND_CHOICE
)) {
11311 mono_class_init (klass
);
11312 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11314 result
|= mono_declsec_get_class_demands_params (klass
, demands
,
11315 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
11322 * Collect all Inherit actions: InheritanceDemand, NonCasInheritanceDemand and InheritanceDemandChoice (2.0).
11324 * Note: Don't use the content of actions if the function return FALSE.
11327 mono_declsec_get_inheritdemands_method (MonoMethod
*method
, MonoDeclSecurityActions
* demands
)
11329 /* quick exit if no declarative security is present in the metadata */
11330 if (!method
->klass
->image
->tables
[MONO_TABLE_DECLSECURITY
].rows
)
11333 /* we want the original as the wrapper is "free" of the security informations */
11334 if (method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_NATIVE
|| method
->wrapper_type
== MONO_WRAPPER_MANAGED_TO_MANAGED
) {
11335 method
= mono_marshal_method_from_wrapper (method
);
11340 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11341 mono_class_init (method
->klass
);
11342 memset (demands
, 0, sizeof (MonoDeclSecurityActions
));
11344 return mono_declsec_get_method_demands_params (method
, demands
,
11345 SECURITY_ACTION_INHERITDEMAND
, SECURITY_ACTION_NONCASINHERITANCE
, SECURITY_ACTION_INHERITDEMANDCHOICE
);
11352 get_declsec_action (MonoImage
*image
, guint32 token
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11354 guint32 cols
[MONO_DECL_SECURITY_SIZE
];
11358 int index
= mono_metadata_declsec_from_index (image
, token
);
11362 t
= &image
->tables
[MONO_TABLE_DECLSECURITY
];
11363 for (i
= index
; i
< t
->rows
; i
++) {
11364 mono_metadata_decode_row (t
, i
, cols
, MONO_DECL_SECURITY_SIZE
);
11366 /* shortcut - index are ordered */
11367 if (token
!= cols
[MONO_DECL_SECURITY_PARENT
])
11370 if (cols
[MONO_DECL_SECURITY_ACTION
] == action
) {
11371 const char *metadata
= mono_metadata_blob_heap (image
, cols
[MONO_DECL_SECURITY_PERMISSIONSET
]);
11372 entry
->blob
= (char*) (metadata
+ 2);
11373 entry
->size
= mono_metadata_decode_blob_size (metadata
, &metadata
);
11382 mono_declsec_get_method_action (MonoMethod
*method
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11384 if (method
->flags
& METHOD_ATTRIBUTE_HAS_SECURITY
) {
11385 guint32 idx
= mono_method_get_index (method
);
11386 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11387 idx
|= MONO_HAS_DECL_SECURITY_METHODDEF
;
11388 return get_declsec_action (method
->klass
->image
, idx
, action
, entry
);
11394 mono_declsec_get_class_action (MonoClass
*klass
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11397 guint32 flags
= mono_declsec_flags_from_class (klass
);
11398 if (declsec_flags_map
[action
] & flags
) {
11399 guint32 idx
= mono_metadata_token_index (klass
->type_token
);
11400 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11401 idx
|= MONO_HAS_DECL_SECURITY_TYPEDEF
;
11402 return get_declsec_action (klass
->image
, idx
, action
, entry
);
11408 mono_declsec_get_assembly_action (MonoAssembly
*assembly
, guint32 action
, MonoDeclSecurityEntry
*entry
)
11410 guint32 idx
= 1; /* there is only one assembly */
11411 idx
<<= MONO_HAS_DECL_SECURITY_BITS
;
11412 idx
|= MONO_HAS_DECL_SECURITY_ASSEMBLY
;
11414 return get_declsec_action (assembly
->image
, idx
, action
, entry
);
11418 mono_reflection_call_is_assignable_to (MonoClass
*klass
, MonoClass
*oklass
)
11420 MonoObject
*res
, *exc
;
11422 static MonoClass
*System_Reflection_Emit_TypeBuilder
= NULL
;
11423 static MonoMethod
*method
= NULL
;
11425 if (!System_Reflection_Emit_TypeBuilder
) {
11426 System_Reflection_Emit_TypeBuilder
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection.Emit", "TypeBuilder");
11427 g_assert (System_Reflection_Emit_TypeBuilder
);
11429 if (method
== NULL
) {
11430 method
= mono_class_get_method_from_name (System_Reflection_Emit_TypeBuilder
, "IsAssignableTo", 1);
11435 * The result of mono_type_get_object () might be a System.MonoType but we
11436 * need a TypeBuilder so use klass->reflection_info.
11438 g_assert (klass
->reflection_info
);
11439 g_assert (!strcmp (((MonoObject
*)(klass
->reflection_info
))->vtable
->klass
->name
, "TypeBuilder"));
11441 params
[0] = mono_type_get_object (mono_domain_get (), &oklass
->byval_arg
);
11443 res
= mono_runtime_invoke (method
, (MonoObject
*)(klass
->reflection_info
), params
, &exc
);
11447 return *(MonoBoolean
*)mono_object_unbox (res
);