5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/io-layer/io-layer.h>
86 #include <mono/utils/monobitset.h>
87 #include <mono/utils/mono-time.h>
88 #include <mono/utils/mono-proclib.h>
89 #include <mono/utils/mono-string.h>
90 #include <mono/utils/mono-error-internals.h>
91 #include <mono/utils/mono-mmap.h>
92 #include <mono/utils/mono-io-portability.h>
93 #include <mono/utils/mono-digest.h>
94 #include <mono/utils/bsearch.h>
95 #include <mono/utils/mono-os-mutex.h>
96 #include <mono/utils/mono-threads.h>
98 #if defined (HOST_WIN32)
102 #include "decimal-ms.h"
103 #include "number-ms.h"
105 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
106 #include <sys/utsname.h>
109 extern MonoString
* ves_icall_System_Environment_GetOSVersionString (void);
111 ICALL_EXPORT MonoReflectionAssembly
* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
113 /* Lazy class loading functions */
114 static GENERATE_GET_CLASS_WITH_CACHE (system_version
, System
, Version
)
115 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name
, System
.Reflection
, AssemblyName
)
116 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info
, System
.Reflection
, ConstructorInfo
)
117 static GENERATE_GET_CLASS_WITH_CACHE (property_info
, System
.Reflection
, PropertyInfo
)
118 static GENERATE_GET_CLASS_WITH_CACHE (event_info
, System
.Reflection
, EventInfo
)
119 static GENERATE_GET_CLASS_WITH_CACHE (module
, System
.Reflection
, Module
)
122 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
, MonoError
*error
);
124 static inline MonoBoolean
125 is_generic_parameter (MonoType
*type
)
127 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
131 mono_class_init_checked (MonoClass
*klass
, MonoError
*error
)
133 mono_error_init (error
);
135 if (!mono_class_init (klass
))
136 mono_error_set_for_class_failure (error
, klass
);
139 ICALL_EXPORT MonoObject
*
140 ves_icall_System_Array_GetValueImpl (MonoArray
*arr
, guint32 pos
)
146 MonoObject
*result
= NULL
;
148 ac
= (MonoClass
*)arr
->obj
.vtable
->klass
;
150 esize
= mono_array_element_size (ac
);
151 ea
= (gpointer
*)((char*)arr
->vector
+ (pos
* esize
));
153 if (ac
->element_class
->valuetype
) {
154 result
= mono_value_box_checked (arr
->obj
.vtable
->domain
, ac
->element_class
, ea
, &error
);
155 mono_error_set_pending_exception (&error
);
157 result
= (MonoObject
*)*ea
;
161 ICALL_EXPORT MonoObject
*
162 ves_icall_System_Array_GetValue (MonoArray
*arr
, MonoArray
*idxs
)
168 MONO_CHECK_ARG_NULL (idxs
, NULL
);
171 ic
= (MonoClass
*)io
->obj
.vtable
->klass
;
173 ac
= (MonoClass
*)arr
->obj
.vtable
->klass
;
175 g_assert (ic
->rank
== 1);
176 if (io
->bounds
!= NULL
|| io
->max_length
!= ac
->rank
) {
177 mono_set_pending_exception (mono_get_exception_argument (NULL
, NULL
));
181 ind
= (gint32
*)io
->vector
;
183 if (arr
->bounds
== NULL
) {
184 if (*ind
< 0 || *ind
>= arr
->max_length
) {
185 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (arr
, *ind
);
192 for (i
= 0; i
< ac
->rank
; i
++) {
193 if ((ind
[i
] < arr
->bounds
[i
].lower_bound
) ||
194 (ind
[i
] >= (mono_array_lower_bound_t
)arr
->bounds
[i
].length
+ arr
->bounds
[i
].lower_bound
)) {
195 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
200 pos
= ind
[0] - arr
->bounds
[0].lower_bound
;
201 for (i
= 1; i
< ac
->rank
; i
++)
202 pos
= pos
* arr
->bounds
[i
].length
+ ind
[i
] -
203 arr
->bounds
[i
].lower_bound
;
205 return ves_icall_System_Array_GetValueImpl (arr
, pos
);
209 ves_icall_System_Array_SetValueImpl (MonoArray
*arr
, MonoObject
*value
, guint32 pos
)
212 MonoClass
*ac
, *vc
, *ec
;
221 mono_error_init (&error
);
224 vc
= value
->vtable
->klass
;
228 ac
= arr
->obj
.vtable
->klass
;
229 ec
= ac
->element_class
;
231 esize
= mono_array_element_size (ac
);
232 ea
= (gpointer
*)((char*)arr
->vector
+ (pos
* esize
));
233 va
= (gpointer
*)((char*)value
+ sizeof (MonoObject
));
235 if (mono_class_is_nullable (ec
)) {
236 mono_nullable_init ((guint8
*)ea
, value
, ec
);
241 mono_gc_bzero_atomic (ea
, esize
);
245 #define NO_WIDENING_CONVERSION G_STMT_START{\
246 mono_set_pending_exception (mono_get_exception_argument ( \
247 "value", "not a widening conversion")); \
251 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
252 if (esize < vsize + (extra)) { \
253 mono_set_pending_exception (mono_get_exception_argument ( \
254 "value", "not a widening conversion")); \
259 #define INVALID_CAST G_STMT_START{ \
260 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
261 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
265 /* Check element (destination) type. */
266 switch (ec
->byval_arg
.type
) {
267 case MONO_TYPE_STRING
:
268 switch (vc
->byval_arg
.type
) {
269 case MONO_TYPE_STRING
:
275 case MONO_TYPE_BOOLEAN
:
276 switch (vc
->byval_arg
.type
) {
277 case MONO_TYPE_BOOLEAN
:
290 NO_WIDENING_CONVERSION
;
299 if (!ec
->valuetype
) {
300 gboolean castOk
= (NULL
!= mono_object_isinst_checked (value
, ec
, &error
));
301 if (mono_error_set_pending_exception (&error
))
305 mono_gc_wbarrier_set_arrayref (arr
, ea
, (MonoObject
*)value
);
309 if (mono_object_isinst_checked (value
, ec
, &error
)) {
310 if (ec
->has_references
)
311 mono_value_copy (ea
, (char*)value
+ sizeof (MonoObject
), ec
);
313 mono_gc_memmove_atomic (ea
, (char *)value
+ sizeof (MonoObject
), esize
);
316 if (mono_error_set_pending_exception (&error
))
322 vsize
= mono_class_instance_size (vc
) - sizeof (MonoObject
);
324 et
= ec
->byval_arg
.type
;
325 if (et
== MONO_TYPE_VALUETYPE
&& ec
->byval_arg
.data
.klass
->enumtype
)
326 et
= mono_class_enum_basetype (ec
->byval_arg
.data
.klass
)->type
;
328 vt
= vc
->byval_arg
.type
;
329 if (vt
== MONO_TYPE_VALUETYPE
&& vc
->byval_arg
.data
.klass
->enumtype
)
330 vt
= mono_class_enum_basetype (vc
->byval_arg
.data
.klass
)->type
;
332 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
338 case MONO_TYPE_CHAR: \
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) u64; \
342 /* You can't assign a signed value to an unsigned array. */ \
347 /* You can't assign a floating point number to an integer array. */ \
350 NO_WIDENING_CONVERSION; \
354 #define ASSIGN_SIGNED(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) i64; \
363 /* You can assign an unsigned value to a signed array if the array's */ \
364 /* element size is larger than the value size. */ \
369 case MONO_TYPE_CHAR: \
370 CHECK_WIDENING_CONVERSION(1); \
371 *(etype *) ea = (etype) u64; \
373 /* You can't assign a floating point number to an integer array. */ \
376 NO_WIDENING_CONVERSION; \
380 #define ASSIGN_REAL(etype) G_STMT_START{\
384 CHECK_WIDENING_CONVERSION(0); \
385 *(etype *) ea = (etype) r64; \
387 /* All integer values fit into a floating point array, so we don't */ \
388 /* need to CHECK_WIDENING_CONVERSION here. */ \
393 *(etype *) ea = (etype) i64; \
399 case MONO_TYPE_CHAR: \
400 *(etype *) ea = (etype) u64; \
407 u64
= *(guint8
*) va
;
410 u64
= *(guint16
*) va
;
413 u64
= *(guint32
*) va
;
416 u64
= *(guint64
*) va
;
422 i64
= *(gint16
*) va
;
425 i64
= *(gint32
*) va
;
428 i64
= *(gint64
*) va
;
431 r64
= *(gfloat
*) va
;
434 r64
= *(gdouble
*) va
;
437 u64
= *(guint16
*) va
;
439 case MONO_TYPE_BOOLEAN
:
440 /* Boolean is only compatible with itself. */
453 NO_WIDENING_CONVERSION
;
460 /* If we can't do a direct copy, let's try a widening conversion. */
463 ASSIGN_UNSIGNED (guint16
);
465 ASSIGN_UNSIGNED (guint8
);
467 ASSIGN_UNSIGNED (guint16
);
469 ASSIGN_UNSIGNED (guint32
);
471 ASSIGN_UNSIGNED (guint64
);
473 ASSIGN_SIGNED (gint8
);
475 ASSIGN_SIGNED (gint16
);
477 ASSIGN_SIGNED (gint32
);
479 ASSIGN_SIGNED (gint64
);
481 ASSIGN_REAL (gfloat
);
483 ASSIGN_REAL (gdouble
);
487 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
491 #undef NO_WIDENING_CONVERSION
492 #undef CHECK_WIDENING_CONVERSION
493 #undef ASSIGN_UNSIGNED
499 ves_icall_System_Array_SetValue (MonoArray
*arr
, MonoObject
*value
,
505 MONO_CHECK_ARG_NULL (idxs
,);
507 ic
= idxs
->obj
.vtable
->klass
;
508 ac
= arr
->obj
.vtable
->klass
;
510 g_assert (ic
->rank
== 1);
511 if (idxs
->bounds
!= NULL
|| idxs
->max_length
!= ac
->rank
) {
512 mono_set_pending_exception (mono_get_exception_argument (NULL
, NULL
));
516 ind
= (gint32
*)idxs
->vector
;
518 if (arr
->bounds
== NULL
) {
519 if (*ind
< 0 || *ind
>= arr
->max_length
) {
520 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
524 ves_icall_System_Array_SetValueImpl (arr
, value
, *ind
);
528 for (i
= 0; i
< ac
->rank
; i
++)
529 if ((ind
[i
] < arr
->bounds
[i
].lower_bound
) ||
530 (ind
[i
] >= (mono_array_lower_bound_t
)arr
->bounds
[i
].length
+ arr
->bounds
[i
].lower_bound
)) {
531 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
535 pos
= ind
[0] - arr
->bounds
[0].lower_bound
;
536 for (i
= 1; i
< ac
->rank
; i
++)
537 pos
= pos
* arr
->bounds
[i
].length
+ ind
[i
] -
538 arr
->bounds
[i
].lower_bound
;
540 ves_icall_System_Array_SetValueImpl (arr
, value
, pos
);
543 ICALL_EXPORT MonoArray
*
544 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType
*type
, MonoArray
*lengths
, MonoArray
*bounds
)
547 MonoClass
*aklass
, *klass
;
550 gboolean bounded
= FALSE
;
552 MONO_CHECK_ARG_NULL (type
, NULL
);
553 MONO_CHECK_ARG_NULL (lengths
, NULL
);
555 MONO_CHECK_ARG (lengths
, mono_array_length (lengths
) > 0, NULL
);
557 MONO_CHECK_ARG (bounds
, mono_array_length (lengths
) == mono_array_length (bounds
), NULL
);
559 for (i
= 0; i
< mono_array_length (lengths
); i
++) {
560 if (mono_array_get (lengths
, gint32
, i
) < 0) {
561 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL
));
566 klass
= mono_class_from_mono_type (type
->type
);
567 mono_class_init_checked (klass
, &error
);
568 if (mono_error_set_pending_exception (&error
))
571 if (bounds
&& (mono_array_length (bounds
) == 1) && (mono_array_get (bounds
, gint32
, 0) != 0))
572 /* vectors are not the same as one dimensional arrays with no-zero bounds */
577 aklass
= mono_bounded_array_class_get (klass
, mono_array_length (lengths
), bounded
);
579 sizes
= (uintptr_t *)alloca (aklass
->rank
* sizeof(intptr_t) * 2);
580 for (i
= 0; i
< aklass
->rank
; ++i
) {
581 sizes
[i
] = mono_array_get (lengths
, guint32
, i
);
583 sizes
[i
+ aklass
->rank
] = mono_array_get (bounds
, gint32
, i
);
585 sizes
[i
+ aklass
->rank
] = 0;
588 array
= mono_array_new_full_checked (mono_object_domain (type
), aklass
, sizes
, (intptr_t*)sizes
+ aklass
->rank
, &error
);
589 mono_error_set_pending_exception (&error
);
594 ICALL_EXPORT MonoArray
*
595 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType
*type
, MonoArray
*lengths
, MonoArray
*bounds
)
598 MonoClass
*aklass
, *klass
;
601 gboolean bounded
= FALSE
;
603 MONO_CHECK_ARG_NULL (type
, NULL
);
604 MONO_CHECK_ARG_NULL (lengths
, NULL
);
606 MONO_CHECK_ARG (lengths
, mono_array_length (lengths
) > 0, NULL
);
608 MONO_CHECK_ARG (bounds
, mono_array_length (lengths
) == mono_array_length (bounds
), NULL
);
610 for (i
= 0; i
< mono_array_length (lengths
); i
++) {
611 if ((mono_array_get (lengths
, gint64
, i
) < 0) ||
612 (mono_array_get (lengths
, gint64
, i
) > MONO_ARRAY_MAX_INDEX
)) {
613 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL
));
618 klass
= mono_class_from_mono_type (type
->type
);
619 mono_class_init_checked (klass
, &error
);
620 if (mono_error_set_pending_exception (&error
))
623 if (bounds
&& (mono_array_length (bounds
) == 1) && (mono_array_get (bounds
, gint64
, 0) != 0))
624 /* vectors are not the same as one dimensional arrays with no-zero bounds */
629 aklass
= mono_bounded_array_class_get (klass
, mono_array_length (lengths
), bounded
);
631 sizes
= (uintptr_t *)alloca (aklass
->rank
* sizeof(intptr_t) * 2);
632 for (i
= 0; i
< aklass
->rank
; ++i
) {
633 sizes
[i
] = mono_array_get (lengths
, guint64
, i
);
635 sizes
[i
+ aklass
->rank
] = (mono_array_size_t
) mono_array_get (bounds
, guint64
, i
);
637 sizes
[i
+ aklass
->rank
] = 0;
640 array
= mono_array_new_full_checked (mono_object_domain (type
), aklass
, sizes
, (intptr_t*)sizes
+ aklass
->rank
, &error
);
641 mono_error_set_pending_exception (&error
);
647 ves_icall_System_Array_GetRank (MonoObject
*arr
)
649 return arr
->vtable
->klass
->rank
;
653 ves_icall_System_Array_GetLength (MonoArray
*arr
, gint32 dimension
)
655 gint32 rank
= arr
->obj
.vtable
->klass
->rank
;
658 if ((dimension
< 0) || (dimension
>= rank
)) {
659 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
663 if (arr
->bounds
== NULL
)
664 length
= arr
->max_length
;
666 length
= arr
->bounds
[dimension
].length
;
668 #ifdef MONO_BIG_ARRAYS
669 if (length
> G_MAXINT32
) {
670 mono_set_pending_exception (mono_get_exception_overflow ());
678 ves_icall_System_Array_GetLongLength (MonoArray
*arr
, gint32 dimension
)
680 gint32 rank
= arr
->obj
.vtable
->klass
->rank
;
682 if ((dimension
< 0) || (dimension
>= rank
)) {
683 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
687 if (arr
->bounds
== NULL
)
688 return arr
->max_length
;
690 return arr
->bounds
[dimension
].length
;
694 ves_icall_System_Array_GetLowerBound (MonoArray
*arr
, gint32 dimension
)
696 gint32 rank
= arr
->obj
.vtable
->klass
->rank
;
698 if ((dimension
< 0) || (dimension
>= rank
)) {
699 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
703 if (arr
->bounds
== NULL
)
706 return arr
->bounds
[dimension
].lower_bound
;
710 ves_icall_System_Array_ClearInternal (MonoArray
*arr
, int idx
, int length
)
712 int sz
= mono_array_element_size (mono_object_class (arr
));
713 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr
, sz
, idx
), length
* sz
);
716 ICALL_EXPORT MonoArray
*
717 ves_icall_System_Array_Clone (MonoArray
*arr
)
720 MonoArray
*result
= mono_array_clone_checked (arr
, &error
);
721 mono_error_set_pending_exception (&error
);
725 ICALL_EXPORT gboolean
726 ves_icall_System_Array_FastCopy (MonoArray
*source
, int source_idx
, MonoArray
* dest
, int dest_idx
, int length
)
731 MonoVTable
*src_vtable
;
732 MonoVTable
*dest_vtable
;
733 MonoClass
*src_class
;
734 MonoClass
*dest_class
;
736 src_vtable
= source
->obj
.vtable
;
737 dest_vtable
= dest
->obj
.vtable
;
739 if (src_vtable
->rank
!= dest_vtable
->rank
)
742 if (source
->bounds
|| dest
->bounds
)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx
+ length
> mono_array_length_fast (dest
)) ||
747 (source_idx
+ length
> mono_array_length_fast (source
)))
750 src_class
= src_vtable
->klass
->element_class
;
751 dest_class
= dest_vtable
->klass
->element_class
;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
758 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
760 if (src_class
== mono_defaults
.object_class
&& dest_class
->valuetype
)
763 /* Check if we're copying a char[] <==> (u)short[] */
764 if (src_class
!= dest_class
) {
765 if (dest_class
->valuetype
|| dest_class
->enumtype
|| src_class
->valuetype
|| src_class
->enumtype
)
768 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
769 if (!mono_class_is_subclass_of (src_class
, dest_class
, FALSE
))
773 if (dest_class
->valuetype
) {
774 element_size
= mono_array_element_size (source
->obj
.vtable
->klass
);
775 source_addr
= mono_array_addr_with_size_fast (source
, element_size
, source_idx
);
776 if (dest_class
->has_references
) {
777 mono_value_copy_array (dest
, dest_idx
, source_addr
, length
);
779 dest_addr
= mono_array_addr_with_size_fast (dest
, element_size
, dest_idx
);
780 mono_gc_memmove_atomic (dest_addr
, source_addr
, element_size
* length
);
783 mono_array_memcpy_refs_fast (dest
, dest_idx
, source
, source_idx
, length
);
790 ves_icall_System_Array_GetGenericValueImpl (MonoArray
*arr
, guint32 pos
, gpointer value
)
796 ac
= (MonoClass
*)arr
->obj
.vtable
->klass
;
798 esize
= mono_array_element_size (ac
);
799 ea
= (gpointer
*)((char*)arr
->vector
+ (pos
* esize
));
801 mono_gc_memmove_atomic (value
, ea
, esize
);
805 ves_icall_System_Array_SetGenericValueImpl (MonoArray
*arr
, guint32 pos
, gpointer value
)
811 ac
= (MonoClass
*)arr
->obj
.vtable
->klass
;
812 ec
= ac
->element_class
;
814 esize
= mono_array_element_size (ac
);
815 ea
= (gpointer
*)((char*)arr
->vector
+ (pos
* esize
));
817 if (MONO_TYPE_IS_REFERENCE (&ec
->byval_arg
)) {
818 g_assert (esize
== sizeof (gpointer
));
819 mono_gc_wbarrier_generic_store (ea
, *(MonoObject
**)value
);
821 g_assert (ec
->inited
);
822 g_assert (esize
== mono_class_value_size (ec
, NULL
));
823 if (ec
->has_references
)
824 mono_gc_wbarrier_value_copy (ea
, value
, 1, ec
);
826 mono_gc_memmove_atomic (ea
, value
, esize
);
831 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray
*array
, MonoClassField
*field_handle
)
833 MonoClass
*klass
= array
->obj
.vtable
->klass
;
834 guint32 size
= mono_array_element_size (klass
);
835 MonoType
*type
= mono_type_get_underlying_type (&klass
->element_class
->byval_arg
);
837 const char *field_data
;
839 if (MONO_TYPE_IS_REFERENCE (type
) || type
->type
== MONO_TYPE_VALUETYPE
) {
840 MonoException
*exc
= mono_get_exception_argument("array",
841 "Cannot initialize array of non-primitive type.");
842 mono_set_pending_exception (exc
);
846 if (!(field_handle
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
)) {
847 MonoException
*exc
= mono_get_exception_argument("field_handle",
848 "Field doesn't have an RVA");
849 mono_set_pending_exception (exc
);
853 size
*= array
->max_length
;
854 field_data
= mono_field_get_data (field_handle
);
856 if (size
> mono_type_size (field_handle
->type
, &align
)) {
857 MonoException
*exc
= mono_get_exception_argument("field_handle",
858 "Field not large enough to fill array");
859 mono_set_pending_exception (exc
);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
868 nEnt = (size / sizeof(guint ## n)); \
870 for (i = 0; i < nEnt; i++) { \
871 data[i] = read ## n (&src[i]); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type
->type
) {
894 memcpy (mono_array_addr (array
, char, 0), field_data
, size
);
898 memcpy (mono_array_addr (array
, char, 0), field_data
, size
);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
905 return offsetof (MonoString
, chars
);
908 ICALL_EXPORT MonoObject
*
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject
*obj
)
911 if ((obj
== NULL
) || (! (obj
->vtable
->klass
->valuetype
)))
915 MonoObject
*ret
= mono_object_clone_checked (obj
, &error
);
916 mono_error_set_pending_exception (&error
);
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType
*handle
)
929 MONO_CHECK_ARG_NULL (handle
,);
931 klass
= mono_class_from_mono_type (handle
);
932 MONO_CHECK_ARG (handle
, klass
,);
934 if (klass
->generic_container
)
937 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, &error
);
938 if (!is_ok (&error
)) {
939 mono_error_set_pending_exception (&error
);
943 /* This will call the type constructor */
944 if (!mono_runtime_class_init_full (vtable
, &error
))
945 mono_error_set_pending_exception (&error
);
949 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage
*image
)
953 mono_image_check_for_module_cctor (image
);
954 if (image
->has_module_cctor
) {
955 MonoClass
*module_klass
= mono_class_get_checked (image
, MONO_TOKEN_TYPE_DEF
| 1, &error
);
956 if (!mono_error_ok (&error
)) {
957 mono_error_set_pending_exception (&error
);
960 /*It's fine to raise the exception here*/
961 MonoVTable
* vtable
= mono_class_vtable_full (mono_domain_get (), module_klass
, &error
);
962 if (!is_ok (&error
)) {
963 mono_error_set_pending_exception (&error
);
966 if (!mono_runtime_class_init_full (vtable
, &error
))
967 mono_error_set_pending_exception (&error
);
971 ICALL_EXPORT MonoBoolean
972 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
977 /* later make this configurable and per-arch */
978 int min_size
= 4096 * 4 * sizeof (void*);
979 mono_thread_info_get_stack_bounds (&stack_addr
, &stack_size
);
980 /* if we have no info we are optimistic and assume there is enough room */
984 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
988 current
= (guint8
*)&stack_addr
;
989 if (current
> stack_addr
) {
990 if ((current
- stack_addr
) < min_size
)
993 if (current
- (stack_addr
- stack_size
) < min_size
)
999 ICALL_EXPORT MonoObject
*
1000 ves_icall_System_Object_MemberwiseClone (MonoObject
*this_obj
)
1003 MonoObject
*ret
= mono_object_clone_checked (this_obj
, &error
);
1004 mono_error_set_pending_exception (&error
);
1010 ves_icall_System_ValueType_InternalGetHashCode (MonoObject
*this_obj
, MonoArray
**fields
)
1014 MonoObject
**values
= NULL
;
1017 gint32 result
= (int)(gsize
)mono_defaults
.int32_class
;
1018 MonoClassField
* field
;
1021 klass
= mono_object_class (this_obj
);
1023 if (mono_class_num_fields (klass
) == 0)
1027 * Compute the starting value of the hashcode for fields of primitive
1028 * types, and return the remaining fields in an array to the managed side.
1029 * This way, we can avoid costly reflection operations in managed code.
1032 while ((field
= mono_class_get_fields (klass
, &iter
))) {
1033 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1035 if (mono_field_is_deleted (field
))
1037 /* FIXME: Add more types */
1038 switch (field
->type
->type
) {
1040 result
^= *(gint32
*)((guint8
*)this_obj
+ field
->offset
);
1042 case MONO_TYPE_STRING
: {
1044 s
= *(MonoString
**)((guint8
*)this_obj
+ field
->offset
);
1046 result
^= mono_string_hash (s
);
1051 values
= g_newa (MonoObject
*, mono_class_num_fields (klass
));
1052 o
= mono_field_get_value_object_checked (mono_object_domain (this_obj
), field
, this_obj
, &error
);
1053 if (!is_ok (&error
)) {
1054 mono_error_set_pending_exception (&error
);
1057 values
[count
++] = o
;
1063 MonoArray
*fields_arr
= mono_array_new_checked (mono_domain_get (), mono_defaults
.object_class
, count
, &error
);
1064 if (mono_error_set_pending_exception (&error
))
1066 mono_gc_wbarrier_generic_store (fields
, (MonoObject
*) fields_arr
);
1067 for (i
= 0; i
< count
; ++i
)
1068 mono_array_setref (*fields
, i
, values
[i
]);
1075 ICALL_EXPORT MonoBoolean
1076 ves_icall_System_ValueType_Equals (MonoObject
*this_obj
, MonoObject
*that
, MonoArray
**fields
)
1080 MonoObject
**values
= NULL
;
1082 MonoClassField
* field
;
1086 MONO_CHECK_ARG_NULL (that
, FALSE
);
1088 if (this_obj
->vtable
!= that
->vtable
)
1091 klass
= mono_object_class (this_obj
);
1093 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) && mono_class_enum_basetype (klass
)->type
== MONO_TYPE_I4
)
1094 return (*(gint32
*)((guint8
*)this_obj
+ sizeof (MonoObject
)) == *(gint32
*)((guint8
*)that
+ sizeof (MonoObject
)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field
= mono_class_get_fields (klass
, &iter
))) {
1105 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1107 if (mono_field_is_deleted (field
))
1109 /* FIXME: Add more types */
1110 switch (field
->type
->type
) {
1113 case MONO_TYPE_BOOLEAN
:
1114 if (*((guint8
*)this_obj
+ field
->offset
) != *((guint8
*)that
+ field
->offset
))
1119 case MONO_TYPE_CHAR
:
1120 if (*(gint16
*)((guint8
*)this_obj
+ field
->offset
) != *(gint16
*)((guint8
*)that
+ field
->offset
))
1125 if (*(gint32
*)((guint8
*)this_obj
+ field
->offset
) != *(gint32
*)((guint8
*)that
+ field
->offset
))
1130 if (*(gint64
*)((guint8
*)this_obj
+ field
->offset
) != *(gint64
*)((guint8
*)that
+ field
->offset
))
1134 if (*(float*)((guint8
*)this_obj
+ field
->offset
) != *(float*)((guint8
*)that
+ field
->offset
))
1138 if (*(double*)((guint8
*)this_obj
+ field
->offset
) != *(double*)((guint8
*)that
+ field
->offset
))
1143 case MONO_TYPE_STRING
: {
1144 MonoString
*s1
, *s2
;
1145 guint32 s1len
, s2len
;
1146 s1
= *(MonoString
**)((guint8
*)this_obj
+ field
->offset
);
1147 s2
= *(MonoString
**)((guint8
*)that
+ field
->offset
);
1150 if ((s1
== NULL
) || (s2
== NULL
))
1152 s1len
= mono_string_length (s1
);
1153 s2len
= mono_string_length (s2
);
1157 if (memcmp (mono_string_chars (s1
), mono_string_chars (s2
), s1len
* sizeof (gunichar2
)) != 0)
1163 values
= g_newa (MonoObject
*, mono_class_num_fields (klass
) * 2);
1164 o
= mono_field_get_value_object_checked (mono_object_domain (this_obj
), field
, this_obj
, &error
);
1165 if (!is_ok (&error
)) {
1166 mono_error_set_pending_exception (&error
);
1169 values
[count
++] = o
;
1170 o
= mono_field_get_value_object_checked (mono_object_domain (this_obj
), field
, that
, &error
);
1171 if (!is_ok (&error
)) {
1172 mono_error_set_pending_exception (&error
);
1175 values
[count
++] = o
;
1178 if (klass
->enumtype
)
1179 /* enums only have one non-static field */
1185 MonoArray
*fields_arr
= mono_array_new_checked (mono_domain_get (), mono_defaults
.object_class
, count
, &error
);
1186 if (mono_error_set_pending_exception (&error
))
1188 mono_gc_wbarrier_generic_store (fields
, (MonoObject
*) fields_arr
);
1189 for (i
= 0; i
< count
; ++i
)
1190 mono_array_setref_fast (*fields
, i
, values
[i
]);
1197 ICALL_EXPORT MonoReflectionType
*
1198 ves_icall_System_Object_GetType (MonoObject
*obj
)
1201 MonoReflectionType
*ret
;
1202 #ifndef DISABLE_REMOTING
1203 if (obj
->vtable
->klass
== mono_defaults
.transparent_proxy_class
)
1204 ret
= mono_type_get_object_checked (mono_object_domain (obj
), &((MonoTransparentProxy
*)obj
)->remote_class
->proxy_class
->byval_arg
, &error
);
1207 ret
= mono_type_get_object_checked (mono_object_domain (obj
), &obj
->vtable
->klass
->byval_arg
, &error
);
1209 mono_error_set_pending_exception (&error
);
1214 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder
*mb
, MonoObject
*obj
, gboolean create_open_instance
)
1216 MONO_CHECK_ARG_NULL (obj
, 0);
1219 gint32 result
= mono_image_create_token (mb
->dynamic_image
, obj
, create_open_instance
, TRUE
, &error
);
1220 mono_error_set_pending_exception (&error
);
1225 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder
*mb
,
1226 MonoReflectionMethod
*method
,
1227 MonoArray
*opt_param_types
)
1229 MONO_CHECK_ARG_NULL (method
, 0);
1232 gint32 result
= mono_image_create_method_token (
1233 mb
->dynamic_image
, (MonoObject
*) method
, opt_param_types
, &error
);
1234 mono_error_set_pending_exception (&error
);
1239 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
1242 mono_image_create_pefile (mb
, file
, &error
);
1243 mono_error_set_pending_exception (&error
);
1247 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder
*mb
)
1250 mono_image_build_metadata (mb
, &error
);
1251 mono_error_set_pending_exception (&error
);
1255 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder
*mb
, MonoObject
*obj
, guint32 token
)
1257 mono_image_register_token (mb
->dynamic_image
, token
, obj
);
1260 ICALL_EXPORT MonoObject
*
1261 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder
*mb
, guint32 token
)
1265 mono_loader_lock ();
1266 obj
= (MonoObject
*)mono_g_hash_table_lookup (mb
->dynamic_image
->tokens
, GUINT_TO_POINTER (token
));
1267 mono_loader_unlock ();
1272 ICALL_EXPORT MonoReflectionModule
*
1273 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder
*ab
, MonoString
*fileName
)
1276 MonoReflectionModule
*result
= mono_image_load_module_dynamic (ab
, fileName
, &error
);
1277 mono_error_set_pending_exception (&error
);
1282 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1283 * @tb: a TypeBuilder object
1286 * Creates the generic class after all generic parameters have been added.
1289 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder
*tb
)
1292 (void) mono_reflection_create_generic_class (tb
, &error
);
1293 mono_error_set_pending_exception (&error
);
1296 #ifndef DISABLE_REFLECTION_EMIT
1297 ICALL_EXPORT MonoArray
*
1298 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly
*assembly
, MonoObject
*ctor
, MonoArray
*ctorArgs
, MonoArray
*properties
, MonoArray
*propValues
, MonoArray
*fields
, MonoArray
* fieldValues
)
1301 MonoArray
*result
= mono_reflection_get_custom_attrs_blob_checked (assembly
, ctor
, ctorArgs
, properties
, propValues
, fields
, fieldValues
, &error
);
1302 mono_error_set_pending_exception (&error
);
1308 get_executing (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1310 MonoMethod
**dest
= (MonoMethod
**)data
;
1312 /* skip unmanaged frames */
1317 if (!strcmp (m
->klass
->name_space
, "System.Reflection"))
1326 get_caller_no_reflection (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1328 MonoMethod
**dest
= (MonoMethod
**)data
;
1330 /* skip unmanaged frames */
1334 if (m
->wrapper_type
!= MONO_WRAPPER_NONE
)
1342 if (m
->klass
->image
== mono_defaults
.corlib
&& !strcmp (m
->klass
->name_space
, "System.Reflection"))
1353 get_caller_no_system_or_reflection (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1355 MonoMethod
**dest
= (MonoMethod
**)data
;
1357 /* skip unmanaged frames */
1361 if (m
->wrapper_type
!= MONO_WRAPPER_NONE
)
1369 if (m
->klass
->image
== mono_defaults
.corlib
&& ((!strcmp (m
->klass
->name_space
, "System.Reflection"))
1370 || (!strcmp (m
->klass
->name_space
, "System"))))
1380 static MonoReflectionType
*
1381 type_from_parsed_name (MonoTypeNameParse
*info
, MonoBoolean ignoreCase
, MonoError
*error
)
1383 MonoMethod
*m
, *dest
;
1385 MonoType
*type
= NULL
;
1386 MonoAssembly
*assembly
= NULL
;
1387 gboolean type_resolve
= FALSE
;
1388 MonoImage
*rootimage
= NULL
;
1390 mono_error_init (error
);
1393 * We must compute the calling assembly as type loading must happen under a metadata context.
1394 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1395 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1397 m
= mono_method_get_last_managed ();
1399 if (m
&& m
->klass
->image
!= mono_defaults
.corlib
) {
1400 /* Happens with inlining */
1402 /* Ugly hack: type_from_parsed_name is called from
1403 * System.Type.internal_from_name, which is called most
1404 * directly from System.Type.GetType(string,bool,bool) but
1405 * also indirectly from places such as
1406 * System.Type.GetType(string,func,func) (via
1407 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1408 * so we need to skip over all of those to find the true caller.
1410 * It would be nice if we had stack marks.
1412 mono_stack_walk_no_il (get_caller_no_system_or_reflection
, &dest
);
1418 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1419 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1420 * to crash. This only seems to happen in some strange remoting
1421 * scenarios and I was unable to figure out what's happening there.
1422 * Dec 10, 2005 - Martin.
1426 assembly
= dest
->klass
->image
->assembly
;
1427 type_resolve
= TRUE
;
1428 rootimage
= assembly
->image
;
1430 g_warning (G_STRLOC
);
1433 if (info
->assembly
.name
)
1434 assembly
= mono_assembly_load (&info
->assembly
, assembly
? assembly
->basedir
: NULL
, NULL
);
1437 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1438 type
= mono_reflection_get_type_checked (rootimage
, assembly
->image
, info
, ignoreCase
, &type_resolve
, error
);
1439 return_val_if_nok (error
, NULL
);
1443 // Say we're looking for System.Generic.Dict<int, Local>
1444 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1445 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1446 // is messed up when we go to construct the Local as the type arg...
1448 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1449 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1450 if (!info
->assembly
.name
&& !type
) {
1452 type
= mono_reflection_get_type_checked (rootimage
, NULL
, info
, ignoreCase
, &type_resolve
, error
);
1453 return_val_if_nok (error
, NULL
);
1455 if (assembly
&& !type
&& type_resolve
) {
1456 type_resolve
= FALSE
; /* This will invoke TypeResolve if not done in the first 'if' */
1457 type
= mono_reflection_get_type_checked (rootimage
, assembly
->image
, info
, ignoreCase
, &type_resolve
, error
);
1458 return_val_if_nok (error
, NULL
);
1464 return mono_type_get_object_checked (mono_domain_get (), type
, error
);
1467 ICALL_EXPORT MonoReflectionType
*
1468 ves_icall_System_Type_internal_from_name (MonoString
*name
,
1469 MonoBoolean throwOnError
,
1470 MonoBoolean ignoreCase
)
1473 MonoTypeNameParse info
;
1474 MonoReflectionType
*type
= NULL
;
1477 char *str
= mono_string_to_utf8_checked (name
, &error
);
1478 if (!is_ok (&error
))
1481 parsedOk
= mono_reflection_parse_type (str
, &info
);
1483 /* mono_reflection_parse_type() mangles the string */
1485 mono_reflection_free_type_info (&info
);
1487 mono_error_set_argument (&error
, "typeName", "failed parse: %s", str
);
1491 type
= type_from_parsed_name (&info
, ignoreCase
, &error
);
1493 mono_reflection_free_type_info (&info
);
1495 if (!is_ok (&error
))
1500 mono_error_set_type_load_name (&error
, g_strdup (str
), NULL
, "");
1507 if (!is_ok (&error
)) {
1509 mono_error_set_pending_exception (&error
);
1511 mono_error_cleanup (&error
);
1519 ICALL_EXPORT MonoReflectionType
*
1520 ves_icall_System_Type_internal_from_handle (MonoType
*handle
)
1523 MonoReflectionType
*ret
;
1524 MonoDomain
*domain
= mono_domain_get ();
1526 ret
= mono_type_get_object_checked (domain
, handle
, &error
);
1527 mono_error_set_pending_exception (&error
);
1532 ICALL_EXPORT MonoType
*
1533 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass
*klass
)
1535 return mono_class_get_type (klass
);
1538 /* System.TypeCode */
1557 TYPECODE_STRING
= 18
1560 ICALL_EXPORT guint32
1561 ves_icall_type_GetTypeCodeInternal (MonoReflectionType
*type
)
1563 int t
= type
->type
->type
;
1565 if (type
->type
->byref
)
1566 return TYPECODE_OBJECT
;
1570 case MONO_TYPE_VOID
:
1571 return TYPECODE_OBJECT
;
1572 case MONO_TYPE_BOOLEAN
:
1573 return TYPECODE_BOOLEAN
;
1575 return TYPECODE_BYTE
;
1577 return TYPECODE_SBYTE
;
1579 return TYPECODE_UINT16
;
1581 return TYPECODE_INT16
;
1582 case MONO_TYPE_CHAR
:
1583 return TYPECODE_CHAR
;
1587 return TYPECODE_OBJECT
;
1589 return TYPECODE_UINT32
;
1591 return TYPECODE_INT32
;
1593 return TYPECODE_UINT64
;
1595 return TYPECODE_INT64
;
1597 return TYPECODE_SINGLE
;
1599 return TYPECODE_DOUBLE
;
1600 case MONO_TYPE_VALUETYPE
: {
1601 MonoClass
*klass
= type
->type
->data
.klass
;
1603 if (klass
->enumtype
) {
1604 t
= mono_class_enum_basetype (klass
)->type
;
1606 } else if (mono_is_corlib_image (klass
->image
)) {
1607 if (strcmp (klass
->name_space
, "System") == 0) {
1608 if (strcmp (klass
->name
, "Decimal") == 0)
1609 return TYPECODE_DECIMAL
;
1610 else if (strcmp (klass
->name
, "DateTime") == 0)
1611 return TYPECODE_DATETIME
;
1614 return TYPECODE_OBJECT
;
1616 case MONO_TYPE_STRING
:
1617 return TYPECODE_STRING
;
1618 case MONO_TYPE_SZARRAY
:
1619 case MONO_TYPE_ARRAY
:
1620 case MONO_TYPE_OBJECT
:
1622 case MONO_TYPE_MVAR
:
1623 case MONO_TYPE_TYPEDBYREF
:
1624 return TYPECODE_OBJECT
;
1625 case MONO_TYPE_CLASS
:
1627 MonoClass
*klass
= type
->type
->data
.klass
;
1628 if (klass
->image
== mono_defaults
.corlib
&& strcmp (klass
->name_space
, "System") == 0) {
1629 if (strcmp (klass
->name
, "DBNull") == 0)
1630 return TYPECODE_DBNULL
;
1633 return TYPECODE_OBJECT
;
1634 case MONO_TYPE_GENERICINST
:
1635 return TYPECODE_OBJECT
;
1637 g_error ("type 0x%02x not handled in GetTypeCode()", t
);
1643 mono_type_is_primitive (MonoType
*type
)
1645 return (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_R8
) ||
1646 type
-> type
== MONO_TYPE_I
|| type
->type
== MONO_TYPE_U
;
1650 mono_type_get_underlying_type_ignore_byref (MonoType
*type
)
1652 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
)
1653 return mono_class_enum_basetype (type
->data
.klass
);
1654 if (type
->type
== MONO_TYPE_GENERICINST
&& type
->data
.generic_class
->container_class
->enumtype
)
1655 return mono_class_enum_basetype (type
->data
.generic_class
->container_class
);
1659 ICALL_EXPORT guint32
1660 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType
*type
, MonoReflectionType
*c
)
1665 g_assert (type
!= NULL
);
1667 klass
= mono_class_from_mono_type (type
->type
);
1668 klassc
= mono_class_from_mono_type (c
->type
);
1670 if (type
->type
->byref
^ c
->type
->byref
)
1673 if (type
->type
->byref
) {
1674 MonoType
*t
= mono_type_get_underlying_type_ignore_byref (type
->type
);
1675 MonoType
*ot
= mono_type_get_underlying_type_ignore_byref (c
->type
);
1677 klass
= mono_class_from_mono_type (t
);
1678 klassc
= mono_class_from_mono_type (ot
);
1680 if (mono_type_is_primitive (t
)) {
1681 return mono_type_is_primitive (ot
) && klass
->instance_size
== klassc
->instance_size
;
1682 } else if (t
->type
== MONO_TYPE_VAR
|| t
->type
== MONO_TYPE_MVAR
) {
1683 return t
->type
== ot
->type
&& t
->data
.generic_param
->num
== ot
->data
.generic_param
->num
;
1684 } else if (t
->type
== MONO_TYPE_PTR
|| t
->type
== MONO_TYPE_FNPTR
) {
1685 return t
->type
== ot
->type
;
1687 if (ot
->type
== MONO_TYPE_VAR
|| ot
->type
== MONO_TYPE_MVAR
)
1690 if (klass
->valuetype
)
1691 return klass
== klassc
;
1692 return klass
->valuetype
== klassc
->valuetype
;
1695 return mono_class_is_assignable_from (klass
, klassc
);
1698 ICALL_EXPORT guint32
1699 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType
*type
, MonoObject
*obj
)
1702 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1703 mono_class_init_checked (klass
, &error
);
1704 if (!is_ok (&error
)) {
1705 mono_error_set_pending_exception (&error
);
1708 guint32 result
= (mono_object_isinst_checked (obj
, klass
, &error
) != NULL
);
1709 mono_error_set_pending_exception (&error
);
1713 ICALL_EXPORT guint32
1714 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType
*type
)
1716 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1717 return klass
->flags
;
1720 ICALL_EXPORT MonoReflectionMarshalAsAttribute
*
1721 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField
*field
)
1724 MonoClass
*klass
= field
->field
->parent
;
1725 MonoMarshalType
*info
;
1729 if (klass
->generic_container
||
1730 (klass
->generic_class
&& klass
->generic_class
->context
.class_inst
->is_open
))
1733 ftype
= mono_field_get_type (field
->field
);
1734 if (ftype
&& !(ftype
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL
))
1737 info
= mono_marshal_load_type_info (klass
);
1739 for (i
= 0; i
< info
->num_fields
; ++i
) {
1740 if (info
->fields
[i
].field
== field
->field
) {
1741 if (!info
->fields
[i
].mspec
)
1744 MonoReflectionMarshalAsAttribute
* obj
;
1745 obj
= mono_reflection_marshal_as_attribute_from_marshal_spec (field
->object
.vtable
->domain
, klass
, info
->fields
[i
].mspec
, &error
);
1746 if (!mono_error_ok (&error
))
1747 mono_error_set_pending_exception (&error
);
1756 ICALL_EXPORT MonoReflectionField
*
1757 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField
*handle
, MonoType
*type
)
1760 gboolean found
= FALSE
;
1767 klass
= handle
->parent
;
1769 klass
= mono_class_from_mono_type (type
);
1771 /* Check that the field belongs to the class */
1772 for (k
= klass
; k
; k
= k
->parent
) {
1773 if (k
== handle
->parent
) {
1780 /* The managed code will throw the exception */
1784 MonoReflectionField
*result
= mono_field_get_object_checked (mono_domain_get (), klass
, handle
, &error
);
1785 mono_error_set_pending_exception (&error
);
1789 ICALL_EXPORT MonoArray
*
1790 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField
*field
, MonoBoolean optional
)
1793 MonoType
*type
= mono_field_get_type_checked (field
->field
, &error
);
1796 if (!mono_error_ok (&error
)) {
1797 mono_error_set_pending_exception (&error
);
1801 res
= type_array_from_modifiers (field
->field
->parent
->image
, type
, optional
, &error
);
1802 mono_error_set_pending_exception (&error
);
1807 vell_icall_get_method_attributes (MonoMethod
*method
)
1809 return method
->flags
;
1813 ves_icall_get_method_info (MonoMethod
*method
, MonoMethodInfo
*info
)
1816 MonoReflectionType
*rt
;
1817 MonoDomain
*domain
= mono_domain_get ();
1818 MonoMethodSignature
* sig
;
1820 sig
= mono_method_signature_checked (method
, &error
);
1821 if (!mono_error_ok (&error
)) {
1822 mono_error_set_pending_exception (&error
);
1826 rt
= mono_type_get_object_checked (domain
, &method
->klass
->byval_arg
, &error
);
1827 if (!mono_error_ok (&error
)) {
1828 mono_error_set_pending_exception (&error
);
1832 MONO_STRUCT_SETREF (info
, parent
, rt
);
1834 rt
= mono_type_get_object_checked (domain
, sig
->ret
, &error
);
1835 if (!mono_error_ok (&error
)) {
1836 mono_error_set_pending_exception (&error
);
1840 MONO_STRUCT_SETREF (info
, ret
, rt
);
1842 info
->attrs
= method
->flags
;
1843 info
->implattrs
= method
->iflags
;
1844 if (sig
->call_convention
== MONO_CALL_DEFAULT
)
1845 info
->callconv
= sig
->sentinelpos
>= 0 ? 2 : 1;
1847 if (sig
->call_convention
== MONO_CALL_VARARG
|| sig
->sentinelpos
>= 0)
1852 info
->callconv
|= (sig
->hasthis
<< 5) | (sig
->explicit_this
<< 6);
1855 ICALL_EXPORT MonoArray
*
1856 ves_icall_get_parameter_info (MonoMethod
*method
, MonoReflectionMethod
*member
)
1859 MonoDomain
*domain
= mono_domain_get ();
1861 MonoArray
*result
= mono_param_get_objects_internal (domain
, method
, member
->reftype
? mono_class_from_mono_type (member
->reftype
->type
) : NULL
, &error
);
1862 mono_error_set_pending_exception (&error
);
1866 ICALL_EXPORT MonoReflectionMarshalAsAttribute
*
1867 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod
*method
)
1870 MonoDomain
*domain
= mono_domain_get ();
1871 MonoReflectionMarshalAsAttribute
* res
= NULL
;
1872 MonoMarshalSpec
**mspecs
;
1875 mspecs
= g_new (MonoMarshalSpec
*, mono_method_signature (method
)->param_count
+ 1);
1876 mono_method_get_marshal_info (method
, mspecs
);
1879 res
= mono_reflection_marshal_as_attribute_from_marshal_spec (domain
, method
->klass
, mspecs
[0], &error
);
1880 if (!mono_error_ok (&error
)) {
1881 mono_error_set_pending_exception (&error
);
1886 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
1888 mono_metadata_free_marshal_spec (mspecs
[i
]);
1895 ves_icall_MonoField_GetFieldOffset (MonoReflectionField
*field
)
1897 MonoClass
*parent
= field
->field
->parent
;
1898 if (!parent
->size_inited
)
1899 mono_class_init (parent
);
1900 mono_class_setup_fields_locking (parent
);
1902 return field
->field
->offset
- sizeof (MonoObject
);
1905 ICALL_EXPORT MonoReflectionType
*
1906 ves_icall_MonoField_GetParentType (MonoReflectionField
*field
, MonoBoolean declaring
)
1909 MonoReflectionType
*ret
;
1912 parent
= declaring
? field
->field
->parent
: field
->klass
;
1914 ret
= mono_type_get_object_checked (mono_object_domain (field
), &parent
->byval_arg
, &error
);
1915 mono_error_set_pending_exception (&error
);
1921 ICALL_EXPORT MonoObject
*
1922 ves_icall_MonoField_GetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
)
1925 MonoClass
*fklass
= field
->klass
;
1926 MonoClassField
*cf
= field
->field
;
1927 MonoDomain
*domain
= mono_object_domain (field
);
1929 if (fklass
->image
->assembly
->ref_only
) {
1930 mono_set_pending_exception (mono_get_exception_invalid_operation (
1931 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1935 if (mono_security_core_clr_enabled () &&
1936 !mono_security_core_clr_ensure_reflection_access_field (cf
, &error
)) {
1937 mono_error_set_pending_exception (&error
);
1941 MonoObject
* result
= mono_field_get_value_object_checked (domain
, cf
, obj
, &error
);
1942 mono_error_set_pending_exception (&error
);
1947 ves_icall_MonoField_SetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
, MonoObject
*value
)
1950 MonoClassField
*cf
= field
->field
;
1954 if (field
->klass
->image
->assembly
->ref_only
) {
1955 mono_set_pending_exception (mono_get_exception_invalid_operation (
1956 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1960 if (mono_security_core_clr_enabled () &&
1961 !mono_security_core_clr_ensure_reflection_access_field (cf
, &error
)) {
1962 mono_error_set_pending_exception (&error
);
1966 type
= mono_field_get_type_checked (cf
, &error
);
1967 if (!mono_error_ok (&error
)) {
1968 mono_error_set_pending_exception (&error
);
1972 v
= (gchar
*) value
;
1974 switch (type
->type
) {
1977 case MONO_TYPE_BOOLEAN
:
1980 case MONO_TYPE_CHAR
:
1989 case MONO_TYPE_VALUETYPE
:
1992 v
+= sizeof (MonoObject
);
1994 case MONO_TYPE_STRING
:
1995 case MONO_TYPE_OBJECT
:
1996 case MONO_TYPE_CLASS
:
1997 case MONO_TYPE_ARRAY
:
1998 case MONO_TYPE_SZARRAY
:
2001 case MONO_TYPE_GENERICINST
: {
2002 MonoGenericClass
*gclass
= type
->data
.generic_class
;
2003 g_assert (!gclass
->context
.class_inst
->is_open
);
2005 if (mono_class_is_nullable (mono_class_from_mono_type (type
))) {
2006 MonoClass
*nklass
= mono_class_from_mono_type (type
);
2007 MonoObject
*nullable
;
2010 * Convert the boxed vtype into a Nullable structure.
2011 * This is complicated by the fact that Nullables have
2012 * a variable structure.
2014 nullable
= mono_object_new_checked (mono_domain_get (), nklass
, &error
);
2015 if (!mono_error_ok (&error
)) {
2016 mono_error_set_pending_exception (&error
);
2020 mono_nullable_init ((guint8
*)mono_object_unbox (nullable
), value
, nklass
);
2022 v
= (gchar
*)mono_object_unbox (nullable
);
2025 if (gclass
->container_class
->valuetype
&& (v
!= NULL
))
2026 v
+= sizeof (MonoObject
);
2030 g_error ("type 0x%x not handled in "
2031 "ves_icall_FieldInfo_SetValueInternal", type
->type
);
2036 if (type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
2037 MonoVTable
*vtable
= mono_class_vtable_full (mono_object_domain (field
), cf
->parent
, &error
);
2038 if (!is_ok (&error
)) {
2039 mono_error_set_pending_exception (&error
);
2042 if (!vtable
->initialized
) {
2043 if (!mono_runtime_class_init_full (vtable
, &error
)) {
2044 mono_error_set_pending_exception (&error
);
2048 mono_field_static_set_value (vtable
, cf
, v
);
2050 mono_field_set_value (obj
, cf
, v
);
2055 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField
*field
, MonoReflectionType
*field_type
, MonoTypedRef
*obj
, MonoObject
*value
, MonoReflectionType
*context_type
)
2064 if (!MONO_TYPE_ISSTRUCT (&f
->parent
->byval_arg
)) {
2065 mono_set_pending_exception (mono_get_exception_not_implemented (NULL
));
2069 if (MONO_TYPE_IS_REFERENCE (f
->type
))
2070 mono_copy_value (f
->type
, (guint8
*)obj
->value
+ f
->offset
- sizeof (MonoObject
), value
, FALSE
);
2072 mono_copy_value (f
->type
, (guint8
*)obj
->value
+ f
->offset
- sizeof (MonoObject
), mono_object_unbox (value
), FALSE
);
2075 ICALL_EXPORT MonoObject
*
2076 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField
*rfield
)
2078 MonoObject
*o
= NULL
;
2079 MonoClassField
*field
= rfield
->field
;
2081 MonoDomain
*domain
= mono_object_domain (rfield
);
2083 MonoTypeEnum def_type
;
2084 const char *def_value
;
2088 mono_class_init (field
->parent
);
2090 t
= mono_field_get_type_checked (field
, &error
);
2091 if (!mono_error_ok (&error
)) {
2092 mono_error_set_pending_exception (&error
);
2096 if (!(t
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
)) {
2097 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL
));
2101 if (image_is_dynamic (field
->parent
->image
)) {
2102 MonoClass
*klass
= field
->parent
;
2103 int fidx
= field
- klass
->fields
;
2105 g_assert (fidx
>= 0 && fidx
< klass
->field
.count
);
2106 g_assert (klass
->ext
);
2107 g_assert (klass
->ext
->field_def_values
);
2108 def_type
= klass
->ext
->field_def_values
[fidx
].def_type
;
2109 def_value
= klass
->ext
->field_def_values
[fidx
].data
;
2110 if (def_type
== MONO_TYPE_END
) {
2111 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL
));
2115 def_value
= mono_class_get_field_default_value (field
, &def_type
);
2116 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2118 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL
));
2123 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2127 case MONO_TYPE_BOOLEAN
:
2130 case MONO_TYPE_CHAR
:
2138 case MONO_TYPE_R8
: {
2141 /* boxed value type */
2142 t
= g_new0 (MonoType
, 1);
2144 klass
= mono_class_from_mono_type (t
);
2146 o
= mono_object_new_checked (domain
, klass
, &error
);
2147 if (!mono_error_ok (&error
)) {
2148 mono_error_set_pending_exception (&error
);
2151 v
= ((gchar
*) o
) + sizeof (MonoObject
);
2152 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, v
, &error
);
2153 if (mono_error_set_pending_exception (&error
))
2157 case MONO_TYPE_STRING
:
2158 case MONO_TYPE_CLASS
:
2159 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, &o
, &error
);
2160 if (mono_error_set_pending_exception (&error
))
2164 g_assert_not_reached ();
2170 ICALL_EXPORT MonoReflectionType
*
2171 ves_icall_MonoField_ResolveType (MonoReflectionField
*ref_field
)
2174 MonoReflectionType
*ret
;
2177 type
= mono_field_get_type_checked (ref_field
->field
, &error
);
2178 if (!mono_error_ok (&error
)) {
2179 mono_error_set_pending_exception (&error
);
2183 ret
= mono_type_get_object_checked (mono_object_domain (ref_field
), type
, &error
);
2184 if (!mono_error_ok (&error
)) {
2185 mono_error_set_pending_exception (&error
);
2192 /* From MonoProperty.cs */
2194 PInfo_Attributes
= 1,
2195 PInfo_GetMethod
= 1 << 1,
2196 PInfo_SetMethod
= 1 << 2,
2197 PInfo_ReflectedType
= 1 << 3,
2198 PInfo_DeclaringType
= 1 << 4,
2203 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty
*property
, MonoPropertyInfo
*info
, PInfo req_info
)
2206 MonoReflectionType
*rt
;
2207 MonoReflectionMethod
*rm
;
2208 MonoDomain
*domain
= mono_object_domain (property
);
2209 const MonoProperty
*pproperty
= property
->property
;
2211 if ((req_info
& PInfo_ReflectedType
) != 0) {
2212 rt
= mono_type_get_object_checked (domain
, &property
->klass
->byval_arg
, &error
);
2213 if (mono_error_set_pending_exception (&error
))
2216 MONO_STRUCT_SETREF (info
, parent
, rt
);
2218 if ((req_info
& PInfo_DeclaringType
) != 0) {
2219 rt
= mono_type_get_object_checked (domain
, &pproperty
->parent
->byval_arg
, &error
);
2220 if (mono_error_set_pending_exception (&error
))
2223 MONO_STRUCT_SETREF (info
, declaring_type
, rt
);
2226 if ((req_info
& PInfo_Name
) != 0)
2227 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, pproperty
->name
));
2229 if ((req_info
& PInfo_Attributes
) != 0)
2230 info
->attrs
= pproperty
->attrs
;
2232 if ((req_info
& PInfo_GetMethod
) != 0) {
2233 if (pproperty
->get
&&
2234 (((pproperty
->get
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) ||
2235 pproperty
->get
->klass
== property
->klass
)) {
2236 rm
= mono_method_get_object_checked (domain
, pproperty
->get
, property
->klass
, &error
);
2237 if (mono_error_set_pending_exception (&error
))
2243 MONO_STRUCT_SETREF (info
, get
, rm
);
2245 if ((req_info
& PInfo_SetMethod
) != 0) {
2246 if (pproperty
->set
&&
2247 (((pproperty
->set
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) ||
2248 pproperty
->set
->klass
== property
->klass
)) {
2249 rm
= mono_method_get_object_checked (domain
, pproperty
->set
, property
->klass
, &error
);
2250 if (mono_error_set_pending_exception (&error
))
2256 MONO_STRUCT_SETREF (info
, set
, rm
);
2259 * There may be other methods defined for properties, though, it seems they are not exposed
2260 * in the reflection API
2265 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent
*event
, MonoEventInfo
*info
)
2268 MonoReflectionType
*rt
;
2269 MonoReflectionMethod
*rm
;
2270 MonoDomain
*domain
= mono_object_domain (event
);
2272 rt
= mono_type_get_object_checked (domain
, &event
->klass
->byval_arg
, &error
);
2273 if (mono_error_set_pending_exception (&error
))
2276 MONO_STRUCT_SETREF (info
, reflected_type
, rt
);
2278 rt
= mono_type_get_object_checked (domain
, &event
->event
->parent
->byval_arg
, &error
);
2279 if (mono_error_set_pending_exception (&error
))
2282 MONO_STRUCT_SETREF (info
, declaring_type
, rt
);
2284 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, event
->event
->name
));
2285 info
->attrs
= event
->event
->attrs
;
2287 if (event
->event
->add
) {
2288 rm
= mono_method_get_object_checked (domain
, event
->event
->add
, NULL
, &error
);
2289 if (mono_error_set_pending_exception (&error
))
2295 MONO_STRUCT_SETREF (info
, add_method
, rm
);
2297 if (event
->event
->remove
) {
2298 rm
= mono_method_get_object_checked (domain
, event
->event
->remove
, NULL
, &error
);
2299 if (mono_error_set_pending_exception (&error
))
2305 MONO_STRUCT_SETREF (info
, remove_method
, rm
);
2307 if (event
->event
->raise
) {
2308 rm
= mono_method_get_object_checked (domain
, event
->event
->raise
, NULL
, &error
);
2309 if (mono_error_set_pending_exception (&error
))
2315 MONO_STRUCT_SETREF (info
, raise_method
, rm
);
2317 #ifndef MONO_SMALL_CONFIG
2318 if (event
->event
->other
) {
2320 while (event
->event
->other
[n
])
2322 MonoArray
*info_arr
= mono_array_new_checked (domain
, mono_defaults
.method_info_class
, n
, &error
);
2323 if (mono_error_set_pending_exception (&error
))
2325 MONO_STRUCT_SETREF (info
, other_methods
, info_arr
);
2327 for (i
= 0; i
< n
; i
++) {
2328 rm
= mono_method_get_object_checked (domain
, event
->event
->other
[i
], NULL
, &error
);
2329 if (mono_error_set_pending_exception (&error
))
2331 mono_array_setref (info
->other_methods
, i
, rm
);
2338 collect_interfaces (MonoClass
*klass
, GHashTable
*ifaces
, MonoError
*error
)
2343 mono_class_setup_interfaces (klass
, error
);
2344 if (!mono_error_ok (error
))
2347 for (i
= 0; i
< klass
->interface_count
; i
++) {
2348 ic
= klass
->interfaces
[i
];
2349 g_hash_table_insert (ifaces
, ic
, ic
);
2351 collect_interfaces (ic
, ifaces
, error
);
2352 if (!mono_error_ok (error
))
2358 MonoArray
*iface_array
;
2359 MonoGenericContext
*context
;
2363 } FillIfaceArrayData
;
2366 fill_iface_array (gpointer key
, gpointer value
, gpointer user_data
)
2368 MonoReflectionType
*rt
;
2369 FillIfaceArrayData
*data
= (FillIfaceArrayData
*)user_data
;
2370 MonoClass
*ic
= (MonoClass
*)key
;
2371 MonoType
*ret
= &ic
->byval_arg
, *inflated
= NULL
;
2373 if (!mono_error_ok (data
->error
))
2376 if (data
->context
&& ic
->generic_class
&& ic
->generic_class
->context
.class_inst
->is_open
) {
2377 inflated
= ret
= mono_class_inflate_generic_type_checked (ret
, data
->context
, data
->error
);
2378 if (!mono_error_ok (data
->error
))
2382 rt
= mono_type_get_object_checked (data
->domain
, ret
, data
->error
);
2383 if (!mono_error_ok (data
->error
))
2386 mono_array_setref (data
->iface_array
, data
->next_idx
++, rt
);
2389 mono_metadata_free_type (inflated
);
2393 get_interfaces_hash (gconstpointer v1
)
2395 MonoClass
*k
= (MonoClass
*)v1
;
2397 return k
->type_token
;
2400 ICALL_EXPORT MonoArray
*
2401 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType
* type
)
2404 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2406 FillIfaceArrayData data
= { 0 };
2409 GHashTable
*iface_hash
= g_hash_table_new (get_interfaces_hash
, NULL
);
2411 if (klass
->generic_class
&& klass
->generic_class
->context
.class_inst
->is_open
) {
2412 data
.context
= mono_class_get_context (klass
);
2413 klass
= klass
->generic_class
->container_class
;
2416 for (parent
= klass
; parent
; parent
= parent
->parent
) {
2417 mono_class_setup_interfaces (parent
, &error
);
2418 if (!mono_error_ok (&error
))
2420 collect_interfaces (parent
, iface_hash
, &error
);
2421 if (!mono_error_ok (&error
))
2425 data
.error
= &error
;
2426 data
.domain
= mono_object_domain (type
);
2428 len
= g_hash_table_size (iface_hash
);
2430 g_hash_table_destroy (iface_hash
);
2431 if (!data
.domain
->empty_types
) {
2432 data
.domain
->empty_types
= mono_array_new_cached (data
.domain
, mono_defaults
.runtimetype_class
, 0, &error
);
2433 if (!is_ok (&error
))
2436 return data
.domain
->empty_types
;
2439 data
.iface_array
= mono_array_new_cached (data
.domain
, mono_defaults
.runtimetype_class
, len
, &error
);
2440 if (!is_ok (&error
))
2442 g_hash_table_foreach (iface_hash
, fill_iface_array
, &data
);
2443 if (!mono_error_ok (&error
))
2446 g_hash_table_destroy (iface_hash
);
2447 return data
.iface_array
;
2450 g_hash_table_destroy (iface_hash
);
2451 mono_error_set_pending_exception (&error
);
2456 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType
*type
, MonoReflectionType
*iface
, MonoArray
**targets
, MonoArray
**methods
)
2458 gboolean variance_used
;
2459 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2460 MonoClass
*iclass
= mono_class_from_mono_type (iface
->type
);
2461 MonoReflectionMethod
*member
;
2464 int i
= 0, len
, ioffset
;
2468 mono_class_init_checked (klass
, &error
);
2469 if (mono_error_set_pending_exception (&error
))
2471 mono_class_init_checked (iclass
, &error
);
2472 if (mono_error_set_pending_exception (&error
))
2475 mono_class_setup_vtable (klass
);
2477 ioffset
= mono_class_interface_offset_with_variance (klass
, iclass
, &variance_used
);
2481 len
= mono_class_num_methods (iclass
);
2482 domain
= mono_object_domain (type
);
2483 MonoArray
*targets_arr
= mono_array_new_checked (domain
, mono_defaults
.method_info_class
, len
, &error
);
2484 if (mono_error_set_pending_exception (&error
))
2486 mono_gc_wbarrier_generic_store (targets
, (MonoObject
*) targets_arr
);
2487 MonoArray
*methods_arr
= mono_array_new_checked (domain
, mono_defaults
.method_info_class
, len
, &error
);
2488 if (mono_error_set_pending_exception (&error
))
2490 mono_gc_wbarrier_generic_store (methods
, (MonoObject
*) methods_arr
);
2492 while ((method
= mono_class_get_methods (iclass
, &iter
))) {
2493 member
= mono_method_get_object_checked (domain
, method
, iclass
, &error
);
2494 if (mono_error_set_pending_exception (&error
))
2496 mono_array_setref (*methods
, i
, member
);
2497 member
= mono_method_get_object_checked (domain
, klass
->vtable
[i
+ ioffset
], klass
, &error
);
2498 if (mono_error_set_pending_exception (&error
))
2500 mono_array_setref (*targets
, i
, member
);
2507 ves_icall_RuntimeType_GetPacking (MonoReflectionType
*type
, guint32
*packing
, guint32
*size
)
2510 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2512 mono_class_init_checked (klass
, &error
);
2513 if (mono_error_set_pending_exception (&error
))
2516 if (image_is_dynamic (klass
->image
)) {
2517 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)type
;
2518 *packing
= tb
->packing_size
;
2519 *size
= tb
->class_size
;
2521 mono_metadata_packing_from_typedef (klass
->image
, klass
->type_token
, packing
, size
);
2525 ICALL_EXPORT MonoReflectionType
*
2526 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType
*type
)
2529 MonoReflectionType
*ret
;
2532 if (!type
->type
->byref
&& type
->type
->type
== MONO_TYPE_SZARRAY
) {
2533 ret
= mono_type_get_object_checked (mono_object_domain (type
), &type
->type
->data
.klass
->byval_arg
, &error
);
2534 mono_error_set_pending_exception (&error
);
2538 klass
= mono_class_from_mono_type (type
->type
);
2539 mono_class_init_checked (klass
, &error
);
2540 if (mono_error_set_pending_exception (&error
))
2544 // GetElementType should only return a type for:
2545 // Array Pointer PassedByRef
2546 if (type
->type
->byref
)
2547 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->byval_arg
, &error
);
2548 else if (klass
->element_class
&& MONO_CLASS_IS_ARRAY (klass
))
2549 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->element_class
->byval_arg
, &error
);
2550 else if (klass
->element_class
&& type
->type
->type
== MONO_TYPE_PTR
)
2551 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->element_class
->byval_arg
, &error
);
2555 mono_error_set_pending_exception (&error
);
2560 ICALL_EXPORT MonoReflectionType
*
2561 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType
*type
)
2564 MonoReflectionType
*ret
;
2566 if (type
->type
->byref
)
2569 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2573 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->parent
->byval_arg
, &error
);
2574 mono_error_set_pending_exception (&error
);
2579 ICALL_EXPORT MonoBoolean
2580 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType
*type
)
2582 return type
->type
->type
== MONO_TYPE_PTR
;
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType
*type
)
2588 return (!type
->type
->byref
&& (((type
->type
->type
>= MONO_TYPE_BOOLEAN
) && (type
->type
->type
<= MONO_TYPE_R8
)) || (type
->type
->type
== MONO_TYPE_I
) || (type
->type
->type
== MONO_TYPE_U
)));
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType
*type
)
2594 return type
->type
->byref
;
2597 ICALL_EXPORT MonoBoolean
2598 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType
*type
)
2601 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2602 mono_class_init_checked (klass
, &error
);
2603 if (mono_error_set_pending_exception (&error
))
2606 return mono_class_is_com_object (klass
);
2609 ICALL_EXPORT guint32
2610 ves_icall_reflection_get_token (MonoObject
* obj
)
2613 guint32 result
= mono_reflection_get_token_checked (obj
, &error
);
2614 mono_error_set_pending_exception (&error
);
2618 ICALL_EXPORT MonoReflectionModule
*
2619 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType
*type
)
2622 MonoReflectionModule
*result
= NULL
;
2623 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2624 result
= mono_module_get_object_checked (mono_object_domain (type
), klass
->image
, &error
);
2625 mono_error_set_pending_exception (&error
);
2629 ICALL_EXPORT MonoReflectionAssembly
*
2630 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType
*type
)
2633 MonoDomain
*domain
= mono_domain_get ();
2634 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2635 MonoReflectionAssembly
*result
= mono_assembly_get_object_checked (domain
, klass
->image
->assembly
, &error
);
2636 mono_error_set_pending_exception (&error
);
2640 ICALL_EXPORT MonoReflectionType
*
2641 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType
*type
)
2644 MonoReflectionType
*ret
;
2645 MonoDomain
*domain
= mono_domain_get ();
2648 if (type
->type
->byref
)
2650 if (type
->type
->type
== MONO_TYPE_VAR
) {
2651 MonoGenericContainer
*param
= mono_type_get_generic_param_owner (type
->type
);
2652 klass
= param
? param
->owner
.klass
: NULL
;
2653 } else if (type
->type
->type
== MONO_TYPE_MVAR
) {
2654 MonoGenericContainer
*param
= mono_type_get_generic_param_owner (type
->type
);
2655 klass
= param
? param
->owner
.method
->klass
: NULL
;
2657 klass
= mono_class_from_mono_type (type
->type
)->nested_in
;
2663 ret
= mono_type_get_object_checked (domain
, &klass
->byval_arg
, &error
);
2664 mono_error_set_pending_exception (&error
);
2669 ICALL_EXPORT MonoString
*
2670 ves_icall_RuntimeType_get_Name (MonoReflectionType
*type
)
2672 MonoDomain
*domain
= mono_domain_get ();
2673 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2675 if (type
->type
->byref
) {
2676 char *n
= g_strdup_printf ("%s&", klass
->name
);
2677 MonoString
*res
= mono_string_new (domain
, n
);
2683 return mono_string_new (domain
, klass
->name
);
2687 ICALL_EXPORT MonoString
*
2688 ves_icall_RuntimeType_get_Namespace (MonoReflectionType
*type
)
2690 MonoDomain
*domain
= mono_domain_get ();
2691 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2693 while (klass
->nested_in
)
2694 klass
= klass
->nested_in
;
2696 if (klass
->name_space
[0] == '\0')
2699 return mono_string_new (domain
, klass
->name_space
);
2703 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType
*type
)
2707 if (type
->type
->type
!= MONO_TYPE_ARRAY
&& type
->type
->type
!= MONO_TYPE_SZARRAY
) {
2708 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2712 klass
= mono_class_from_mono_type (type
->type
);
2718 create_type_array (MonoDomain
*domain
, MonoBoolean runtimeTypeArray
, int count
, MonoError
*error
)
2720 return mono_array_new_checked (domain
, runtimeTypeArray
? mono_defaults
.runtimetype_class
: mono_defaults
.systemtype_class
, count
, error
);
2723 ICALL_EXPORT MonoArray
*
2724 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType
*type
, MonoBoolean runtimeTypeArray
)
2727 MonoReflectionType
*rt
;
2729 MonoClass
*klass
, *pklass
;
2730 MonoDomain
*domain
= mono_object_domain (type
);
2733 klass
= mono_class_from_mono_type (type
->type
);
2735 if (klass
->generic_container
) {
2736 MonoGenericContainer
*container
= klass
->generic_container
;
2737 res
= create_type_array (domain
, runtimeTypeArray
, container
->type_argc
, &error
);
2738 if (mono_error_set_pending_exception (&error
))
2740 for (i
= 0; i
< container
->type_argc
; ++i
) {
2741 pklass
= mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container
, i
));
2743 rt
= mono_type_get_object_checked (domain
, &pklass
->byval_arg
, &error
);
2744 if (mono_error_set_pending_exception (&error
))
2747 mono_array_setref (res
, i
, rt
);
2749 } else if (klass
->generic_class
) {
2750 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
2751 res
= create_type_array (domain
, runtimeTypeArray
, inst
->type_argc
, &error
);
2752 if (mono_error_set_pending_exception (&error
))
2754 for (i
= 0; i
< inst
->type_argc
; ++i
) {
2755 rt
= mono_type_get_object_checked (domain
, inst
->type_argv
[i
], &error
);
2756 if (mono_error_set_pending_exception (&error
))
2759 mono_array_setref (res
, i
, rt
);
2767 ICALL_EXPORT gboolean
2768 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType
*type
)
2772 if (!IS_MONOTYPE (type
))
2775 if (type
->type
->byref
)
2778 klass
= mono_class_from_mono_type (type
->type
);
2779 return klass
->generic_container
!= NULL
;
2782 ICALL_EXPORT MonoReflectionType
*
2783 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType
*type
)
2786 MonoReflectionType
*ret
;
2789 if (type
->type
->byref
)
2792 klass
= mono_class_from_mono_type (type
->type
);
2794 if (klass
->generic_container
) {
2795 return type
; /* check this one */
2797 if (klass
->generic_class
) {
2798 MonoClass
*generic_class
= klass
->generic_class
->container_class
;
2801 tb
= mono_class_get_ref_info (generic_class
);
2803 if (generic_class
->wastypebuilder
&& tb
)
2804 return (MonoReflectionType
*)tb
;
2806 ret
= mono_type_get_object_checked (mono_object_domain (type
), &generic_class
->byval_arg
, &error
);
2807 mono_error_set_pending_exception (&error
);
2815 ICALL_EXPORT MonoReflectionType
*
2816 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType
*type
, MonoArray
*type_array
)
2819 MonoReflectionType
*ret
;
2821 MonoType
*geninst
, **types
;
2824 g_assert (IS_MONOTYPE (type
));
2825 mono_class_init_checked (mono_class_from_mono_type (type
->type
), &error
);
2826 if (mono_error_set_pending_exception (&error
))
2829 count
= mono_array_length (type_array
);
2830 types
= g_new0 (MonoType
*, count
);
2832 for (i
= 0; i
< count
; i
++) {
2833 MonoReflectionType
*t
= (MonoReflectionType
*)mono_array_get (type_array
, gpointer
, i
);
2834 types
[i
] = t
->type
;
2837 geninst
= mono_reflection_bind_generic_parameters (type
, count
, types
, &error
);
2840 mono_error_set_pending_exception (&error
);
2844 klass
= mono_class_from_mono_type (geninst
);
2846 /*we might inflate to the GTD*/
2847 if (klass
->generic_class
&& !mono_verifier_class_is_valid_generic_instantiation (klass
)) {
2848 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2852 ret
= mono_type_get_object_checked (mono_object_domain (type
), geninst
, &error
);
2853 mono_error_set_pending_exception (&error
);
2858 ICALL_EXPORT gboolean
2859 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType
*type
)
2863 if (!IS_MONOTYPE (type
))
2866 if (type
->type
->byref
)
2869 klass
= mono_class_from_mono_type (type
->type
);
2870 return klass
->generic_class
!= NULL
|| klass
->generic_container
!= NULL
;
2874 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType
*type
)
2876 if (!IS_MONOTYPE (type
))
2879 if (is_generic_parameter (type
->type
))
2880 return mono_type_get_generic_param_num (type
->type
);
2884 ICALL_EXPORT GenericParameterAttributes
2885 ves_icall_RuntimeType_GetGenericParameterAttributes (MonoReflectionType
*type
)
2887 g_assert (IS_MONOTYPE (type
));
2888 g_assert (is_generic_parameter (type
->type
));
2889 return (GenericParameterAttributes
)mono_generic_param_info (type
->type
->data
.generic_param
)->flags
;
2892 ICALL_EXPORT MonoArray
*
2893 ves_icall_RuntimeType_GetGenericParameterConstraints (MonoReflectionType
*type
)
2896 MonoReflectionType
*rt
;
2897 MonoGenericParamInfo
*param_info
;
2903 g_assert (IS_MONOTYPE (type
));
2905 domain
= mono_object_domain (type
);
2906 param_info
= mono_generic_param_info (type
->type
->data
.generic_param
);
2907 for (count
= 0, ptr
= param_info
->constraints
; ptr
&& *ptr
; ptr
++, count
++)
2910 res
= mono_array_new_checked (domain
, mono_defaults
.runtimetype_class
, count
, &error
);
2911 if (mono_error_set_pending_exception (&error
))
2913 for (i
= 0; i
< count
; i
++) {
2914 rt
= mono_type_get_object_checked (domain
, ¶m_info
->constraints
[i
]->byval_arg
, &error
);
2915 if (mono_error_set_pending_exception (&error
))
2918 mono_array_setref (res
, i
, rt
);
2925 ICALL_EXPORT MonoBoolean
2926 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType
*type
)
2928 return is_generic_parameter (type
->type
);
2931 ICALL_EXPORT MonoBoolean
2932 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder
*tb
)
2934 return is_generic_parameter (tb
->type
.type
);
2938 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType
*enumtype
,
2939 MonoReflectionType
*t
)
2941 enumtype
->type
= t
->type
;
2944 ICALL_EXPORT MonoReflectionMethod
*
2945 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType
*type
,
2946 MonoReflectionMethod
* generic
)
2953 MonoReflectionMethod
*ret
= NULL
;
2955 domain
= ((MonoObject
*)type
)->vtable
->domain
;
2957 klass
= mono_class_from_mono_type (type
->type
);
2958 mono_class_init_checked (klass
, &error
);
2959 if (mono_error_set_pending_exception (&error
))
2963 while ((method
= mono_class_get_methods (klass
, &iter
))) {
2964 if (method
->token
== generic
->method
->token
) {
2965 ret
= mono_method_get_object_checked (domain
, method
, klass
, &error
);
2966 if (mono_error_set_pending_exception (&error
))
2974 ICALL_EXPORT MonoReflectionMethod
*
2975 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType
*ref_type
)
2978 MonoType
*type
= ref_type
->type
;
2980 MonoReflectionMethod
*ret
= NULL
;
2982 if (type
->byref
|| (type
->type
!= MONO_TYPE_MVAR
&& type
->type
!= MONO_TYPE_VAR
)) {
2983 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2986 if (type
->type
== MONO_TYPE_VAR
)
2989 method
= mono_type_get_generic_param_owner (type
)->owner
.method
;
2992 ret
= mono_method_get_object_checked (mono_object_domain (ref_type
), method
, method
->klass
, &error
);
2993 if (!mono_error_ok (&error
))
2994 mono_set_pending_exception (mono_error_convert_to_exception (&error
));
2998 ICALL_EXPORT MonoBoolean
2999 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3001 mono_set_pending_exception (mono_get_exception_not_implemented (NULL
));
3005 ICALL_EXPORT MonoBoolean
3006 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3008 mono_set_pending_exception (mono_get_exception_not_implemented (NULL
));
3013 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod
*method
, int* flags
, MonoString
** entry_point
, MonoString
** dll_name
)
3015 MonoDomain
*domain
= mono_domain_get ();
3016 MonoImage
*image
= method
->method
->klass
->image
;
3017 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)method
->method
;
3018 MonoTableInfo
*tables
= image
->tables
;
3019 MonoTableInfo
*im
= &tables
[MONO_TABLE_IMPLMAP
];
3020 MonoTableInfo
*mr
= &tables
[MONO_TABLE_MODULEREF
];
3021 guint32 im_cols
[MONO_IMPLMAP_SIZE
];
3022 guint32 scope_token
;
3023 const char *import
= NULL
;
3024 const char *scope
= NULL
;
3026 if (image_is_dynamic (image
)) {
3027 MonoReflectionMethodAux
*method_aux
=
3028 (MonoReflectionMethodAux
*)g_hash_table_lookup (((MonoDynamicImage
*)image
)->method_aux_hash
, method
->method
);
3030 import
= method_aux
->dllentry
;
3031 scope
= method_aux
->dll
;
3034 if (!import
|| !scope
) {
3035 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3040 if (piinfo
->implmap_idx
) {
3041 mono_metadata_decode_row (im
, piinfo
->implmap_idx
- 1, im_cols
, MONO_IMPLMAP_SIZE
);
3043 piinfo
->piflags
= im_cols
[MONO_IMPLMAP_FLAGS
];
3044 import
= mono_metadata_string_heap (image
, im_cols
[MONO_IMPLMAP_NAME
]);
3045 scope_token
= mono_metadata_decode_row_col (mr
, im_cols
[MONO_IMPLMAP_SCOPE
] - 1, MONO_MODULEREF_NAME
);
3046 scope
= mono_metadata_string_heap (image
, scope_token
);
3050 *flags
= piinfo
->piflags
;
3051 *entry_point
= mono_string_new (domain
, import
);
3052 *dll_name
= mono_string_new (domain
, scope
);
3055 ICALL_EXPORT MonoReflectionMethod
*
3056 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod
*method
)
3058 MonoMethodInflated
*imethod
;
3060 MonoReflectionMethod
*ret
= NULL
;
3063 if (method
->method
->is_generic
)
3066 if (!method
->method
->is_inflated
)
3069 imethod
= (MonoMethodInflated
*) method
->method
;
3071 result
= imethod
->declaring
;
3072 /* Not a generic method. */
3073 if (!result
->is_generic
)
3076 if (image_is_dynamic (method
->method
->klass
->image
)) {
3077 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->method
->klass
->image
;
3078 MonoReflectionMethod
*res
;
3081 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3082 * the dynamic case as well ?
3084 mono_image_lock ((MonoImage
*)image
);
3085 res
= (MonoReflectionMethod
*)mono_g_hash_table_lookup (image
->generic_def_objects
, imethod
);
3086 mono_image_unlock ((MonoImage
*)image
);
3092 if (imethod
->context
.class_inst
) {
3093 MonoClass
*klass
= ((MonoMethod
*) imethod
)->klass
;
3094 /*Generic methods gets the context of the GTD.*/
3095 if (mono_class_get_context (klass
)) {
3096 result
= mono_class_inflate_generic_method_full_checked (result
, klass
, mono_class_get_context (klass
), &error
);
3097 if (!mono_error_ok (&error
))
3102 ret
= mono_method_get_object_checked (mono_object_domain (method
), result
, NULL
, &error
);
3104 if (!mono_error_ok (&error
))
3105 mono_error_set_pending_exception (&error
);
3109 ICALL_EXPORT gboolean
3110 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod
*method
)
3112 return mono_method_signature (method
->method
)->generic_param_count
!= 0;
3115 ICALL_EXPORT gboolean
3116 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod
*method
)
3118 return method
->method
->is_generic
;
3121 ICALL_EXPORT MonoArray
*
3122 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod
*method
)
3125 MonoReflectionType
*rt
;
3130 domain
= mono_object_domain (method
);
3132 if (method
->method
->is_inflated
) {
3133 MonoGenericInst
*inst
= mono_method_get_context (method
->method
)->method_inst
;
3136 count
= inst
->type_argc
;
3137 res
= mono_array_new_checked (domain
, mono_defaults
.systemtype_class
, count
, &error
);
3138 if (mono_error_set_pending_exception (&error
))
3141 for (i
= 0; i
< count
; i
++) {
3142 rt
= mono_type_get_object_checked (domain
, inst
->type_argv
[i
], &error
);
3143 if (mono_error_set_pending_exception (&error
))
3146 mono_array_setref (res
, i
, rt
);
3153 count
= mono_method_signature (method
->method
)->generic_param_count
;
3154 res
= mono_array_new_checked (domain
, mono_defaults
.systemtype_class
, count
, &error
);
3155 if (mono_error_set_pending_exception (&error
))
3158 for (i
= 0; i
< count
; i
++) {
3159 MonoGenericContainer
*container
= mono_method_get_generic_container (method
->method
);
3160 MonoGenericParam
*param
= mono_generic_container_get_param (container
, i
);
3161 MonoClass
*pklass
= mono_class_from_generic_parameter_internal (param
);
3163 rt
= mono_type_get_object_checked (domain
, &pklass
->byval_arg
, &error
);
3164 if (mono_error_set_pending_exception (&error
))
3167 mono_array_setref (res
, i
, rt
);
3173 ICALL_EXPORT MonoObject
*
3174 ves_icall_InternalInvoke (MonoReflectionMethod
*method
, MonoObject
*this_arg
, MonoArray
*params
, MonoException
**exc
)
3178 * Invoke from reflection is supposed to always be a virtual call (the API
3179 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3180 * greater flexibility.
3182 MonoMethod
*m
= method
->method
;
3183 MonoMethodSignature
*sig
= mono_method_signature (m
);
3186 void *obj
= this_arg
;
3190 if (mono_security_core_clr_enabled () &&
3191 !mono_security_core_clr_ensure_reflection_access_method (m
, &error
)) {
3192 mono_error_set_pending_exception (&error
);
3196 if (!(m
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
3197 if (!mono_class_vtable_full (mono_object_domain (method
), m
->klass
, &error
)) {
3198 mono_error_cleanup (&error
); /* FIXME does this make sense? */
3199 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_class_get_exception_for_failure (m
->klass
));
3204 if (!mono_object_isinst_checked (this_arg
, m
->klass
, &error
)) {
3205 if (!is_ok (&error
)) {
3206 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_error_convert_to_exception (&error
));
3209 char *this_name
= mono_type_get_full_name (mono_object_get_class (this_arg
));
3210 char *target_name
= mono_type_get_full_name (m
->klass
);
3211 char *msg
= g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name
, target_name
);
3212 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", msg
));
3214 g_free (target_name
);
3218 m
= mono_object_get_virtual_method (this_arg
, m
);
3219 /* must pass the pointer to the value for valuetype methods */
3220 if (m
->klass
->valuetype
)
3221 obj
= mono_object_unbox (this_arg
);
3222 } else if (strcmp (m
->name
, ".ctor") && !m
->wrapper_type
) {
3223 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Non-static method requires a target."));
3228 if (sig
->ret
->byref
) {
3229 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
3233 pcount
= params
? mono_array_length (params
): 0;
3234 if (pcount
!= sig
->param_count
) {
3235 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name (mono_defaults
.corlib
, "System.Reflection", "TargetParameterCountException"));
3239 if ((m
->klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
) && !strcmp (m
->name
, ".ctor") && !this_arg
) {
3240 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
3244 image
= m
->klass
->image
;
3245 if (image
->assembly
->ref_only
) {
3246 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
3250 if (image_is_dynamic (image
) && !((MonoDynamicImage
*)image
)->run
) {
3251 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3255 if (m
->klass
->rank
&& !strcmp (m
->name
, ".ctor")) {
3259 intptr_t *lower_bounds
;
3260 pcount
= mono_array_length (params
);
3261 lengths
= (uintptr_t *)alloca (sizeof (uintptr_t) * pcount
);
3262 /* Note: the synthetized array .ctors have int32 as argument type */
3263 for (i
= 0; i
< pcount
; ++i
)
3264 lengths
[i
] = *(int32_t*) ((char*)mono_array_get (params
, gpointer
, i
) + sizeof (MonoObject
));
3266 if (m
->klass
->rank
== 1 && sig
->param_count
== 2 && m
->klass
->element_class
->rank
) {
3267 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3268 arr
= mono_array_new_full_checked (mono_object_domain (params
), m
->klass
, lengths
, NULL
, &error
);
3269 if (!mono_error_ok (&error
)) {
3270 mono_error_set_pending_exception (&error
);
3274 for (i
= 0; i
< mono_array_length (arr
); ++i
) {
3275 MonoArray
*subarray
= mono_array_new_full_checked (mono_object_domain (params
), m
->klass
->element_class
, &lengths
[1], NULL
, &error
);
3276 if (!mono_error_ok (&error
)) {
3277 mono_error_set_pending_exception (&error
);
3280 mono_array_setref_fast (arr
, i
, subarray
);
3282 return (MonoObject
*)arr
;
3285 if (m
->klass
->rank
== pcount
) {
3286 /* Only lengths provided. */
3287 arr
= mono_array_new_full_checked (mono_object_domain (params
), m
->klass
, lengths
, NULL
, &error
);
3288 if (!mono_error_ok (&error
)) {
3289 mono_error_set_pending_exception (&error
);
3293 return (MonoObject
*)arr
;
3295 g_assert (pcount
== (m
->klass
->rank
* 2));
3296 /* The arguments are lower-bound-length pairs */
3297 lower_bounds
= (intptr_t *)g_alloca (sizeof (intptr_t) * pcount
);
3299 for (i
= 0; i
< pcount
/ 2; ++i
) {
3300 lower_bounds
[i
] = *(int32_t*) ((char*)mono_array_get (params
, gpointer
, (i
* 2)) + sizeof (MonoObject
));
3301 lengths
[i
] = *(int32_t*) ((char*)mono_array_get (params
, gpointer
, (i
* 2) + 1) + sizeof (MonoObject
));
3304 arr
= mono_array_new_full_checked (mono_object_domain (params
), m
->klass
, lengths
, lower_bounds
, &error
);
3305 if (!mono_error_ok (&error
)) {
3306 mono_error_set_pending_exception (&error
);
3310 return (MonoObject
*)arr
;
3313 MonoObject
*result
= mono_runtime_invoke_array_checked (m
, obj
, params
, &error
);
3314 mono_error_set_pending_exception (&error
);
3318 #ifndef DISABLE_REMOTING
3319 ICALL_EXPORT MonoObject
*
3320 ves_icall_InternalExecute (MonoReflectionMethod
*method
, MonoObject
*this_arg
, MonoArray
*params
, MonoArray
**outArgs
)
3323 MonoDomain
*domain
= mono_object_domain (method
);
3324 MonoMethod
*m
= method
->method
;
3325 MonoMethodSignature
*sig
= mono_method_signature (m
);
3326 MonoArray
*out_args
;
3328 int i
, j
, outarg_count
= 0;
3330 if (m
->klass
== mono_defaults
.object_class
) {
3331 if (!strcmp (m
->name
, "FieldGetter")) {
3332 MonoClass
*k
= this_arg
->vtable
->klass
;
3336 /* If this is a proxy, then it must be a CBO */
3337 if (k
== mono_defaults
.transparent_proxy_class
) {
3338 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this_arg
;
3339 this_arg
= tp
->rp
->unwrapped_server
;
3340 g_assert (this_arg
);
3341 k
= this_arg
->vtable
->klass
;
3344 name
= mono_array_get (params
, MonoString
*, 1);
3345 str
= mono_string_to_utf8_checked (name
, &error
);
3346 if (mono_error_set_pending_exception (&error
))
3350 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
3353 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
3354 if (field_klass
->valuetype
) {
3355 result
= mono_value_box_checked (domain
, field_klass
, (char *)this_arg
+ field
->offset
, &error
);
3356 if (mono_error_set_pending_exception (&error
))
3359 result
= (MonoObject
*)*((gpointer
*)((char *)this_arg
+ field
->offset
));
3361 out_args
= mono_array_new_checked (domain
, mono_defaults
.object_class
, 1, &error
);
3362 if (mono_error_set_pending_exception (&error
))
3364 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
3365 mono_array_setref (out_args
, 0, result
);
3372 g_assert_not_reached ();
3374 } else if (!strcmp (m
->name
, "FieldSetter")) {
3375 MonoClass
*k
= this_arg
->vtable
->klass
;
3381 /* If this is a proxy, then it must be a CBO */
3382 if (k
== mono_defaults
.transparent_proxy_class
) {
3383 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this_arg
;
3384 this_arg
= tp
->rp
->unwrapped_server
;
3385 g_assert (this_arg
);
3386 k
= this_arg
->vtable
->klass
;
3389 name
= mono_array_get (params
, MonoString
*, 1);
3390 str
= mono_string_to_utf8_checked (name
, &error
);
3391 if (mono_error_set_pending_exception (&error
))
3395 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
3398 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
3399 MonoObject
*val
= (MonoObject
*)mono_array_get (params
, gpointer
, 2);
3401 if (field_klass
->valuetype
) {
3402 size
= mono_type_size (field
->type
, &align
);
3403 g_assert (size
== mono_class_value_size (field_klass
, NULL
));
3404 mono_gc_wbarrier_value_copy ((char *)this_arg
+ field
->offset
, (char*)val
+ sizeof (MonoObject
), 1, field_klass
);
3406 mono_gc_wbarrier_set_field (this_arg
, (char*)this_arg
+ field
->offset
, val
);
3409 out_args
= mono_array_new_checked (domain
, mono_defaults
.object_class
, 0, &error
);
3410 if (mono_error_set_pending_exception (&error
))
3412 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
3421 g_assert_not_reached ();
3426 for (i
= 0; i
< mono_array_length (params
); i
++) {
3427 if (sig
->params
[i
]->byref
)
3431 out_args
= mono_array_new_checked (domain
, mono_defaults
.object_class
, outarg_count
, &error
);
3432 if (mono_error_set_pending_exception (&error
))
3435 /* handle constructors only for objects already allocated */
3436 if (!strcmp (method
->method
->name
, ".ctor"))
3437 g_assert (this_arg
);
3439 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3440 g_assert (!method
->method
->klass
->valuetype
);
3441 result
= mono_runtime_invoke_array_checked (method
->method
, this_arg
, params
, &error
);
3442 if (mono_error_set_pending_exception (&error
))
3445 for (i
= 0, j
= 0; i
< mono_array_length (params
); i
++) {
3446 if (sig
->params
[i
]->byref
) {
3448 arg
= mono_array_get (params
, gpointer
, i
);
3449 mono_array_setref (out_args
, j
, arg
);
3454 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
3461 read_enum_value (const char *mem
, int type
)
3464 case MONO_TYPE_BOOLEAN
:
3466 return *(guint8
*)mem
;
3468 return *(gint8
*)mem
;
3469 case MONO_TYPE_CHAR
:
3471 return read16 (mem
);
3473 return (gint16
) read16 (mem
);
3475 return read32 (mem
);
3477 return (gint32
) read32 (mem
);
3480 return read64 (mem
);
3482 g_assert_not_reached ();
3488 write_enum_value (char *mem
, int type
, guint64 value
)
3492 case MONO_TYPE_I1
: {
3493 guint8
*p
= (guint8
*)mem
;
3499 case MONO_TYPE_CHAR
: {
3500 guint16
*p
= (guint16
*)mem
;
3505 case MONO_TYPE_I4
: {
3506 guint32
*p
= (guint32
*)mem
;
3511 case MONO_TYPE_I8
: {
3512 guint64
*p
= (guint64
*)mem
;
3517 g_assert_not_reached ();
3522 ICALL_EXPORT MonoObject
*
3523 ves_icall_System_Enum_ToObject (MonoReflectionType
*enumType
, guint64 value
)
3531 domain
= mono_object_domain (enumType
);
3532 enumc
= mono_class_from_mono_type (enumType
->type
);
3534 mono_class_init_checked (enumc
, &error
);
3535 if (mono_error_set_pending_exception (&error
))
3538 etype
= mono_class_enum_basetype (enumc
);
3540 res
= mono_object_new_checked (domain
, enumc
, &error
);
3541 if (mono_error_set_pending_exception (&error
))
3543 write_enum_value ((char *)res
+ sizeof (MonoObject
), etype
->type
, value
);
3548 ICALL_EXPORT MonoBoolean
3549 ves_icall_System_Enum_InternalHasFlag (MonoObject
*a
, MonoObject
*b
)
3551 int size
= mono_class_value_size (a
->vtable
->klass
, NULL
);
3552 guint64 a_val
= 0, b_val
= 0;
3554 memcpy (&a_val
, mono_object_unbox (a
), size
);
3555 memcpy (&b_val
, mono_object_unbox (b
), size
);
3557 return (a_val
& b_val
) == b_val
;
3560 ICALL_EXPORT MonoObject
*
3561 ves_icall_System_Enum_get_value (MonoObject
*eobj
)
3573 g_assert (eobj
->vtable
->klass
->enumtype
);
3575 enumc
= mono_class_from_mono_type (mono_class_enum_basetype (eobj
->vtable
->klass
));
3576 res
= mono_object_new_checked (mono_object_domain (eobj
), enumc
, &error
);
3577 if (mono_error_set_pending_exception (&error
))
3579 dst
= (char *)res
+ sizeof (MonoObject
);
3580 src
= (char *)eobj
+ sizeof (MonoObject
);
3581 size
= mono_class_value_size (enumc
, NULL
);
3583 memcpy (dst
, src
, size
);
3588 ICALL_EXPORT MonoReflectionType
*
3589 ves_icall_System_Enum_get_underlying_type (MonoReflectionType
*type
)
3592 MonoReflectionType
*ret
;
3596 klass
= mono_class_from_mono_type (type
->type
);
3597 mono_class_init_checked (klass
, &error
);
3598 if (mono_error_set_pending_exception (&error
))
3601 etype
= mono_class_enum_basetype (klass
);
3603 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3607 ret
= mono_type_get_object_checked (mono_object_domain (type
), etype
, &error
);
3608 mono_error_set_pending_exception (&error
);
3614 ves_icall_System_Enum_compare_value_to (MonoObject
*eobj
, MonoObject
*other
)
3616 gpointer tdata
= (char *)eobj
+ sizeof (MonoObject
);
3617 gpointer odata
= (char *)other
+ sizeof (MonoObject
);
3618 MonoType
*basetype
= mono_class_enum_basetype (eobj
->vtable
->klass
);
3619 g_assert (basetype
);
3624 if (eobj
->vtable
->klass
!= other
->vtable
->klass
)
3627 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3628 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3629 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3632 return me > other ? 1 : -1; \
3635 switch (basetype
->type
) {
3637 COMPARE_ENUM_VALUES (guint8
);
3639 COMPARE_ENUM_VALUES (gint8
);
3640 case MONO_TYPE_CHAR
:
3642 COMPARE_ENUM_VALUES (guint16
);
3644 COMPARE_ENUM_VALUES (gint16
);
3646 COMPARE_ENUM_VALUES (guint32
);
3648 COMPARE_ENUM_VALUES (gint32
);
3650 COMPARE_ENUM_VALUES (guint64
);
3652 COMPARE_ENUM_VALUES (gint64
);
3656 #undef COMPARE_ENUM_VALUES
3657 /* indicates that the enum was of an unsupported unerlying type */
3662 ves_icall_System_Enum_get_hashcode (MonoObject
*eobj
)
3664 gpointer data
= (char *)eobj
+ sizeof (MonoObject
);
3665 MonoType
*basetype
= mono_class_enum_basetype (eobj
->vtable
->klass
);
3666 g_assert (basetype
);
3668 switch (basetype
->type
) {
3669 case MONO_TYPE_I1
: {
3670 gint8 value
= *((gint8
*)data
);
3671 return ((int)value
^ (int)value
<< 8);
3674 return *((guint8
*)data
);
3675 case MONO_TYPE_CHAR
:
3677 return *((guint16
*)data
);
3679 case MONO_TYPE_I2
: {
3680 gint16 value
= *((gint16
*)data
);
3681 return ((int)(guint16
)value
| (((int)value
) << 16));
3684 return *((guint32
*)data
);
3686 return *((gint32
*)data
);
3688 case MONO_TYPE_I8
: {
3689 gint64 value
= *((gint64
*)data
);
3690 return (gint
)(value
& 0xffffffff) ^ (int)(value
>> 32);
3693 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3698 ICALL_EXPORT MonoBoolean
3699 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType
*type
, MonoArray
**values
, MonoArray
**names
)
3702 MonoDomain
*domain
= mono_object_domain (type
);
3703 MonoClass
*enumc
= mono_class_from_mono_type (type
->type
);
3704 guint j
= 0, nvalues
;
3706 MonoClassField
*field
;
3708 guint64 field_value
, previous_value
= 0;
3709 gboolean sorted
= TRUE
;
3711 mono_class_init_checked (enumc
, &error
);
3712 if (mono_error_set_pending_exception (&error
))
3716 if (!enumc
->enumtype
) {
3717 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3721 base_type
= mono_class_enum_basetype (enumc
)->type
;
3723 nvalues
= mono_class_num_fields (enumc
) ? mono_class_num_fields (enumc
) - 1 : 0;
3724 *names
= mono_array_new_checked (domain
, mono_defaults
.string_class
, nvalues
, &error
);
3725 if (mono_error_set_pending_exception (&error
))
3727 *values
= mono_array_new_checked (domain
, mono_defaults
.uint64_class
, nvalues
, &error
);
3728 if (mono_error_set_pending_exception (&error
))
3732 while ((field
= mono_class_get_fields (enumc
, &iter
))) {
3734 MonoTypeEnum def_type
;
3736 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
3738 if (strcmp ("value__", mono_field_get_name (field
)) == 0)
3740 if (mono_field_is_deleted (field
))
3742 mono_array_setref (*names
, j
, mono_string_new (domain
, mono_field_get_name (field
)));
3744 p
= mono_class_get_field_default_value (field
, &def_type
);
3745 /* len = */ mono_metadata_decode_blob_size (p
, &p
);
3747 field_value
= read_enum_value (p
, base_type
);
3748 mono_array_set (*values
, guint64
, j
, field_value
);
3750 if (previous_value
> field_value
)
3753 previous_value
= field_value
;
3761 BFLAGS_IgnoreCase
= 1,
3762 BFLAGS_DeclaredOnly
= 2,
3763 BFLAGS_Instance
= 4,
3765 BFLAGS_Public
= 0x10,
3766 BFLAGS_NonPublic
= 0x20,
3767 BFLAGS_FlattenHierarchy
= 0x40,
3768 BFLAGS_InvokeMethod
= 0x100,
3769 BFLAGS_CreateInstance
= 0x200,
3770 BFLAGS_GetField
= 0x400,
3771 BFLAGS_SetField
= 0x800,
3772 BFLAGS_GetProperty
= 0x1000,
3773 BFLAGS_SetProperty
= 0x2000,
3774 BFLAGS_ExactBinding
= 0x10000,
3775 BFLAGS_SuppressChangeType
= 0x20000,
3776 BFLAGS_OptionalParamBinding
= 0x40000
3779 ICALL_EXPORT MonoArray
*
3780 ves_icall_RuntimeType_GetFields_internal (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoReflectionType
*reftype
)
3784 MonoClass
*startklass
, *klass
, *refklass
;
3789 char *utf8_name
= NULL
;
3790 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3791 MonoClassField
*field
;
3792 MonoPtrArray tmp_array
;
3794 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3795 if (type
->type
->byref
) {
3796 MonoArray
*result
= mono_array_new_checked (domain
, mono_defaults
.field_info_class
, 0, &error
);
3797 mono_error_set_pending_exception (&error
);
3801 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3802 refklass
= mono_class_from_mono_type (reftype
->type
);
3804 mono_ptr_array_init (tmp_array
, 2, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection fields list");
3807 if (mono_class_has_failure (klass
)) {
3808 mono_ptr_array_destroy (tmp_array
);
3809 mono_set_pending_exception (mono_class_get_exception_for_failure (klass
));
3814 while ((field
= mono_class_get_fields_lazy (klass
, &iter
))) {
3815 guint32 flags
= mono_field_get_flags (field
);
3817 if (mono_field_is_deleted_with_flags (field
, flags
))
3819 if ((flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3820 if (bflags
& BFLAGS_Public
)
3822 } else if ((klass
== startklass
) || (flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3823 if (bflags
& BFLAGS_NonPublic
) {
3830 if (flags
& FIELD_ATTRIBUTE_STATIC
) {
3831 if (bflags
& BFLAGS_Static
)
3832 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3835 if (bflags
& BFLAGS_Instance
)
3843 if (utf8_name
== NULL
) {
3844 utf8_name
= mono_string_to_utf8_checked (name
, &error
);
3845 if (!is_ok (&error
))
3847 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
3850 if (compare_func (mono_field_get_name (field
), utf8_name
))
3854 member
= (MonoObject
*)mono_field_get_object_checked (domain
, refklass
, field
, &error
);
3855 if (!mono_error_ok (&error
))
3857 mono_ptr_array_append (tmp_array
, member
);
3859 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3862 res
= mono_array_new_cached (domain
, mono_defaults
.field_info_class
, mono_ptr_array_size (tmp_array
), &error
);
3863 if (!is_ok (&error
))
3866 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3867 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3869 mono_ptr_array_destroy (tmp_array
);
3871 if (utf8_name
!= NULL
)
3876 mono_ptr_array_destroy (tmp_array
);
3877 mono_error_set_pending_exception (&error
);
3882 method_nonpublic (MonoMethod
* method
, gboolean start_klass
)
3884 switch (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) {
3885 case METHOD_ATTRIBUTE_ASSEM
:
3886 return (start_klass
|| mono_defaults
.generic_ilist_class
);
3887 case METHOD_ATTRIBUTE_PRIVATE
:
3889 case METHOD_ATTRIBUTE_PUBLIC
:
3897 mono_class_get_methods_by_name (MonoClass
*klass
, const char *name
, guint32 bflags
, gboolean ignore_case
, gboolean allow_ctors
, MonoException
**ex
)
3900 MonoClass
*startklass
;
3904 /*FIXME, use MonoBitSet*/
3905 guint32 method_slots_default
[8];
3906 guint32
*method_slots
= NULL
;
3907 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3909 array
= g_ptr_array_new ();
3914 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3916 /* An optimization for calls made from Delegate:CreateDelegate () */
3917 if (klass
->delegate
&& name
&& !strcmp (name
, "Invoke") && (bflags
== (BFLAGS_Public
| BFLAGS_Static
| BFLAGS_Instance
))) {
3918 method
= mono_get_delegate_invoke (klass
);
3921 g_ptr_array_add (array
, method
);
3925 mono_class_setup_methods (klass
);
3926 mono_class_setup_vtable (klass
);
3927 if (mono_class_has_failure (klass
))
3930 if (is_generic_parameter (&klass
->byval_arg
))
3931 nslots
= mono_class_get_vtable_size (klass
->parent
);
3933 nslots
= MONO_CLASS_IS_INTERFACE (klass
) ? mono_class_num_methods (klass
) : mono_class_get_vtable_size (klass
);
3934 if (nslots
>= sizeof (method_slots_default
) * 8) {
3935 method_slots
= g_new0 (guint32
, nslots
/ 32 + 1);
3937 method_slots
= method_slots_default
;
3938 memset (method_slots
, 0, sizeof (method_slots_default
));
3941 mono_class_setup_methods (klass
);
3942 mono_class_setup_vtable (klass
);
3943 if (mono_class_has_failure (klass
))
3947 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3949 if (method
->slot
!= -1) {
3950 g_assert (method
->slot
< nslots
);
3951 if (method_slots
[method
->slot
>> 5] & (1 << (method
->slot
& 0x1f)))
3953 if (!(method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
))
3954 method_slots
[method
->slot
>> 5] |= 1 << (method
->slot
& 0x1f);
3957 if (!allow_ctors
&& method
->name
[0] == '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0))
3959 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3960 if (bflags
& BFLAGS_Public
)
3962 } else if ((bflags
& BFLAGS_NonPublic
) && method_nonpublic (method
, (klass
== startklass
))) {
3968 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3969 if (bflags
& BFLAGS_Static
)
3970 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3973 if (bflags
& BFLAGS_Instance
)
3981 if (compare_func (name
, method
->name
))
3986 g_ptr_array_add (array
, method
);
3988 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3990 if (method_slots
!= method_slots_default
)
3991 g_free (method_slots
);
3996 if (method_slots
!= method_slots_default
)
3997 g_free (method_slots
);
3998 g_ptr_array_free (array
, TRUE
);
4000 if (mono_class_has_failure (klass
)) {
4001 *ex
= mono_class_get_exception_for_failure (klass
);
4003 *ex
= mono_get_exception_execution_engine ("Unknown error");
4008 ICALL_EXPORT MonoArray
*
4009 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
4011 static MonoClass
*MethodInfo_array
;
4015 MonoVTable
*array_vtable
;
4016 MonoException
*ex
= NULL
;
4017 const char *mname
= NULL
;
4018 GPtrArray
*method_array
;
4019 MonoClass
*klass
, *refklass
;
4022 mono_error_init (&error
);
4024 if (!MethodInfo_array
) {
4025 MonoClass
*klass
= mono_array_class_get (mono_defaults
.method_info_class
, 1);
4026 mono_memory_barrier ();
4027 MethodInfo_array
= klass
;
4030 klass
= mono_class_from_mono_type (type
->type
);
4031 refklass
= mono_class_from_mono_type (reftype
->type
);
4032 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4033 array_vtable
= mono_class_vtable_full (domain
, MethodInfo_array
, &error
);
4034 if (!is_ok (&error
)) {
4035 mono_error_set_pending_exception (&error
);
4038 if (type
->type
->byref
) {
4039 res
= mono_array_new_specific_checked (array_vtable
, 0, &error
);
4040 mono_error_set_pending_exception (&error
);
4046 mname
= mono_string_to_utf8_checked (name
, &error
);
4047 if (mono_error_set_pending_exception (&error
))
4051 method_array
= mono_class_get_methods_by_name (klass
, mname
, bflags
, ignore_case
, FALSE
, &ex
);
4052 g_free ((char*)mname
);
4054 mono_set_pending_exception (ex
);
4058 res
= mono_array_new_specific_checked (array_vtable
, method_array
->len
, &error
);
4059 if (!mono_error_ok (&error
)) {
4060 mono_error_set_pending_exception (&error
);
4064 for (i
= 0; i
< method_array
->len
; ++i
) {
4065 MonoMethod
*method
= (MonoMethod
*)g_ptr_array_index (method_array
, i
);
4066 MonoReflectionMethod
*rm
= mono_method_get_object_checked (domain
, method
, refklass
, &error
);
4067 if (!mono_error_ok (&error
))
4069 mono_array_setref (res
, i
, rm
);
4073 g_ptr_array_free (method_array
, TRUE
);
4074 if (!mono_error_ok (&error
))
4075 mono_set_pending_exception (mono_error_convert_to_exception (&error
));
4079 ICALL_EXPORT MonoArray
*
4080 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
4083 MonoClass
*startklass
, *klass
, *refklass
;
4084 MonoArray
*res
= NULL
;
4088 gpointer iter
= NULL
;
4089 MonoPtrArray tmp_array
;
4092 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4093 if (type
->type
->byref
) {
4094 res
= mono_array_new_cached (domain
, mono_defaults
.method_info_class
, 0, &error
);
4095 mono_error_set_pending_exception (&error
);
4099 mono_ptr_array_init (tmp_array
, 4, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection constructors list"); /*FIXME, guestimating*/
4102 klass
= startklass
= mono_class_from_mono_type (type
->type
);
4103 refklass
= mono_class_from_mono_type (reftype
->type
);
4105 mono_class_setup_methods (klass
);
4106 if (mono_class_has_failure (klass
)) {
4107 mono_set_pending_exception (mono_class_get_exception_for_failure (klass
));
4112 while ((method
= mono_class_get_methods (klass
, &iter
))) {
4114 if (strcmp (method
->name
, ".ctor") && strcmp (method
->name
, ".cctor"))
4116 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
4117 if (bflags
& BFLAGS_Public
)
4120 if (bflags
& BFLAGS_NonPublic
)
4126 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
4127 if (bflags
& BFLAGS_Static
)
4128 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
4131 if (bflags
& BFLAGS_Instance
)
4137 member
= (MonoObject
*)mono_method_get_object_checked (domain
, method
, refklass
, &error
);
4138 if (mono_error_set_pending_exception (&error
))
4141 mono_ptr_array_append (tmp_array
, member
);
4144 res
= mono_array_new_cached (domain
, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array
), &error
);
4145 if (mono_error_set_pending_exception (&error
))
4148 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4149 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4152 mono_ptr_array_destroy (tmp_array
);
4158 property_hash (gconstpointer data
)
4160 MonoProperty
*prop
= (MonoProperty
*)data
;
4162 return g_str_hash (prop
->name
);
4166 property_accessor_override (MonoMethod
*method1
, MonoMethod
*method2
)
4168 if (method1
->slot
!= -1 && method1
->slot
== method2
->slot
)
4171 if (mono_class_get_generic_type_definition (method1
->klass
) == mono_class_get_generic_type_definition (method2
->klass
)) {
4172 if (method1
->is_inflated
)
4173 method1
= ((MonoMethodInflated
*) method1
)->declaring
;
4174 if (method2
->is_inflated
)
4175 method2
= ((MonoMethodInflated
*) method2
)->declaring
;
4178 return mono_metadata_signature_equal (mono_method_signature (method1
), mono_method_signature (method2
));
4182 property_equal (MonoProperty
*prop1
, MonoProperty
*prop2
)
4184 // Properties are hide-by-name-and-signature
4185 if (!g_str_equal (prop1
->name
, prop2
->name
))
4188 /* If we see a property in a generic method, we want to
4189 compare the generic signatures, not the inflated signatures
4190 because we might conflate two properties that were
4194 public T this[T t] { getter { return t; } } // method 1
4195 public U this[U u] { getter { return u; } } // method 2
4198 If we see int Foo<int,int>::Item[int] we need to know if
4199 the indexer came from method 1 or from method 2, and we
4200 shouldn't conflate them. (Bugzilla 36283)
4202 if (prop1
->get
&& prop2
->get
&& !property_accessor_override (prop1
->get
, prop2
->get
))
4205 if (prop1
->set
&& prop2
->set
&& !property_accessor_override (prop1
->set
, prop2
->set
))
4212 property_accessor_nonpublic (MonoMethod
* accessor
, gboolean start_klass
)
4217 return method_nonpublic (accessor
, start_klass
);
4220 ICALL_EXPORT MonoArray
*
4221 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
4225 MonoClass
*startklass
, *klass
;
4231 gchar
*propname
= NULL
;
4232 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
4234 GHashTable
*properties
= NULL
;
4235 MonoPtrArray tmp_array
;
4237 mono_error_init (&error
);
4239 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4240 if (type
->type
->byref
) {
4241 res
= mono_array_new_cached (domain
, mono_class_get_property_info_class (), 0, &error
);
4242 mono_error_set_pending_exception (&error
);
4246 mono_ptr_array_init (tmp_array
, 8, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4248 klass
= startklass
= mono_class_from_mono_type (type
->type
);
4251 propname
= mono_string_to_utf8_checked (name
, &error
);
4252 if (mono_error_set_pending_exception (&error
))
4254 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
4257 properties
= g_hash_table_new (property_hash
, (GEqualFunc
)property_equal
);
4259 mono_class_setup_methods (klass
);
4260 mono_class_setup_vtable (klass
);
4261 if (mono_class_has_failure (klass
))
4265 while ((prop
= mono_class_get_properties (klass
, &iter
))) {
4271 flags
= method
->flags
;
4274 if ((prop
->get
&& ((prop
->get
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
)) ||
4275 (prop
->set
&& ((prop
->set
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
))) {
4276 if (bflags
& BFLAGS_Public
)
4278 } else if (bflags
& BFLAGS_NonPublic
) {
4279 if (property_accessor_nonpublic(prop
->get
, startklass
== klass
) ||
4280 property_accessor_nonpublic(prop
->set
, startklass
== klass
)) {
4287 if (flags
& METHOD_ATTRIBUTE_STATIC
) {
4288 if (bflags
& BFLAGS_Static
)
4289 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
4292 if (bflags
& BFLAGS_Instance
)
4301 if (compare_func (propname
, prop
->name
))
4305 if (g_hash_table_lookup (properties
, prop
))
4308 MonoReflectionProperty
*pr
= mono_property_get_object_checked (domain
, startklass
, prop
, &error
);
4311 mono_ptr_array_append (tmp_array
, pr
);
4313 g_hash_table_insert (properties
, prop
, prop
);
4315 if ((!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
)))
4318 g_hash_table_destroy (properties
);
4321 res
= mono_array_new_cached (domain
, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array
), &error
);
4322 if (!is_ok (&error
))
4324 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4325 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4327 mono_ptr_array_destroy (tmp_array
);
4334 if (mono_class_has_failure (klass
))
4335 mono_error_set_for_class_failure (&error
, klass
);
4339 g_hash_table_destroy (properties
);
4342 mono_ptr_array_destroy (tmp_array
);
4344 mono_error_set_pending_exception (&error
);
4350 event_hash (gconstpointer data
)
4352 MonoEvent
*event
= (MonoEvent
*)data
;
4354 return g_str_hash (event
->name
);
4358 event_equal (MonoEvent
*event1
, MonoEvent
*event2
)
4360 // Events are hide-by-name
4361 return g_str_equal (event1
->name
, event2
->name
);
4364 ICALL_EXPORT MonoArray
*
4365 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoReflectionType
*reftype
)
4369 MonoClass
*startklass
, *klass
;
4375 char *utf8_name
= NULL
;
4376 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
4377 GHashTable
*events
= NULL
;
4378 MonoPtrArray tmp_array
;
4380 mono_error_init (&error
);
4382 domain
= mono_object_domain (type
);
4383 if (type
->type
->byref
) {
4384 res
= mono_array_new_cached (domain
, mono_class_get_event_info_class (), 0, &error
);
4385 mono_error_set_pending_exception (&error
);
4389 mono_ptr_array_init (tmp_array
, 4, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection events list");
4391 klass
= startklass
= mono_class_from_mono_type (type
->type
);
4393 events
= g_hash_table_new (event_hash
, (GEqualFunc
)event_equal
);
4395 mono_class_setup_methods (klass
);
4396 mono_class_setup_vtable (klass
);
4397 if (mono_class_has_failure (klass
))
4401 while ((event
= mono_class_get_events (klass
, &iter
))) {
4403 method
= event
->add
;
4405 method
= event
->remove
;
4407 method
= event
->raise
;
4409 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
4410 if (bflags
& BFLAGS_Public
)
4412 } else if ((klass
== startklass
) || (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) {
4413 if (bflags
& BFLAGS_NonPublic
)
4418 if (bflags
& BFLAGS_NonPublic
)
4424 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
4425 if (bflags
& BFLAGS_Static
)
4426 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
4429 if (bflags
& BFLAGS_Instance
)
4434 if (bflags
& BFLAGS_Instance
)
4440 if (utf8_name
== NULL
) {
4441 utf8_name
= mono_string_to_utf8_checked (name
, &error
);
4442 if (!is_ok (&error
))
4444 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
4447 if (compare_func (event
->name
, utf8_name
))
4451 if (g_hash_table_lookup (events
, event
))
4454 MonoReflectionEvent
*ev_obj
;
4455 ev_obj
= mono_event_get_object_checked (domain
, startklass
, event
, &error
);
4458 mono_ptr_array_append (tmp_array
, ev_obj
);
4460 g_hash_table_insert (events
, event
, event
);
4462 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
4465 g_hash_table_destroy (events
);
4467 res
= mono_array_new_cached (domain
, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array
), &error
);
4468 if (!is_ok (&error
))
4471 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4472 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4474 mono_ptr_array_destroy (tmp_array
);
4476 if (utf8_name
!= NULL
)
4482 if (mono_class_has_failure (klass
))
4483 mono_error_set_for_class_failure (&error
, klass
);
4488 g_hash_table_destroy (events
);
4489 if (utf8_name
!= NULL
)
4492 mono_ptr_array_destroy (tmp_array
);
4494 mono_error_set_pending_exception (&error
);
4498 ICALL_EXPORT MonoArray
*
4499 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
4502 MonoReflectionType
*rt
;
4505 MonoArray
*res
= NULL
;
4510 MonoPtrArray tmp_array
;
4512 mono_error_init (&error
);
4514 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4515 if (type
->type
->byref
) {
4516 MonoArray
*result
= mono_array_new_cached (domain
, mono_defaults
.runtimetype_class
, 0, &error
);
4517 mono_error_set_pending_exception (&error
);
4520 klass
= mono_class_from_mono_type (type
->type
);
4523 * If a nested type is generic, return its generic type definition.
4524 * Note that this means that the return value is essentially the set
4525 * of nested types of the generic type definition of @klass.
4527 * A note in MSDN claims that a generic type definition can have
4528 * nested types that aren't generic. In any case, the container of that
4529 * nested type would be the generic type definition.
4531 if (klass
->generic_class
)
4532 klass
= klass
->generic_class
->container_class
;
4534 mono_ptr_array_init (tmp_array
, 1, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection nested types list");
4536 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
4538 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
4539 if (bflags
& BFLAGS_Public
)
4542 if (bflags
& BFLAGS_NonPublic
)
4550 str
= mono_string_to_utf8_checked (name
, &error
);
4551 if (!is_ok (&error
))
4553 mono_identifier_unescape_type_name_chars (str
);
4556 if (strcmp (nested
->name
, str
))
4560 rt
= mono_type_get_object_checked (domain
, &nested
->byval_arg
, &error
);
4561 if (!is_ok (&error
))
4564 mono_ptr_array_append (tmp_array
, (MonoObject
*) rt
);
4567 res
= mono_array_new_cached (domain
, mono_defaults
.runtimetype_class
, mono_ptr_array_size (tmp_array
), &error
);
4568 if (!is_ok (&error
))
4571 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4572 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4575 mono_ptr_array_destroy (tmp_array
);
4579 mono_error_set_pending_exception (&error
);
4583 ICALL_EXPORT MonoReflectionType
*
4584 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly
*assembly
, MonoReflectionModule
*module
, MonoString
*name
, MonoBoolean throwOnError
, MonoBoolean ignoreCase
)
4587 MonoReflectionType
*ret
;
4589 MonoType
*type
= NULL
;
4590 MonoTypeNameParse info
;
4591 gboolean type_resolve
;
4593 /* On MS.NET, this does not fire a TypeResolve event */
4594 type_resolve
= TRUE
;
4595 str
= mono_string_to_utf8_checked (name
, &error
);
4596 if (mono_error_set_pending_exception (&error
))
4598 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4599 if (!mono_reflection_parse_type (str
, &info
)) {
4601 mono_reflection_free_type_info (&info
);
4603 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4606 /*g_print ("failed parse\n");*/
4610 if (info
.assembly
.name
) {
4612 mono_reflection_free_type_info (&info
);
4614 /* 1.0 and 2.0 throw different exceptions */
4615 if (mono_defaults
.generic_ilist_class
)
4616 mono_set_pending_exception (mono_get_exception_argument (NULL
, "Type names passed to Assembly.GetType() must not specify an assembly."));
4618 mono_set_pending_exception (mono_get_exception_type_load (name
, NULL
));
4624 if (module
!= NULL
) {
4625 if (module
->image
) {
4626 type
= mono_reflection_get_type_checked (module
->image
, module
->image
, &info
, ignoreCase
, &type_resolve
, &error
);
4627 if (!is_ok (&error
)) {
4629 mono_reflection_free_type_info (&info
);
4630 mono_error_set_pending_exception (&error
);
4637 if (assembly_is_dynamic (assembly
->assembly
)) {
4638 /* Enumerate all modules */
4639 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)assembly
;
4643 if (abuilder
->modules
) {
4644 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
4645 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
4646 type
= mono_reflection_get_type_checked (&mb
->dynamic_image
->image
, &mb
->dynamic_image
->image
, &info
, ignoreCase
, &type_resolve
, &error
);
4647 if (!is_ok (&error
)) {
4649 mono_reflection_free_type_info (&info
);
4650 mono_error_set_pending_exception (&error
);
4658 if (!type
&& abuilder
->loaded_modules
) {
4659 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
4660 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
4661 type
= mono_reflection_get_type_checked (mod
->image
, mod
->image
, &info
, ignoreCase
, &type_resolve
, &error
);
4662 if (!is_ok (&error
)) {
4664 mono_reflection_free_type_info (&info
);
4665 mono_error_set_pending_exception (&error
);
4674 type
= mono_reflection_get_type_checked (assembly
->assembly
->image
, assembly
->assembly
->image
, &info
, ignoreCase
, &type_resolve
, &error
);
4675 if (!is_ok (&error
)) {
4677 mono_reflection_free_type_info (&info
);
4678 mono_error_set_pending_exception (&error
);
4683 mono_reflection_free_type_info (&info
);
4685 MonoException
*e
= NULL
;
4688 e
= mono_get_exception_type_load (name
, NULL
);
4691 mono_set_pending_exception (e
);
4695 if (type
->type
== MONO_TYPE_CLASS
) {
4696 MonoClass
*klass
= mono_type_get_class (type
);
4698 /* need to report exceptions ? */
4699 if (throwOnError
&& mono_class_has_failure (klass
)) {
4700 /* report SecurityException (or others) that occured when loading the assembly */
4701 MonoException
*exc
= mono_class_get_exception_for_failure (klass
);
4702 mono_set_pending_exception (exc
);
4707 /* g_print ("got it\n"); */
4708 ret
= mono_type_get_object_checked (mono_object_domain (assembly
), type
, &error
);
4709 mono_error_set_pending_exception (&error
);
4715 replace_shadow_path (MonoDomain
*domain
, gchar
*dirname
, gchar
**filename
)
4718 gchar
*shadow_ini_file
;
4721 /* Check for shadow-copied assembly */
4722 if (mono_is_shadow_copy_enabled (domain
, dirname
)) {
4723 shadow_ini_file
= g_build_filename (dirname
, "__AssemblyInfo__.ini", NULL
);
4725 if (!g_file_get_contents (shadow_ini_file
, &content
, &len
, NULL
) ||
4726 !g_file_test (content
, G_FILE_TEST_IS_REGULAR
)) {
4732 g_free (shadow_ini_file
);
4733 if (content
!= NULL
) {
4736 *filename
= content
;
4743 ICALL_EXPORT MonoString
*
4744 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly
*assembly
, MonoBoolean escaped
)
4746 MonoDomain
*domain
= mono_object_domain (assembly
);
4747 MonoAssembly
*mass
= assembly
->assembly
;
4748 MonoString
*res
= NULL
;
4753 if (g_path_is_absolute (mass
->image
->name
)) {
4754 absolute
= g_strdup (mass
->image
->name
);
4755 dirname
= g_path_get_dirname (absolute
);
4757 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
4758 dirname
= g_strdup (mass
->basedir
);
4761 replace_shadow_path (domain
, dirname
, &absolute
);
4766 for (i
= strlen (absolute
) - 1; i
>= 0; i
--)
4767 if (absolute
[i
] == '\\')
4772 uri
= g_filename_to_uri (absolute
, NULL
, NULL
);
4774 const char *prepend
= "file://";
4776 if (*absolute
== '/' && *(absolute
+ 1) == '/') {
4779 prepend
= "file:///";
4782 uri
= g_strconcat (prepend
, absolute
, NULL
);
4786 res
= mono_string_new (domain
, uri
);
4793 ICALL_EXPORT MonoBoolean
4794 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly
*assembly
)
4796 MonoAssembly
*mass
= assembly
->assembly
;
4798 return mass
->in_gac
;
4801 ICALL_EXPORT MonoReflectionAssembly
*
4802 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString
*mname
, MonoObject
*evidence
)
4807 MonoImageOpenStatus status
;
4808 MonoReflectionAssembly
* result
= NULL
;
4810 name
= mono_string_to_utf8_checked (mname
, &error
);
4811 if (mono_error_set_pending_exception (&error
))
4813 res
= mono_assembly_load_with_partial_name (name
, &status
);
4819 result
= mono_assembly_get_object_checked (mono_domain_get (), res
, &error
);
4821 mono_error_set_pending_exception (&error
);
4825 ICALL_EXPORT MonoString
*
4826 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly
*assembly
)
4828 MonoDomain
*domain
= mono_object_domain (assembly
);
4831 res
= mono_string_new (domain
, mono_image_get_filename (assembly
->assembly
->image
));
4836 ICALL_EXPORT MonoBoolean
4837 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly
*assembly
)
4839 return assembly
->assembly
->ref_only
;
4842 ICALL_EXPORT MonoString
*
4843 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly
*assembly
)
4845 MonoDomain
*domain
= mono_object_domain (assembly
);
4847 return mono_string_new (domain
, assembly
->assembly
->image
->version
);
4850 ICALL_EXPORT MonoReflectionMethod
*
4851 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly
*assembly
)
4854 MonoReflectionMethod
*res
= NULL
;
4857 guint32 token
= mono_image_get_entry_point (assembly
->assembly
->image
);
4861 method
= mono_get_method_checked (assembly
->assembly
->image
, token
, NULL
, NULL
, &error
);
4862 if (!mono_error_ok (&error
))
4865 res
= mono_method_get_object_checked (mono_object_domain (assembly
), method
, NULL
, &error
);
4868 if (!mono_error_ok (&error
))
4869 mono_error_set_pending_exception (&error
);
4873 ICALL_EXPORT MonoReflectionModule
*
4874 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly
*assembly
)
4877 MonoReflectionModule
*result
= NULL
;
4878 result
= mono_module_get_object_checked (mono_object_domain (assembly
), assembly
->assembly
->image
, &error
);
4879 if (!mono_error_ok (&error
))
4880 mono_error_set_pending_exception (&error
);
4884 ICALL_EXPORT MonoArray
*
4885 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly
*assembly
)
4888 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4889 MonoArray
*result
= mono_array_new_checked (mono_object_domain (assembly
), mono_defaults
.string_class
, table
->rows
, &error
);
4890 if (mono_error_set_pending_exception (&error
))
4895 for (i
= 0; i
< table
->rows
; ++i
) {
4896 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_MANIFEST_NAME
));
4897 mono_array_setref (result
, i
, mono_string_new (mono_object_domain (assembly
), val
));
4902 ICALL_EXPORT MonoString
*
4903 ves_icall_System_Reflection_Assembly_GetAotId ()
4906 guint8 aotid_sum
= 0;
4907 MonoDomain
* domain
= mono_domain_get ();
4909 if (!domain
->entry_assembly
|| !domain
->entry_assembly
->image
)
4912 guint8 (*aotid
)[16] = &domain
->entry_assembly
->image
->aotid
;
4914 for (i
= 0; i
< 16; ++i
)
4915 aotid_sum
|= (*aotid
)[i
];
4920 return mono_string_new (domain
, mono_guid_to_string((guint8
*) aotid
));
4924 create_version (MonoDomain
*domain
, guint32 major
, guint32 minor
, guint32 build
, guint32 revision
, MonoError
*error
)
4926 static MonoMethod
*create_version
= NULL
;
4930 mono_error_init (error
);
4933 if (!create_version
) {
4934 MonoMethodDesc
*desc
= mono_method_desc_new (":.ctor(int,int,int,int)", FALSE
);
4935 create_version
= mono_method_desc_search_in_class (desc
, mono_class_get_system_version_class ());
4936 g_assert (create_version
);
4937 mono_method_desc_free (desc
);
4943 args
[3] = &revision
;
4944 result
= mono_object_new_checked (domain
, mono_class_get_system_version_class (), error
);
4945 return_val_if_nok (error
, NULL
);
4947 mono_runtime_invoke_checked (create_version
, result
, args
, error
);
4948 return_val_if_nok (error
, NULL
);
4953 ICALL_EXPORT MonoArray
*
4954 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly
*assembly
)
4958 MonoDomain
*domain
= mono_object_domain (assembly
);
4960 static MonoMethod
*create_culture
= NULL
;
4961 MonoImage
*image
= assembly
->assembly
->image
;
4965 t
= &assembly
->assembly
->image
->tables
[MONO_TABLE_ASSEMBLYREF
];
4968 result
= mono_array_new_checked (domain
, mono_class_get_assembly_name_class (), count
, &error
);
4969 if (mono_error_set_pending_exception (&error
))
4973 if (count
> 0 && !create_culture
) {
4974 MonoMethodDesc
*desc
= mono_method_desc_new (
4975 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4976 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4977 g_assert (create_culture
);
4978 mono_method_desc_free (desc
);
4981 for (i
= 0; i
< count
; i
++) {
4982 MonoObject
*version
;
4983 MonoReflectionAssemblyName
*aname
;
4984 guint32 cols
[MONO_ASSEMBLYREF_SIZE
];
4986 mono_metadata_decode_row (t
, i
, cols
, MONO_ASSEMBLYREF_SIZE
);
4988 aname
= (MonoReflectionAssemblyName
*) mono_object_new_checked (
4989 domain
, mono_class_get_assembly_name_class (), &error
);
4990 if (mono_error_set_pending_exception (&error
))
4993 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_NAME
])));
4995 aname
->major
= cols
[MONO_ASSEMBLYREF_MAJOR_VERSION
];
4996 aname
->minor
= cols
[MONO_ASSEMBLYREF_MINOR_VERSION
];
4997 aname
->build
= cols
[MONO_ASSEMBLYREF_BUILD_NUMBER
];
4998 aname
->revision
= cols
[MONO_ASSEMBLYREF_REV_NUMBER
];
4999 aname
->flags
= cols
[MONO_ASSEMBLYREF_FLAGS
];
5000 aname
->versioncompat
= 1; /* SameMachine (default) */
5001 aname
->hashalg
= ASSEMBLY_HASH_SHA1
; /* SHA1 (default) */
5003 version
= create_version (domain
, aname
->major
, aname
->minor
, aname
->build
, aname
->revision
, &error
);
5004 if (mono_error_set_pending_exception (&error
))
5007 MONO_OBJECT_SETREF (aname
, version
, version
);
5009 if (create_culture
) {
5011 MonoBoolean assembly_ref
= 1;
5012 args
[0] = mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_CULTURE
]));
5013 args
[1] = &assembly_ref
;
5015 o
= mono_runtime_invoke_checked (create_culture
, NULL
, args
, &error
);
5016 if (mono_error_set_pending_exception (&error
))
5019 MONO_OBJECT_SETREF (aname
, cultureInfo
, o
);
5022 if (cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]) {
5023 const gchar
*pkey_ptr
= mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]);
5024 guint32 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
5026 if ((cols
[MONO_ASSEMBLYREF_FLAGS
] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
)) {
5027 /* public key token isn't copied - the class library will
5028 automatically generate it from the public key if required */
5029 MonoArray
*pkey
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, pkey_len
, &error
);
5030 if (mono_error_set_pending_exception (&error
))
5033 MONO_OBJECT_SETREF (aname
, publicKey
, pkey
);
5034 memcpy (mono_array_addr (pkey
, guint8
, 0), pkey_ptr
, pkey_len
);
5036 MonoArray
*keyToken
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, pkey_len
, &error
);
5037 if (mono_error_set_pending_exception (&error
))
5040 MONO_OBJECT_SETREF (aname
, keyToken
, keyToken
);
5041 memcpy (mono_array_addr (keyToken
, guint8
, 0), pkey_ptr
, pkey_len
);
5044 MonoArray
*keyToken
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, 0, &error
);
5045 if (mono_error_set_pending_exception (&error
))
5048 MONO_OBJECT_SETREF (aname
, keyToken
, keyToken
);
5051 /* note: this function doesn't return the codebase on purpose (i.e. it can
5052 be used under partial trust as path information isn't present). */
5054 mono_array_setref (result
, i
, aname
);
5059 /* move this in some file in mono/util/ */
5061 g_concat_dir_and_file (const char *dir
, const char *file
)
5063 g_return_val_if_fail (dir
!= NULL
, NULL
);
5064 g_return_val_if_fail (file
!= NULL
, NULL
);
5067 * If the directory name doesn't have a / on the end, we need
5068 * to add one so we get a proper path to the file
5070 if (dir
[strlen(dir
) - 1] != G_DIR_SEPARATOR
)
5071 return g_strconcat (dir
, G_DIR_SEPARATOR_S
, file
, NULL
);
5073 return g_strconcat (dir
, file
, NULL
);
5077 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, gint32
*size
, MonoReflectionModule
**ref_module
)
5080 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
5082 guint32 cols
[MONO_MANIFEST_SIZE
];
5083 guint32 impl
, file_idx
;
5087 char *n
= mono_string_to_utf8_checked (name
, &error
);
5088 if (mono_error_set_pending_exception (&error
))
5091 for (i
= 0; i
< table
->rows
; ++i
) {
5092 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
5093 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
5094 if (strcmp (val
, n
) == 0)
5098 if (i
== table
->rows
)
5101 impl
= cols
[MONO_MANIFEST_IMPLEMENTATION
];
5104 * this code should only be called after obtaining the
5105 * ResourceInfo and handling the other cases.
5107 g_assert ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
);
5108 file_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
5110 module
= mono_image_load_file_for_image (assembly
->assembly
->image
, file_idx
);
5115 module
= assembly
->assembly
->image
;
5118 MonoReflectionModule
*rm
= mono_module_get_object_checked (mono_domain_get (), module
, &error
);
5119 if (mono_error_set_pending_exception (&error
))
5121 mono_gc_wbarrier_generic_store (ref_module
, (MonoObject
*) rm
);
5123 return (void*)mono_image_get_resource (module
, cols
[MONO_MANIFEST_OFFSET
], (guint32
*)size
);
5126 ICALL_EXPORT gboolean
5127 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoManifestResourceInfo
*info
)
5130 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
5132 guint32 cols
[MONO_MANIFEST_SIZE
];
5133 guint32 file_cols
[MONO_FILE_SIZE
];
5137 n
= mono_string_to_utf8_checked (name
, &error
);
5138 if (mono_error_set_pending_exception (&error
))
5140 for (i
= 0; i
< table
->rows
; ++i
) {
5141 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
5142 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
5143 if (strcmp (val
, n
) == 0)
5147 if (i
== table
->rows
)
5150 if (!cols
[MONO_MANIFEST_IMPLEMENTATION
]) {
5151 info
->location
= RESOURCE_LOCATION_EMBEDDED
| RESOURCE_LOCATION_IN_MANIFEST
;
5154 switch (cols
[MONO_MANIFEST_IMPLEMENTATION
] & MONO_IMPLEMENTATION_MASK
) {
5155 case MONO_IMPLEMENTATION_FILE
:
5156 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
5157 table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
5158 mono_metadata_decode_row (table
, i
- 1, file_cols
, MONO_FILE_SIZE
);
5159 val
= mono_metadata_string_heap (assembly
->assembly
->image
, file_cols
[MONO_FILE_NAME
]);
5160 MONO_OBJECT_SETREF (info
, filename
, mono_string_new (mono_object_domain (assembly
), val
));
5161 if (file_cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
5164 info
->location
= RESOURCE_LOCATION_EMBEDDED
;
5167 case MONO_IMPLEMENTATION_ASSEMBLYREF
:
5168 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
5169 mono_assembly_load_reference (assembly
->assembly
->image
, i
- 1);
5170 if (assembly
->assembly
->image
->references
[i
- 1] == (gpointer
)-1) {
5171 char *msg
= g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i
- 1, assembly
->assembly
->image
->name
);
5172 MonoException
*ex
= mono_get_exception_file_not_found2 (msg
, NULL
);
5174 mono_set_pending_exception (ex
);
5177 MonoReflectionAssembly
*assm_obj
;
5178 assm_obj
= mono_assembly_get_object_checked (mono_domain_get (), assembly
->assembly
->image
->references
[i
- 1], &error
);
5180 mono_error_set_pending_exception (&error
);
5183 MONO_OBJECT_SETREF (info
, assembly
, assm_obj
);
5185 /* Obtain info recursively */
5186 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info
->assembly
, name
, info
);
5187 info
->location
|= RESOURCE_LOCATION_ANOTHER_ASSEMBLY
;
5190 case MONO_IMPLEMENTATION_EXP_TYPE
:
5191 g_assert_not_reached ();
5199 ICALL_EXPORT MonoObject
*
5200 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoBoolean resource_modules
)
5203 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
5204 MonoArray
*result
= NULL
;
5209 /* check hash if needed */
5211 n
= mono_string_to_utf8_checked (name
, &error
);
5212 if (mono_error_set_pending_exception (&error
))
5215 for (i
= 0; i
< table
->rows
; ++i
) {
5216 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
5217 if (strcmp (val
, n
) == 0) {
5220 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
5221 fn
= mono_string_new (mono_object_domain (assembly
), n
);
5223 return (MonoObject
*)fn
;
5231 for (i
= 0; i
< table
->rows
; ++i
) {
5232 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
))
5236 result
= mono_array_new_checked (mono_object_domain (assembly
), mono_defaults
.string_class
, count
, &error
);
5237 if (mono_error_set_pending_exception (&error
))
5242 for (i
= 0; i
< table
->rows
; ++i
) {
5243 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
5244 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
5245 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
5246 mono_array_setref (result
, count
, mono_string_new (mono_object_domain (assembly
), n
));
5251 return (MonoObject
*)result
;
5254 ICALL_EXPORT MonoArray
*
5255 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly
*assembly
)
5258 MonoDomain
*domain
= mono_domain_get();
5261 int i
, j
, file_count
= 0;
5262 MonoImage
**modules
;
5263 guint32 module_count
, real_module_count
;
5264 MonoTableInfo
*table
;
5265 guint32 cols
[MONO_FILE_SIZE
];
5266 MonoImage
*image
= assembly
->assembly
->image
;
5268 g_assert (image
!= NULL
);
5269 g_assert (!assembly_is_dynamic (assembly
->assembly
));
5271 table
= &image
->tables
[MONO_TABLE_FILE
];
5272 file_count
= table
->rows
;
5274 modules
= image
->modules
;
5275 module_count
= image
->module_count
;
5277 real_module_count
= 0;
5278 for (i
= 0; i
< module_count
; ++i
)
5280 real_module_count
++;
5282 klass
= mono_class_get_module_class ();
5283 res
= mono_array_new_checked (domain
, klass
, 1 + real_module_count
+ file_count
, &error
);
5284 if (mono_error_set_pending_exception (&error
))
5287 MonoReflectionModule
*image_obj
= mono_module_get_object_checked (domain
, image
, &error
);
5288 if (mono_error_set_pending_exception (&error
))
5291 mono_array_setref (res
, 0, image_obj
);
5293 for (i
= 0; i
< module_count
; ++i
)
5295 MonoReflectionModule
*rm
= mono_module_get_object_checked (domain
, modules
[i
], &error
);
5296 if (mono_error_set_pending_exception (&error
))
5298 mono_array_setref (res
, j
, rm
);
5302 for (i
= 0; i
< file_count
; ++i
, ++j
) {
5303 mono_metadata_decode_row (table
, i
, cols
, MONO_FILE_SIZE
);
5304 if (cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
) {
5305 MonoReflectionModule
*rm
= mono_module_file_get_object_checked (domain
, image
, i
, &error
);
5306 if (mono_error_set_pending_exception (&error
))
5308 mono_array_setref (res
, j
, rm
);
5311 MonoImage
*m
= mono_image_load_file_for_image (image
, i
+ 1);
5313 MonoString
*fname
= mono_string_new (mono_domain_get (), mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]));
5314 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL
, fname
));
5317 MonoReflectionModule
*rm
= mono_module_get_object_checked (domain
, m
, &error
);
5318 if (mono_error_set_pending_exception (&error
))
5320 mono_array_setref (res
, j
, rm
);
5327 ICALL_EXPORT MonoReflectionMethod
*
5328 ves_icall_GetCurrentMethod (void)
5330 MonoReflectionMethod
*res
= NULL
;
5333 MonoMethod
*m
= mono_method_get_last_managed ();
5336 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5340 while (m
->is_inflated
)
5341 m
= ((MonoMethodInflated
*)m
)->declaring
;
5343 res
= mono_method_get_object_checked (mono_domain_get (), m
, NULL
, &error
);
5344 mono_error_set_pending_exception (&error
);
5350 mono_method_get_equivalent_method (MonoMethod
*method
, MonoClass
*klass
)
5353 if (method
->is_inflated
&& ((MonoMethodInflated
*)method
)->context
.method_inst
) {
5356 MonoMethodInflated
*inflated
= (MonoMethodInflated
*)method
;
5357 //method is inflated, we should inflate it on the other class
5358 MonoGenericContext ctx
;
5359 ctx
.method_inst
= inflated
->context
.method_inst
;
5360 ctx
.class_inst
= inflated
->context
.class_inst
;
5361 if (klass
->generic_class
)
5362 ctx
.class_inst
= klass
->generic_class
->context
.class_inst
;
5363 else if (klass
->generic_container
)
5364 ctx
.class_inst
= klass
->generic_container
->context
.class_inst
;
5365 result
= mono_class_inflate_generic_method_full_checked (inflated
->declaring
, klass
, &ctx
, &error
);
5366 g_assert (mono_error_ok (&error
)); /* FIXME don't swallow the error */
5370 mono_class_setup_methods (method
->klass
);
5371 if (mono_class_has_failure (method
->klass
))
5373 for (i
= 0; i
< method
->klass
->method
.count
; ++i
) {
5374 if (method
->klass
->methods
[i
] == method
) {
5379 mono_class_setup_methods (klass
);
5380 if (mono_class_has_failure (klass
))
5382 g_assert (offset
>= 0 && offset
< klass
->method
.count
);
5383 return klass
->methods
[offset
];
5386 ICALL_EXPORT MonoReflectionMethod
*
5387 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod
*method
, MonoType
*type
)
5389 MonoReflectionMethod
*res
= NULL
;
5393 klass
= mono_class_from_mono_type (type
);
5394 if (mono_class_get_generic_type_definition (method
->klass
) != mono_class_get_generic_type_definition (klass
))
5396 if (method
->klass
!= klass
) {
5397 method
= mono_method_get_equivalent_method (method
, klass
);
5402 klass
= method
->klass
;
5403 res
= mono_method_get_object_checked (mono_domain_get (), method
, klass
, &error
);
5404 mono_error_set_pending_exception (&error
);
5408 ICALL_EXPORT MonoReflectionMethodBody
*
5409 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod
*method
)
5412 MonoReflectionMethodBody
*result
= mono_method_body_get_object_checked (mono_domain_get (), method
, &error
);
5413 mono_error_set_pending_exception (&error
);
5417 ICALL_EXPORT MonoReflectionAssembly
*
5418 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5421 MonoReflectionAssembly
*result
;
5422 MonoMethod
*dest
= NULL
;
5424 mono_stack_walk_no_il (get_executing
, &dest
);
5426 result
= mono_assembly_get_object_checked (mono_domain_get (), dest
->klass
->image
->assembly
, &error
);
5428 mono_error_set_pending_exception (&error
);
5433 ICALL_EXPORT MonoReflectionAssembly
*
5434 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5437 MonoReflectionAssembly
*result
;
5438 MonoDomain
* domain
= mono_domain_get ();
5440 if (!domain
->entry_assembly
)
5443 result
= mono_assembly_get_object_checked (domain
, domain
->entry_assembly
, &error
);
5445 mono_error_set_pending_exception (&error
);
5449 ICALL_EXPORT MonoReflectionAssembly
*
5450 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5455 MonoReflectionAssembly
*result
;
5458 mono_stack_walk_no_il (get_executing
, &dest
);
5460 mono_stack_walk_no_il (get_caller_no_reflection
, &dest
);
5464 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5467 result
= mono_assembly_get_object_checked (mono_domain_get (), dest
->klass
->image
->assembly
, &error
);
5469 mono_error_set_pending_exception (&error
);
5473 ICALL_EXPORT MonoString
*
5474 ves_icall_System_MonoType_getFullName (MonoReflectionType
*object
, gboolean full_name
,
5475 gboolean assembly_qualified
)
5477 MonoDomain
*domain
= mono_object_domain (object
);
5478 MonoTypeNameFormat format
;
5483 format
= assembly_qualified
?
5484 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
:
5485 MONO_TYPE_NAME_FORMAT_FULL_NAME
;
5487 format
= MONO_TYPE_NAME_FORMAT_REFLECTION
;
5489 name
= mono_type_get_name_full (object
->type
, format
);
5493 if (full_name
&& (object
->type
->type
== MONO_TYPE_VAR
|| object
->type
->type
== MONO_TYPE_MVAR
)) {
5498 res
= mono_string_new (domain
, name
);
5505 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType
*rfield
)
5508 MonoClass
*klass
= mono_class_from_mono_type (rfield
->type
);
5510 mono_class_init_checked (klass
, &error
);
5511 mono_error_set_pending_exception (&error
);
5512 return mono_security_core_clr_class_level (klass
);
5516 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField
*rfield
)
5518 MonoClassField
*field
= rfield
->field
;
5519 return mono_security_core_clr_field_level (field
, TRUE
);
5523 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod
*rfield
)
5525 MonoMethod
*method
= rfield
->method
;
5526 return mono_security_core_clr_method_level (method
, TRUE
);
5530 fill_reflection_assembly_name (MonoDomain
*domain
, MonoReflectionAssemblyName
*aname
, MonoAssemblyName
*name
, const char *absolute
, gboolean by_default_version
, gboolean default_publickey
, gboolean default_token
, MonoError
*error
)
5532 static MonoMethod
*create_culture
= NULL
;
5536 const char *pkey_ptr
;
5538 MonoBoolean assembly_ref
= 0;
5540 mono_error_init (error
);
5542 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, name
->name
));
5543 aname
->major
= name
->major
;
5544 aname
->minor
= name
->minor
;
5545 aname
->build
= name
->build
;
5546 aname
->flags
= name
->flags
;
5547 aname
->revision
= name
->revision
;
5548 aname
->hashalg
= name
->hash_alg
;
5549 aname
->versioncompat
= 1; /* SameMachine (default) */
5550 aname
->processor_architecture
= name
->arch
;
5552 if (by_default_version
) {
5553 MonoObject
*version
;
5555 version
= create_version (domain
, name
->major
, name
->minor
, name
->build
, name
->revision
, error
);
5556 return_if_nok (error
);
5558 MONO_OBJECT_SETREF (aname
, version
, version
);
5562 if (absolute
!= NULL
&& *absolute
!= '\0') {
5563 const gchar
*prepend
= "file://";
5566 codebase
= g_strdup (absolute
);
5571 for (i
= strlen (codebase
) - 1; i
>= 0; i
--)
5572 if (codebase
[i
] == '\\')
5575 if (*codebase
== '/' && *(codebase
+ 1) == '/') {
5578 prepend
= "file:///";
5582 result
= g_strconcat (prepend
, codebase
, NULL
);
5588 MONO_OBJECT_SETREF (aname
, codebase
, mono_string_new (domain
, codebase
));
5592 if (!create_culture
) {
5593 MonoMethodDesc
*desc
= mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
5594 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
5595 g_assert (create_culture
);
5596 mono_method_desc_free (desc
);
5599 if (name
->culture
) {
5600 args
[0] = mono_string_new (domain
, name
->culture
);
5601 args
[1] = &assembly_ref
;
5603 obj
= mono_runtime_invoke_checked (create_culture
, NULL
, args
, error
);
5604 return_if_nok (error
);
5606 MONO_OBJECT_SETREF (aname
, cultureInfo
, obj
);
5609 if (name
->public_key
) {
5610 pkey_ptr
= (char*)name
->public_key
;
5611 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
5613 MonoArray
*pkey
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, pkey_len
, error
);
5614 return_if_nok (error
);
5615 MONO_OBJECT_SETREF (aname
, publicKey
, pkey
);
5616 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
5617 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
5618 } else if (default_publickey
) {
5619 MonoArray
*pkey
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, 0, error
);
5620 return_if_nok (error
);
5621 MONO_OBJECT_SETREF (aname
, publicKey
, pkey
);
5622 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
5625 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5626 if (name
->public_key_token
[0]) {
5630 MonoArray
*keyToken
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, 8, error
);
5631 return_if_nok (error
);
5633 MONO_OBJECT_SETREF (aname
, keyToken
, keyToken
);
5634 p
= mono_array_addr (keyToken
, char, 0);
5636 for (i
= 0, j
= 0; i
< 8; i
++) {
5637 *p
= g_ascii_xdigit_value (name
->public_key_token
[j
++]) << 4;
5638 *p
|= g_ascii_xdigit_value (name
->public_key_token
[j
++]);
5641 } else if (default_token
) {
5642 MonoArray
*keyToken
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, 0, error
);
5643 return_if_nok (error
);
5644 MONO_OBJECT_SETREF (aname
, keyToken
, keyToken
);
5648 ICALL_EXPORT MonoString
*
5649 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly
*assembly
)
5651 MonoDomain
*domain
= mono_object_domain (assembly
);
5652 MonoAssembly
*mass
= assembly
->assembly
;
5656 name
= mono_stringify_assembly_name (&mass
->aname
);
5657 res
= mono_string_new (domain
, name
);
5664 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly
*assembly
, MonoReflectionAssemblyName
*aname
)
5667 gchar
*absolute
, *dirname
;
5668 MonoAssembly
*mass
= assembly
->assembly
;
5670 /* XXX this is duplicated code to compute the codebase URI, unify it */
5671 if (g_path_is_absolute (mass
->image
->name
)) {
5672 absolute
= g_strdup (mass
->image
->name
);
5673 dirname
= g_path_get_dirname (absolute
);
5675 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
5676 dirname
= g_strdup (mass
->basedir
);
5679 replace_shadow_path (mono_object_domain (assembly
), dirname
, &absolute
);
5682 fill_reflection_assembly_name (mono_object_domain (assembly
), aname
, &mass
->aname
, absolute
, TRUE
, TRUE
, TRUE
, &error
);
5683 mono_error_set_pending_exception (&error
);
5689 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString
*fname
, MonoReflectionAssemblyName
*aname
)
5693 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
5696 MonoAssemblyName name
;
5699 filename
= mono_string_to_utf8_checked (fname
, &error
);
5700 if (mono_error_set_pending_exception (&error
))
5703 dirname
= g_path_get_dirname (filename
);
5704 replace_shadow_path (mono_domain_get (), dirname
, &filename
);
5707 image
= mono_image_open (filename
, &status
);
5713 if (status
== MONO_IMAGE_IMAGE_INVALID
)
5714 exc
= mono_get_exception_bad_image_format2 (NULL
, fname
);
5716 exc
= mono_get_exception_file_not_found2 (NULL
, fname
);
5717 mono_set_pending_exception (exc
);
5721 res
= mono_assembly_fill_assembly_name (image
, &name
);
5723 mono_image_close (image
);
5725 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5729 fill_reflection_assembly_name (mono_domain_get (), aname
, &name
, filename
, TRUE
, FALSE
, TRUE
, &error
);
5730 mono_error_set_pending_exception (&error
);
5732 mono_image_close (image
);
5736 ICALL_EXPORT MonoBoolean
5737 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly
*assembly
,
5738 char **minimum
, guint32
*minLength
, char **optional
, guint32
*optLength
, char **refused
, guint32
*refLength
)
5740 MonoBoolean result
= FALSE
;
5741 MonoDeclSecurityEntry entry
;
5743 /* SecurityAction.RequestMinimum */
5744 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQMIN
, &entry
)) {
5745 *minimum
= entry
.blob
;
5746 *minLength
= entry
.size
;
5749 /* SecurityAction.RequestOptional */
5750 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQOPT
, &entry
)) {
5751 *optional
= entry
.blob
;
5752 *optLength
= entry
.size
;
5755 /* SecurityAction.RequestRefuse */
5756 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQREFUSE
, &entry
)) {
5757 *refused
= entry
.blob
;
5758 *refLength
= entry
.size
;
5766 mono_module_type_is_visible (MonoTableInfo
*tdef
, MonoImage
*image
, int type
)
5768 guint32 attrs
, visibility
;
5770 attrs
= mono_metadata_decode_row_col (tdef
, type
- 1, MONO_TYPEDEF_FLAGS
);
5771 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5772 if (visibility
!= TYPE_ATTRIBUTE_PUBLIC
&& visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
)
5775 } while ((type
= mono_metadata_token_index (mono_metadata_nested_in_typedef (image
, type
))));
5781 mono_module_get_types (MonoDomain
*domain
, MonoImage
*image
, MonoArray
**exceptions
, MonoBoolean exportedOnly
, MonoError
*error
)
5783 MonoReflectionType
*rt
;
5786 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_TYPEDEF
];
5789 mono_error_init (error
);
5791 /* we start the count from 1 because we skip the special type <Module> */
5794 for (i
= 1; i
< tdef
->rows
; ++i
) {
5795 if (mono_module_type_is_visible (tdef
, image
, i
+ 1))
5799 count
= tdef
->rows
- 1;
5801 res
= mono_array_new_checked (domain
, mono_defaults
.runtimetype_class
, count
, error
);
5802 return_val_if_nok (error
, NULL
);
5803 *exceptions
= mono_array_new_checked (domain
, mono_defaults
.exception_class
, count
, error
);
5804 return_val_if_nok (error
, NULL
);
5806 for (i
= 1; i
< tdef
->rows
; ++i
) {
5807 if (!exportedOnly
|| mono_module_type_is_visible (tdef
, image
, i
+ 1)) {
5808 klass
= mono_class_get_checked (image
, (i
+ 1) | MONO_TOKEN_TYPE_DEF
, error
);
5811 rt
= mono_type_get_object_checked (domain
, &klass
->byval_arg
, error
);
5812 return_val_if_nok (error
, NULL
);
5814 mono_array_setref (res
, count
, rt
);
5816 MonoException
*ex
= mono_error_convert_to_exception (error
);
5817 mono_array_setref (*exceptions
, count
, ex
);
5826 ICALL_EXPORT MonoArray
*
5827 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly
*assembly
, MonoBoolean exportedOnly
)
5830 MonoArray
*res
= NULL
;
5831 MonoArray
*exceptions
= NULL
;
5832 MonoImage
*image
= NULL
;
5833 MonoTableInfo
*table
= NULL
;
5836 int i
, len
, ex_count
;
5838 domain
= mono_object_domain (assembly
);
5840 g_assert (!assembly_is_dynamic (assembly
->assembly
));
5841 image
= assembly
->assembly
->image
;
5842 table
= &image
->tables
[MONO_TABLE_FILE
];
5843 res
= mono_module_get_types (domain
, image
, &exceptions
, exportedOnly
, &error
);
5844 if (mono_error_set_pending_exception (&error
))
5847 /* Append data from all modules in the assembly */
5848 for (i
= 0; i
< table
->rows
; ++i
) {
5849 if (!(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
5850 MonoImage
*loaded_image
= mono_assembly_load_module (image
->assembly
, i
+ 1);
5855 res2
= mono_module_get_types (domain
, loaded_image
, &ex2
, exportedOnly
, &error
);
5856 if (mono_error_set_pending_exception (&error
))
5860 /* Append the new types to the end of the array */
5861 if (mono_array_length (res2
) > 0) {
5863 MonoArray
*res3
, *ex3
;
5865 len1
= mono_array_length (res
);
5866 len2
= mono_array_length (res2
);
5868 res3
= mono_array_new_checked (domain
, mono_defaults
.runtimetype_class
, len1
+ len2
, &error
);
5869 if (mono_error_set_pending_exception (&error
))
5871 mono_array_memcpy_refs (res3
, 0, res
, 0, len1
);
5872 mono_array_memcpy_refs (res3
, len1
, res2
, 0, len2
);
5875 ex3
= mono_array_new_checked (domain
, mono_defaults
.runtimetype_class
, len1
+ len2
, &error
);
5876 if (mono_error_set_pending_exception (&error
))
5878 mono_array_memcpy_refs (ex3
, 0, exceptions
, 0, len1
);
5879 mono_array_memcpy_refs (ex3
, len1
, ex2
, 0, len2
);
5886 /* the ReflectionTypeLoadException must have all the types (Types property),
5887 * NULL replacing types which throws an exception. The LoaderException must
5888 * contain all exceptions for NULL items.
5891 len
= mono_array_length (res
);
5894 for (i
= 0; i
< len
; i
++) {
5895 MonoReflectionType
*t
= (MonoReflectionType
*)mono_array_get (res
, gpointer
, i
);
5899 klass
= mono_type_get_class (t
->type
);
5900 if ((klass
!= NULL
) && mono_class_has_failure (klass
)) {
5901 /* keep the class in the list */
5902 list
= g_list_append (list
, klass
);
5903 /* and replace Type with NULL */
5904 mono_array_setref (res
, i
, NULL
);
5911 if (list
|| ex_count
) {
5913 MonoException
*exc
= NULL
;
5914 MonoArray
*exl
= NULL
;
5915 int j
, length
= g_list_length (list
) + ex_count
;
5917 exl
= mono_array_new_checked (domain
, mono_defaults
.exception_class
, length
, &error
);
5918 if (mono_error_set_pending_exception (&error
)) {
5922 /* Types for which mono_class_get_checked () succeeded */
5923 for (i
= 0, tmp
= list
; tmp
; i
++, tmp
= tmp
->next
) {
5924 MonoException
*exc
= mono_class_get_exception_for_failure ((MonoClass
*)tmp
->data
);
5925 mono_array_setref (exl
, i
, exc
);
5927 /* Types for which it don't */
5928 for (j
= 0; j
< mono_array_length (exceptions
); ++j
) {
5929 MonoException
*exc
= mono_array_get (exceptions
, MonoException
*, j
);
5931 g_assert (i
< length
);
5932 mono_array_setref (exl
, i
, exc
);
5939 exc
= mono_get_exception_reflection_type_load_checked (res
, exl
, &error
);
5940 if (!is_ok (&error
)) {
5941 mono_error_set_pending_exception (&error
);
5944 mono_set_pending_exception (exc
);
5951 ICALL_EXPORT gboolean
5952 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName
*name
, MonoString
*assname
)
5955 MonoAssemblyName aname
;
5956 MonoDomain
*domain
= mono_object_domain (name
);
5958 gboolean is_version_defined
;
5959 gboolean is_token_defined
;
5961 aname
.public_key
= NULL
;
5962 val
= mono_string_to_utf8_checked (assname
, &error
);
5963 if (mono_error_set_pending_exception (&error
))
5966 if (!mono_assembly_name_parse_full (val
, &aname
, TRUE
, &is_version_defined
, &is_token_defined
)) {
5967 g_free ((guint8
*) aname
.public_key
);
5972 fill_reflection_assembly_name (domain
, name
, &aname
, "", is_version_defined
, FALSE
, is_token_defined
, &error
);
5973 mono_error_set_pending_exception (&error
);
5975 mono_assembly_name_free (&aname
);
5976 g_free ((guint8
*) aname
.public_key
);
5982 ICALL_EXPORT MonoReflectionType
*
5983 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule
*module
)
5986 MonoReflectionType
*ret
;
5987 MonoDomain
*domain
= mono_object_domain (module
);
5990 g_assert (module
->image
);
5992 if (image_is_dynamic (module
->image
) && ((MonoDynamicImage
*)(module
->image
))->initial_image
)
5993 /* These images do not have a global type */
5996 klass
= mono_class_get_checked (module
->image
, 1 | MONO_TOKEN_TYPE_DEF
, &error
);
5997 if (!mono_error_ok (&error
)) {
5998 mono_error_set_pending_exception (&error
);
6002 ret
= mono_type_get_object_checked (domain
, &klass
->byval_arg
, &error
);
6003 if (!mono_error_ok (&error
)) {
6004 mono_error_set_pending_exception (&error
);
6012 ves_icall_System_Reflection_Module_Close (MonoReflectionModule
*module
)
6014 /*if (module->image)
6015 mono_image_close (module->image);*/
6018 ICALL_EXPORT MonoString
*
6019 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule
*module
)
6021 MonoDomain
*domain
= mono_object_domain (module
);
6023 g_assert (module
->image
);
6024 return mono_string_new (domain
, module
->image
->guid
);
6027 ICALL_EXPORT gpointer
6028 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule
*module
)
6031 if (module
->image
&& module
->image
->is_module_handle
)
6032 return module
->image
->raw_data
;
6035 return (gpointer
) (-1);
6039 ves_icall_System_Reflection_Module_GetPEKind (MonoImage
*image
, gint32
*pe_kind
, gint32
*machine
)
6041 if (image_is_dynamic (image
)) {
6042 MonoDynamicImage
*dyn
= (MonoDynamicImage
*)image
;
6043 *pe_kind
= dyn
->pe_kind
;
6044 *machine
= dyn
->machine
;
6047 *pe_kind
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_cli_header
.ch_flags
& 0x3;
6048 *machine
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_header
.coff
.coff_machine
;
6053 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage
*image
)
6055 return (image
->md_version_major
<< 16) | (image
->md_version_minor
);
6058 ICALL_EXPORT MonoArray
*
6059 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule
*module
)
6062 MonoArray
*exceptions
;
6065 if (!module
->image
) {
6066 MonoArray
*arr
= mono_array_new_checked (mono_object_domain (module
), mono_defaults
.runtimetype_class
, 0, &error
);
6067 mono_error_set_pending_exception (&error
);
6072 res
= mono_module_get_types (mono_object_domain (module
), module
->image
, &exceptions
, FALSE
, &error
);
6073 if (mono_error_set_pending_exception (&error
))
6076 for (i
= 0; i
< mono_array_length (exceptions
); ++i
) {
6077 MonoException
*ex
= mono_array_get (exceptions
, MonoException
*, i
);
6079 mono_set_pending_exception (ex
);
6088 mono_memberref_is_method (MonoImage
*image
, guint32 token
)
6090 if (!image_is_dynamic (image
)) {
6091 guint32 cols
[MONO_MEMBERREF_SIZE
];
6093 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
6094 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
6095 mono_metadata_decode_blob_size (sig
, &sig
);
6096 return (*sig
!= 0x6);
6099 MonoClass
*handle_class
;
6101 if (!mono_lookup_dynamic_token_class (image
, token
, FALSE
, &handle_class
, NULL
, &error
)) {
6102 mono_error_cleanup (&error
); /* just probing, ignore error */
6106 return mono_defaults
.methodhandle_class
== handle_class
;
6111 init_generic_context_from_args (MonoGenericContext
*context
, MonoArray
*type_args
, MonoArray
*method_args
)
6114 context
->class_inst
= mono_metadata_get_generic_inst (mono_array_length (type_args
),
6115 mono_array_addr (type_args
, MonoType
*, 0));
6117 context
->class_inst
= NULL
;
6119 context
->method_inst
= mono_metadata_get_generic_inst (mono_array_length (method_args
),
6120 mono_array_addr (method_args
, MonoType
*, 0));
6122 context
->method_inst
= NULL
;
6125 ICALL_EXPORT MonoType
*
6126 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*resolve_error
)
6129 int table
= mono_metadata_token_table (token
);
6130 int index
= mono_metadata_token_index (token
);
6131 MonoGenericContext context
;
6134 *resolve_error
= ResolveTokenError_Other
;
6136 /* Validate token */
6137 if ((table
!= MONO_TABLE_TYPEDEF
) && (table
!= MONO_TABLE_TYPEREF
) &&
6138 (table
!= MONO_TABLE_TYPESPEC
)) {
6139 *resolve_error
= ResolveTokenError_BadTable
;
6143 if (image_is_dynamic (image
)) {
6144 if ((table
== MONO_TABLE_TYPEDEF
) || (table
== MONO_TABLE_TYPEREF
)) {
6145 klass
= (MonoClass
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
, &error
);
6146 mono_error_cleanup (&error
);
6147 return klass
? &klass
->byval_arg
: NULL
;
6150 init_generic_context_from_args (&context
, type_args
, method_args
);
6151 klass
= (MonoClass
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
, &error
);
6152 mono_error_cleanup (&error
);
6153 return klass
? &klass
->byval_arg
: NULL
;
6156 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
6157 *resolve_error
= ResolveTokenError_OutOfRange
;
6161 init_generic_context_from_args (&context
, type_args
, method_args
);
6162 klass
= mono_class_get_checked (image
, token
, &error
);
6164 klass
= mono_class_inflate_generic_class_checked (klass
, &context
, &error
);
6165 if (!mono_error_ok (&error
)) {
6166 mono_error_set_pending_exception (&error
);
6171 return &klass
->byval_arg
;
6176 ICALL_EXPORT MonoMethod
*
6177 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*resolve_error
)
6180 int table
= mono_metadata_token_table (token
);
6181 int index
= mono_metadata_token_index (token
);
6182 MonoGenericContext context
;
6185 *resolve_error
= ResolveTokenError_Other
;
6187 /* Validate token */
6188 if ((table
!= MONO_TABLE_METHOD
) && (table
!= MONO_TABLE_METHODSPEC
) &&
6189 (table
!= MONO_TABLE_MEMBERREF
)) {
6190 *resolve_error
= ResolveTokenError_BadTable
;
6194 if (image_is_dynamic (image
)) {
6195 if (table
== MONO_TABLE_METHOD
) {
6196 method
= (MonoMethod
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
, &error
);
6197 mono_error_cleanup (&error
);
6201 if ((table
== MONO_TABLE_MEMBERREF
) && !(mono_memberref_is_method (image
, token
))) {
6202 *resolve_error
= ResolveTokenError_BadTable
;
6206 init_generic_context_from_args (&context
, type_args
, method_args
);
6207 method
= (MonoMethod
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
, &error
);
6208 mono_error_cleanup (&error
);
6212 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
6213 *resolve_error
= ResolveTokenError_OutOfRange
;
6216 if ((table
== MONO_TABLE_MEMBERREF
) && (!mono_memberref_is_method (image
, token
))) {
6217 *resolve_error
= ResolveTokenError_BadTable
;
6221 init_generic_context_from_args (&context
, type_args
, method_args
);
6222 method
= mono_get_method_checked (image
, token
, NULL
, &context
, &error
);
6223 mono_error_set_pending_exception (&error
);
6228 ICALL_EXPORT MonoString
*
6229 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*resolve_error
)
6232 int index
= mono_metadata_token_index (token
);
6234 *resolve_error
= ResolveTokenError_Other
;
6236 /* Validate token */
6237 if (mono_metadata_token_code (token
) != MONO_TOKEN_STRING
) {
6238 *resolve_error
= ResolveTokenError_BadTable
;
6242 if (image_is_dynamic (image
)) {
6243 MonoString
* result
= (MonoString
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
, &error
);
6244 mono_error_cleanup (&error
);
6248 if ((index
<= 0) || (index
>= image
->heap_us
.size
)) {
6249 *resolve_error
= ResolveTokenError_OutOfRange
;
6253 /* FIXME: What to do if the index points into the middle of a string ? */
6255 MonoString
*result
= mono_ldstr_checked (mono_domain_get (), image
, index
, &error
);
6256 mono_error_set_pending_exception (&error
);
6260 ICALL_EXPORT MonoClassField
*
6261 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*resolve_error
)
6265 int table
= mono_metadata_token_table (token
);
6266 int index
= mono_metadata_token_index (token
);
6267 MonoGenericContext context
;
6268 MonoClassField
*field
;
6270 *resolve_error
= ResolveTokenError_Other
;
6272 /* Validate token */
6273 if ((table
!= MONO_TABLE_FIELD
) && (table
!= MONO_TABLE_MEMBERREF
)) {
6274 *resolve_error
= ResolveTokenError_BadTable
;
6278 if (image_is_dynamic (image
)) {
6279 if (table
== MONO_TABLE_FIELD
) {
6280 field
= (MonoClassField
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
, &error
);
6281 mono_error_cleanup (&error
);
6285 if (mono_memberref_is_method (image
, token
)) {
6286 *resolve_error
= ResolveTokenError_BadTable
;
6290 init_generic_context_from_args (&context
, type_args
, method_args
);
6291 field
= (MonoClassField
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
, &error
);
6292 mono_error_cleanup (&error
);
6296 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
6297 *resolve_error
= ResolveTokenError_OutOfRange
;
6300 if ((table
== MONO_TABLE_MEMBERREF
) && (mono_memberref_is_method (image
, token
))) {
6301 *resolve_error
= ResolveTokenError_BadTable
;
6305 init_generic_context_from_args (&context
, type_args
, method_args
);
6306 field
= mono_field_from_token_checked (image
, token
, &klass
, &context
, &error
);
6307 mono_error_set_pending_exception (&error
);
6313 ICALL_EXPORT MonoObject
*
6314 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
6318 int table
= mono_metadata_token_table (token
);
6320 *error
= ResolveTokenError_Other
;
6323 case MONO_TABLE_TYPEDEF
:
6324 case MONO_TABLE_TYPEREF
:
6325 case MONO_TABLE_TYPESPEC
: {
6326 MonoType
*t
= ves_icall_System_Reflection_Module_ResolveTypeToken (image
, token
, type_args
, method_args
, error
);
6328 ret
= (MonoObject
*) mono_type_get_object_checked (mono_domain_get (), t
, &merror
);
6329 mono_error_set_pending_exception (&merror
);
6336 case MONO_TABLE_METHOD
:
6337 case MONO_TABLE_METHODSPEC
: {
6338 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
6340 ret
= (MonoObject
*)mono_method_get_object_checked (mono_domain_get (), m
, m
->klass
, &merror
);
6341 mono_error_set_pending_exception (&merror
);
6347 case MONO_TABLE_FIELD
: {
6348 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
6350 ret
=(MonoObject
*)mono_field_get_object_checked (mono_domain_get (), f
->parent
, f
, &merror
);
6351 mono_error_set_pending_exception (&merror
);
6357 case MONO_TABLE_MEMBERREF
:
6358 if (mono_memberref_is_method (image
, token
)) {
6359 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
6361 ret
= (MonoObject
*)mono_method_get_object_checked (mono_domain_get (), m
, m
->klass
, &merror
);
6362 mono_error_set_pending_exception (&merror
);
6369 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
6371 ret
= (MonoObject
*)mono_field_get_object_checked (mono_domain_get (), f
->parent
, f
, &merror
);
6372 mono_error_set_pending_exception (&merror
);
6381 *error
= ResolveTokenError_BadTable
;
6387 ICALL_EXPORT MonoArray
*
6388 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*resolve_error
)
6391 int table
= mono_metadata_token_table (token
);
6392 int idx
= mono_metadata_token_index (token
);
6393 MonoTableInfo
*tables
= image
->tables
;
6398 *resolve_error
= ResolveTokenError_OutOfRange
;
6400 /* FIXME: Support other tables ? */
6401 if (table
!= MONO_TABLE_STANDALONESIG
)
6404 if (image_is_dynamic (image
))
6407 if ((idx
== 0) || (idx
> tables
[MONO_TABLE_STANDALONESIG
].rows
))
6410 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
6412 ptr
= mono_metadata_blob_heap (image
, sig
);
6413 len
= mono_metadata_decode_blob_size (ptr
, &ptr
);
6415 res
= mono_array_new_checked (mono_domain_get (), mono_defaults
.byte_class
, len
, &error
);
6416 if (mono_error_set_pending_exception (&error
))
6418 memcpy (mono_array_addr (res
, guint8
, 0), ptr
, len
);
6422 ICALL_EXPORT MonoReflectionType
*
6423 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder
*tb
, MonoString
*smodifiers
)
6426 MonoReflectionType
*ret
;
6428 int isbyref
= 0, rank
;
6430 char *str
= mono_string_to_utf8_checked (smodifiers
, &error
);
6431 if (mono_error_set_pending_exception (&error
))
6434 klass
= mono_class_from_mono_type (tb
->type
.type
);
6436 /* logic taken from mono_reflection_parse_type(): keep in sync */
6440 if (isbyref
) { /* only one level allowed by the spec */
6449 ret
= mono_type_get_object_checked (mono_object_domain (tb
), &klass
->this_arg
, &error
);
6450 mono_error_set_pending_exception (&error
);
6454 klass
= mono_ptr_class_get (&klass
->byval_arg
);
6455 mono_class_init (klass
);
6466 else if (*p
!= '*') { /* '*' means unknown lower bound */
6477 klass
= mono_array_class_get (klass
, rank
);
6478 mono_class_init (klass
);
6487 ret
= mono_type_get_object_checked (mono_object_domain (tb
), &klass
->byval_arg
, &error
);
6488 mono_error_set_pending_exception (&error
);
6493 ICALL_EXPORT MonoBoolean
6494 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType
*t
)
6500 res
= !type
->byref
&& (type
->type
== MONO_TYPE_ARRAY
|| type
->type
== MONO_TYPE_SZARRAY
);
6506 check_for_invalid_type (MonoClass
*klass
, MonoError
*error
)
6511 mono_error_init (error
);
6513 if (klass
->byval_arg
.type
!= MONO_TYPE_TYPEDBYREF
)
6516 name
= mono_type_get_full_name (klass
);
6517 str
= mono_string_new (mono_domain_get (), name
);
6519 mono_error_set_exception_instance (error
, mono_get_exception_type_load (str
, NULL
));
6522 ICALL_EXPORT MonoReflectionType
*
6523 ves_icall_RuntimeType_make_array_type (MonoReflectionType
*type
, int rank
)
6526 MonoReflectionType
*ret
;
6527 MonoClass
*klass
, *aklass
;
6529 klass
= mono_class_from_mono_type (type
->type
);
6530 check_for_invalid_type (klass
, &error
);
6531 mono_error_set_pending_exception (&error
);
6533 if (rank
== 0) //single dimentional array
6534 aklass
= mono_array_class_get (klass
, 1);
6536 aklass
= mono_bounded_array_class_get (klass
, rank
, TRUE
);
6538 ret
= mono_type_get_object_checked (mono_object_domain (type
), &aklass
->byval_arg
, &error
);
6539 mono_error_set_pending_exception (&error
);
6544 ICALL_EXPORT MonoReflectionType
*
6545 ves_icall_RuntimeType_make_byref_type (MonoReflectionType
*type
)
6548 MonoReflectionType
*ret
;
6551 klass
= mono_class_from_mono_type (type
->type
);
6552 mono_class_init_checked (klass
, &error
);
6553 if (mono_error_set_pending_exception (&error
))
6556 check_for_invalid_type (klass
, &error
);
6557 if (mono_error_set_pending_exception (&error
))
6560 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->this_arg
, &error
);
6561 mono_error_set_pending_exception (&error
);
6566 ICALL_EXPORT MonoReflectionType
*
6567 ves_icall_RuntimeType_MakePointerType (MonoReflectionType
*type
)
6570 MonoReflectionType
*ret
;
6571 MonoClass
*klass
, *pklass
;
6573 klass
= mono_class_from_mono_type (type
->type
);
6574 mono_class_init_checked (klass
, &error
);
6575 if (mono_error_set_pending_exception (&error
))
6577 check_for_invalid_type (klass
, &error
);
6578 if (mono_error_set_pending_exception (&error
))
6581 pklass
= mono_ptr_class_get (type
->type
);
6583 ret
= mono_type_get_object_checked (mono_object_domain (type
), &pklass
->byval_arg
, &error
);
6584 mono_error_set_pending_exception (&error
);
6589 ICALL_EXPORT MonoObject
*
6590 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType
*type
, MonoObject
*target
,
6591 MonoReflectionMethod
*info
, MonoBoolean throwOnBindFailure
)
6594 MonoClass
*delegate_class
= mono_class_from_mono_type (type
->type
);
6595 MonoObject
*delegate
;
6597 MonoMethod
*method
= info
->method
;
6599 mono_class_init_checked (delegate_class
, &error
);
6600 if (mono_error_set_pending_exception (&error
))
6603 if (!(delegate_class
->parent
== mono_defaults
.multicastdelegate_class
)) {
6604 /* FIXME improve this exception message */
6605 mono_error_set_execution_engine (&error
, "file %s: line %d (%s): assertion failed: (%s)", __FILE__
, __LINE__
,
6607 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6608 mono_error_set_pending_exception (&error
);
6612 if (mono_security_core_clr_enabled ()) {
6613 if (!mono_security_core_clr_ensure_delegate_creation (method
, &error
)) {
6614 if (throwOnBindFailure
)
6615 mono_error_set_pending_exception (&error
);
6617 mono_error_cleanup (&error
);
6622 delegate
= mono_object_new_checked (mono_object_domain (type
), delegate_class
, &error
);
6623 if (mono_error_set_pending_exception (&error
))
6626 if (method_is_dynamic (method
)) {
6627 /* Creating a trampoline would leak memory */
6628 func
= mono_compile_method_checked (method
, &error
);
6629 if (mono_error_set_pending_exception (&error
))
6632 if (target
&& method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
&& method
->klass
!= mono_object_class (target
))
6633 method
= mono_object_get_virtual_method (target
, method
);
6634 gpointer trampoline
= mono_runtime_create_jump_trampoline (mono_domain_get (), method
, TRUE
, &error
);
6635 if (mono_error_set_pending_exception (&error
))
6637 func
= mono_create_ftnptr (mono_domain_get (), trampoline
);
6640 mono_delegate_ctor_with_method (delegate
, target
, func
, method
, &error
);
6641 if (mono_error_set_pending_exception (&error
))
6646 ICALL_EXPORT MonoMulticastDelegate
*
6647 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate
*delegate
)
6650 MonoMulticastDelegate
*ret
;
6652 g_assert (mono_class_has_parent (mono_object_class (delegate
), mono_defaults
.multicastdelegate_class
));
6654 ret
= (MonoMulticastDelegate
*) mono_object_new_checked (mono_object_domain (delegate
), mono_object_class (delegate
), &error
);
6655 if (mono_error_set_pending_exception (&error
))
6658 ret
->delegate
.invoke_impl
= mono_runtime_create_delegate_trampoline (mono_object_class (delegate
));
6663 ICALL_EXPORT MonoReflectionMethod
*
6664 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate
*delegate
)
6666 MonoReflectionMethod
*ret
= NULL
;
6668 ret
= mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate
->target
, delegate
->method
), mono_object_class (delegate
->target
), &error
);
6669 mono_error_set_pending_exception (&error
);
6675 static inline gint32
6676 mono_array_get_byte_length (MonoArray
*array
)
6682 klass
= array
->obj
.vtable
->klass
;
6684 if (array
->bounds
== NULL
)
6685 length
= array
->max_length
;
6688 for (i
= 0; i
< klass
->rank
; ++ i
)
6689 length
*= array
->bounds
[i
].length
;
6692 switch (klass
->element_class
->byval_arg
.type
) {
6695 case MONO_TYPE_BOOLEAN
:
6699 case MONO_TYPE_CHAR
:
6707 return length
* sizeof (gpointer
);
6718 ves_icall_System_Buffer_ByteLengthInternal (MonoArray
*array
)
6720 return mono_array_get_byte_length (array
);
6724 ves_icall_System_Buffer_GetByteInternal (MonoArray
*array
, gint32 idx
)
6726 return mono_array_get (array
, gint8
, idx
);
6730 ves_icall_System_Buffer_SetByteInternal (MonoArray
*array
, gint32 idx
, gint8 value
)
6732 mono_array_set (array
, gint8
, idx
, value
);
6735 ICALL_EXPORT MonoBoolean
6736 ves_icall_System_Buffer_BlockCopyInternal (MonoArray
*src
, gint32 src_offset
, MonoArray
*dest
, gint32 dest_offset
, gint32 count
)
6738 guint8
*src_buf
, *dest_buf
;
6741 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6745 g_assert (count
>= 0);
6747 /* This is called directly from the class libraries without going through the managed wrapper */
6748 MONO_CHECK_ARG_NULL (src
, FALSE
);
6749 MONO_CHECK_ARG_NULL (dest
, FALSE
);
6751 /* watch out for integer overflow */
6752 if ((src_offset
> mono_array_get_byte_length (src
) - count
) || (dest_offset
> mono_array_get_byte_length (dest
) - count
))
6755 src_buf
= (guint8
*)src
->vector
+ src_offset
;
6756 dest_buf
= (guint8
*)dest
->vector
+ dest_offset
;
6759 memcpy (dest_buf
, src_buf
, count
);
6761 memmove (dest_buf
, src_buf
, count
); /* Source and dest are the same array */
6766 #ifndef DISABLE_REMOTING
6767 ICALL_EXPORT MonoObject
*
6768 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject
*this_obj
, MonoString
*class_name
)
6771 MonoDomain
*domain
= mono_object_domain (this_obj
);
6773 MonoRealProxy
*rp
= ((MonoRealProxy
*)this_obj
);
6774 MonoTransparentProxy
*tp
;
6778 res
= mono_object_new_checked (domain
, mono_defaults
.transparent_proxy_class
, &error
);
6779 if (mono_error_set_pending_exception (&error
))
6782 tp
= (MonoTransparentProxy
*) res
;
6784 MONO_OBJECT_SETREF (tp
, rp
, rp
);
6785 type
= ((MonoReflectionType
*)rp
->class_to_proxy
)->type
;
6786 klass
= mono_class_from_mono_type (type
);
6788 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6789 mono_class_setup_vtable (klass
);
6790 if (mono_class_has_failure (klass
)) {
6791 mono_set_pending_exception (mono_class_get_exception_for_failure (klass
));
6795 tp
->custom_type_info
= (mono_object_isinst_checked (this_obj
, mono_defaults
.iremotingtypeinfo_class
, &error
) != NULL
);
6796 if (mono_error_set_pending_exception (&error
))
6798 tp
->remote_class
= mono_remote_class (domain
, class_name
, klass
, &error
);
6799 if (mono_error_set_pending_exception (&error
))
6802 res
->vtable
= (MonoVTable
*)mono_remote_class_vtable (domain
, tp
->remote_class
, rp
, &error
);
6803 if (mono_error_set_pending_exception (&error
))
6808 ICALL_EXPORT MonoReflectionType
*
6809 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy
*tp
)
6812 MonoReflectionType
*ret
= mono_type_get_object_checked (mono_object_domain (tp
), &tp
->remote_class
->proxy_class
->byval_arg
, &error
);
6813 mono_error_set_pending_exception (&error
);
6819 /* System.Environment */
6822 ves_icall_System_Environment_get_UserName (void)
6824 /* using glib is more portable */
6825 return mono_string_new (mono_domain_get (), g_get_user_name ());
6829 ICALL_EXPORT MonoString
*
6830 ves_icall_System_Environment_get_MachineName (void)
6832 #if defined (HOST_WIN32)
6837 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
6838 buf
= g_new (gunichar2
, len
);
6841 if (GetComputerName (buf
, (PDWORD
) &len
)) {
6843 result
= mono_string_new_utf16_checked (mono_domain_get (), buf
, len
, &error
);
6844 mono_error_set_pending_exception (&error
);
6849 #elif !defined(DISABLE_SOCKETS)
6853 #if defined _SC_HOST_NAME_MAX
6854 n
= sysconf (_SC_HOST_NAME_MAX
);
6858 buf
= g_malloc (n
+1);
6860 if (gethostname (buf
, n
) == 0){
6862 result
= mono_string_new (mono_domain_get (), buf
);
6869 return mono_string_new (mono_domain_get (), "mono");
6874 ves_icall_System_Environment_get_Platform (void)
6876 #if defined (TARGET_WIN32)
6879 #elif defined(__MACH__)
6882 // Notice that the value is hidden from user code, and only exposed
6883 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6884 // define and making assumptions based on Unix/128/4 values before there
6885 // was a MacOS define. Lots of code would assume that not-Unix meant
6886 // Windows, but in this case, it would be OSX.
6895 ICALL_EXPORT MonoString
*
6896 ves_icall_System_Environment_get_NewLine (void)
6898 #if defined (HOST_WIN32)
6899 return mono_string_new (mono_domain_get (), "\r\n");
6901 return mono_string_new (mono_domain_get (), "\n");
6905 ICALL_EXPORT MonoBoolean
6906 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6908 #if SIZEOF_VOID_P == 8
6912 gboolean isWow64Process
= FALSE
;
6913 if (IsWow64Process (GetCurrentProcess (), &isWow64Process
)) {
6914 return (MonoBoolean
)isWow64Process
;
6916 #elif defined(HAVE_SYS_UTSNAME_H)
6917 struct utsname name
;
6919 if (uname (&name
) >= 0) {
6920 return strcmp (name
.machine
, "x86_64") == 0 || strncmp (name
.machine
, "aarch64", 7) == 0 || strncmp (name
.machine
, "ppc64", 5) == 0;
6927 ICALL_EXPORT MonoString
*
6928 ves_icall_System_Environment_GetEnvironmentVariable (MonoString
*name
)
6937 utf8_name
= mono_string_to_utf8_checked (name
, &error
); /* FIXME: this should be ascii */
6938 if (mono_error_set_pending_exception (&error
))
6940 value
= g_getenv (utf8_name
);
6947 return mono_string_new (mono_domain_get (), value
);
6951 * There is no standard way to get at environ.
6954 #ifndef __MINGW32_VERSION
6955 #if defined(__APPLE__)
6956 #if defined (TARGET_OSX)
6957 /* Apple defines this in crt_externs.h but doesn't provide that header for
6958 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6959 * in fact exist on all implementations (so far)
6961 gchar
***_NSGetEnviron(void);
6962 #define environ (*_NSGetEnviron())
6964 static char *mono_environ
[1] = { NULL
};
6965 #define environ mono_environ
6966 #endif /* defined (TARGET_OSX) */
6974 ICALL_EXPORT MonoArray
*
6975 ves_icall_System_Environment_GetCoomandLineArgs (void)
6978 MonoArray
*result
= mono_runtime_get_main_args_checked (&error
);
6979 mono_error_set_pending_exception (&error
);
6983 ICALL_EXPORT MonoArray
*
6984 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6996 env_strings
= GetEnvironmentStrings();
6999 env_string
= env_strings
;
7000 while (*env_string
!= '\0') {
7001 /* weird case that MS seems to skip */
7002 if (*env_string
!= '=')
7004 while (*env_string
!= '\0')
7010 domain
= mono_domain_get ();
7011 names
= mono_array_new_checked (domain
, mono_defaults
.string_class
, n
, &error
);
7012 if (mono_error_set_pending_exception (&error
))
7017 env_string
= env_strings
;
7018 while (*env_string
!= '\0') {
7019 /* weird case that MS seems to skip */
7020 if (*env_string
!= '=') {
7021 equal_str
= wcschr(env_string
, '=');
7022 g_assert(equal_str
);
7024 str
= mono_string_new_utf16_checked (domain
, env_string
, equal_str
-env_string
, &error
);
7025 if (mono_error_set_pending_exception (&error
))
7028 mono_array_setref (names
, n
, str
);
7031 while (*env_string
!= '\0')
7036 FreeEnvironmentStrings (env_strings
);
7050 for (e
= environ
; *e
!= 0; ++ e
)
7053 domain
= mono_domain_get ();
7054 names
= mono_array_new_checked (domain
, mono_defaults
.string_class
, n
, &error
);
7055 if (mono_error_set_pending_exception (&error
))
7059 for (e
= environ
; *e
!= 0; ++ e
) {
7060 parts
= g_strsplit (*e
, "=", 2);
7062 str
= mono_string_new (domain
, *parts
);
7063 mono_array_setref (names
, n
, str
);
7076 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString
*name
, MonoString
*value
)
7079 gunichar2
*utf16_name
, *utf16_value
;
7081 gchar
*utf8_name
, *utf8_value
;
7086 utf16_name
= mono_string_to_utf16 (name
);
7087 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
7088 SetEnvironmentVariable (utf16_name
, NULL
);
7089 g_free (utf16_name
);
7093 utf16_value
= mono_string_to_utf16 (value
);
7095 SetEnvironmentVariable (utf16_name
, utf16_value
);
7097 g_free (utf16_name
);
7098 g_free (utf16_value
);
7100 utf8_name
= mono_string_to_utf8_checked (name
, &error
); /* FIXME: this should be ascii */
7101 if (mono_error_set_pending_exception (&error
))
7104 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
7105 g_unsetenv (utf8_name
);
7110 utf8_value
= mono_string_to_utf8_checked (value
, &error
);
7111 if (!mono_error_ok (&error
)) {
7113 mono_error_set_pending_exception (&error
);
7116 g_setenv (utf8_name
, utf8_value
, TRUE
);
7119 g_free (utf8_value
);
7124 ves_icall_System_Environment_Exit (int result
)
7126 mono_environment_exitcode_set (result
);
7128 /* FIXME: There are some cleanup hangs that should be worked out, but
7129 * if the program is going to exit, everything will be cleaned up when
7130 * NaCl exits anyway.
7132 #ifndef __native_client__
7133 if (!mono_runtime_try_shutdown ())
7134 mono_thread_exit ();
7136 /* Suspend all managed threads since the runtime is going away */
7137 mono_thread_suspend_all_other_threads ();
7139 mono_runtime_quit ();
7142 /* we may need to do some cleanup here... */
7146 ICALL_EXPORT MonoString
*
7147 ves_icall_System_Environment_GetGacPath (void)
7149 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7152 ICALL_EXPORT MonoString
*
7153 ves_icall_System_Environment_GetWindowsFolderPath (int folder
)
7155 #if defined (HOST_WIN32)
7156 #ifndef CSIDL_FLAG_CREATE
7157 #define CSIDL_FLAG_CREATE 0x8000
7160 WCHAR path
[MAX_PATH
];
7161 /* Create directory if no existing */
7162 if (SUCCEEDED (SHGetFolderPathW (NULL
, folder
| CSIDL_FLAG_CREATE
, NULL
, 0, path
))) {
7167 MonoString
*res
= mono_string_new_utf16_checked (mono_domain_get (), path
, len
, &error
);
7168 mono_error_set_pending_exception (&error
);
7172 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7174 return mono_string_new (mono_domain_get (), "");
7177 ICALL_EXPORT MonoArray
*
7178 ves_icall_System_Environment_GetLogicalDrives (void)
7181 gunichar2 buf
[256], *ptr
, *dname
;
7183 guint initial_size
= 127, size
= 128;
7186 MonoString
*drivestr
;
7187 MonoDomain
*domain
= mono_domain_get ();
7193 while (size
> initial_size
) {
7194 size
= (guint
) GetLogicalDriveStrings (initial_size
, ptr
);
7195 if (size
> initial_size
) {
7198 ptr
= (gunichar2
*)g_malloc0 ((size
+ 1) * sizeof (gunichar2
));
7199 initial_size
= size
;
7213 result
= mono_array_new_checked (domain
, mono_defaults
.string_class
, ndrives
, &error
);
7214 if (mono_error_set_pending_exception (&error
))
7221 while (*u16
) { u16
++; len
++; }
7222 drivestr
= mono_string_new_utf16_checked (domain
, dname
, len
, &error
);
7223 if (mono_error_set_pending_exception (&error
))
7226 mono_array_setref (result
, ndrives
++, drivestr
);
7237 ICALL_EXPORT MonoString
*
7238 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString
*path
)
7241 gunichar2 volume_name
[MAX_PATH
+ 1];
7243 if (GetVolumeInformation (mono_string_chars (path
), NULL
, 0, NULL
, NULL
, NULL
, volume_name
, MAX_PATH
+ 1) == FALSE
)
7245 MonoString
*result
= mono_string_from_utf16_checked (volume_name
, &error
);
7246 mono_error_set_pending_exception (&error
);
7250 ICALL_EXPORT MonoString
*
7251 ves_icall_System_Environment_InternalGetHome (void)
7253 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7256 static const char *encodings
[] = {
7258 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7259 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7260 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7262 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7263 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7264 "x_unicode_2_0_utf_7",
7266 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7267 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7269 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7272 "unicodefffe", "utf_16be",
7279 * Returns the internal codepage, if the value of "int_code_page" is
7280 * 1 at entry, and we can not compute a suitable code page number,
7281 * returns the code page as a string
7283 ICALL_EXPORT MonoString
*
7284 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32
*int_code_page
)
7289 char *codepage
= NULL
;
7291 int want_name
= *int_code_page
;
7294 *int_code_page
= -1;
7296 g_get_charset (&cset
);
7297 c
= codepage
= strdup (cset
);
7298 for (c
= codepage
; *c
; c
++){
7299 if (isascii (*c
) && isalpha (*c
))
7304 /* g_print ("charset: %s\n", cset); */
7306 /* handle some common aliases */
7309 for (i
= 0; p
!= 0; ){
7312 p
= encodings
[++i
];
7315 if (strcmp (p
, codepage
) == 0){
7316 *int_code_page
= code
;
7319 p
= encodings
[++i
];
7322 if (strstr (codepage
, "utf_8") != NULL
)
7323 *int_code_page
|= 0x10000000;
7326 if (want_name
&& *int_code_page
== -1)
7327 return mono_string_new (mono_domain_get (), cset
);
7332 ICALL_EXPORT MonoBoolean
7333 ves_icall_System_Environment_get_HasShutdownStarted (void)
7335 if (mono_runtime_is_shutting_down ())
7338 if (mono_domain_is_unloading (mono_domain_get ()))
7345 ves_icall_System_Environment_BroadcastSettingChange (void)
7348 SendMessageTimeout (HWND_BROADCAST
, WM_SETTINGCHANGE
, (WPARAM
)NULL
, (LPARAM
)L
"Environment", SMTO_ABORTIFHUNG
, 2000, 0);
7354 ves_icall_System_Environment_get_TickCount (void)
7356 /* this will overflow after ~24 days */
7357 return (gint32
) (mono_msec_boottime () & 0xffffffff);
7361 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7366 #ifndef DISABLE_REMOTING
7367 ICALL_EXPORT MonoBoolean
7368 ves_icall_IsTransparentProxy (MonoObject
*proxy
)
7373 if (proxy
->vtable
->klass
== mono_defaults
.transparent_proxy_class
)
7379 ICALL_EXPORT MonoReflectionMethod
*
7380 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7381 MonoReflectionType
*rtype
, MonoReflectionMethod
*rmethod
)
7383 MonoReflectionMethod
*ret
= NULL
;
7388 MonoMethod
**vtable
;
7389 MonoMethod
*res
= NULL
;
7391 MONO_CHECK_ARG_NULL (rtype
, NULL
);
7392 MONO_CHECK_ARG_NULL (rmethod
, NULL
);
7394 method
= rmethod
->method
;
7395 klass
= mono_class_from_mono_type (rtype
->type
);
7396 mono_class_init_checked (klass
, &error
);
7397 if (mono_error_set_pending_exception (&error
))
7400 if (MONO_CLASS_IS_INTERFACE (klass
))
7403 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
)
7406 if ((method
->flags
& METHOD_ATTRIBUTE_FINAL
) || !(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
7407 if (klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
))
7413 mono_class_setup_vtable (klass
);
7414 vtable
= klass
->vtable
;
7416 if (method
->klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
7417 gboolean variance_used
= FALSE
;
7418 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7419 int offs
= mono_class_interface_offset_with_variance (klass
, method
->klass
, &variance_used
);
7421 res
= vtable
[offs
+ method
->slot
];
7423 if (!(klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
)))
7426 if (method
->slot
!= -1)
7427 res
= vtable
[method
->slot
];
7433 ret
= mono_method_get_object_checked (mono_domain_get (), res
, NULL
, &error
);
7434 mono_error_set_pending_exception (&error
);
7439 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType
*type
, MonoBoolean enable
)
7445 klass
= mono_class_from_mono_type (type
->type
);
7446 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, &error
);
7447 if (!is_ok (&error
)) {
7448 mono_error_set_pending_exception (&error
);
7452 mono_vtable_set_is_remote (vtable
, enable
);
7455 #else /* DISABLE_REMOTING */
7458 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType
*type
, MonoBoolean enable
)
7460 g_assert_not_reached ();
7465 ICALL_EXPORT MonoObject
*
7466 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType
*type
)
7473 domain
= mono_object_domain (type
);
7474 klass
= mono_class_from_mono_type (type
->type
);
7475 mono_class_init_checked (klass
, &error
);
7476 if (mono_error_set_pending_exception (&error
))
7479 if (MONO_CLASS_IS_INTERFACE (klass
) || (klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
)) {
7480 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7484 if (klass
->rank
>= 1) {
7485 g_assert (klass
->rank
== 1);
7486 ret
= (MonoObject
*) mono_array_new_checked (domain
, klass
->element_class
, 0, &error
);
7487 mono_error_set_pending_exception (&error
);
7490 MonoVTable
*vtable
= mono_class_vtable_full (domain
, klass
, &error
);
7491 if (!is_ok (&error
)) {
7492 mono_error_set_pending_exception (&error
);
7495 /* Bypass remoting object creation check */
7496 ret
= mono_object_new_alloc_specific_checked (vtable
, &error
);
7497 mono_error_set_pending_exception (&error
);
7503 ICALL_EXPORT MonoString
*
7504 ves_icall_System_IO_get_temp_path (void)
7506 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7509 #ifndef PLATFORM_NO_DRIVEINFO
7510 ICALL_EXPORT MonoBoolean
7511 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString
*path_name
, guint64
*free_bytes_avail
,
7512 guint64
*total_number_of_bytes
, guint64
*total_number_of_free_bytes
,
7516 ULARGE_INTEGER wapi_free_bytes_avail
;
7517 ULARGE_INTEGER wapi_total_number_of_bytes
;
7518 ULARGE_INTEGER wapi_total_number_of_free_bytes
;
7520 *error
= ERROR_SUCCESS
;
7521 result
= GetDiskFreeSpaceEx (mono_string_chars (path_name
), &wapi_free_bytes_avail
, &wapi_total_number_of_bytes
,
7522 &wapi_total_number_of_free_bytes
);
7525 *free_bytes_avail
= wapi_free_bytes_avail
.QuadPart
;
7526 *total_number_of_bytes
= wapi_total_number_of_bytes
.QuadPart
;
7527 *total_number_of_free_bytes
= wapi_total_number_of_free_bytes
.QuadPart
;
7529 *free_bytes_avail
= 0;
7530 *total_number_of_bytes
= 0;
7531 *total_number_of_free_bytes
= 0;
7532 *error
= GetLastError ();
7538 ICALL_EXPORT guint32
7539 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString
*root_path_name
)
7541 return GetDriveType (mono_string_chars (root_path_name
));
7545 ICALL_EXPORT gpointer
7546 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod
*method
)
7549 gpointer result
= mono_compile_method_checked (method
, &error
);
7550 mono_error_set_pending_exception (&error
);
7554 ICALL_EXPORT MonoString
*
7555 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7560 path
= g_build_path (G_DIR_SEPARATOR_S
, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version
, "machine.config", NULL
);
7562 #if defined (HOST_WIN32)
7563 /* Avoid mixing '/' and '\\' */
7566 for (i
= strlen (path
) - 1; i
>= 0; i
--)
7567 if (path
[i
] == '/')
7571 mcpath
= mono_string_new (mono_domain_get (), path
);
7577 /* this is an icall */
7579 get_bundled_app_config (void)
7582 const gchar
*app_config
;
7585 gchar
*config_file_name
, *config_file_path
;
7586 gsize len
, config_file_path_length
, config_ext_length
;
7589 domain
= mono_domain_get ();
7590 file
= domain
->setup
->configuration_file
;
7591 if (!file
|| file
->length
== 0)
7594 // Retrieve config file and remove the extension
7595 config_file_name
= mono_string_to_utf8_checked (file
, &error
);
7596 if (mono_error_set_pending_exception (&error
))
7598 config_file_path
= mono_portability_find_file (config_file_name
, TRUE
);
7599 if (!config_file_path
)
7600 config_file_path
= config_file_name
;
7602 config_file_path_length
= strlen (config_file_path
);
7603 config_ext_length
= strlen (".config");
7604 if (config_file_path_length
<= config_ext_length
)
7607 len
= config_file_path_length
- config_ext_length
;
7608 module
= (gchar
*)g_malloc0 (len
+ 1);
7609 memcpy (module
, config_file_path
, len
);
7610 // Get the config file from the module name
7611 app_config
= mono_config_string_for_assembly_file (module
);
7614 if (config_file_name
!= config_file_path
)
7615 g_free (config_file_name
);
7616 g_free (config_file_path
);
7621 return mono_string_new (mono_domain_get (), app_config
);
7625 get_bundled_machine_config (void)
7627 const gchar
*machine_config
;
7629 machine_config
= mono_get_machine_config ();
7631 if (!machine_config
)
7634 return mono_string_new (mono_domain_get (), machine_config
);
7637 ICALL_EXPORT MonoString
*
7638 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7643 path
= g_path_get_dirname (mono_get_config_dir ());
7645 #if defined (HOST_WIN32)
7646 /* Avoid mixing '/' and '\\' */
7649 for (i
= strlen (path
) - 1; i
>= 0; i
--)
7650 if (path
[i
] == '/')
7654 ipath
= mono_string_new (mono_domain_get (), path
);
7660 ICALL_EXPORT gboolean
7661 ves_icall_get_resources_ptr (MonoReflectionAssembly
*assembly
, gpointer
*result
, gint32
*size
)
7663 MonoPEResourceDataEntry
*entry
;
7666 if (!assembly
|| !result
|| !size
)
7671 image
= assembly
->assembly
->image
;
7672 entry
= (MonoPEResourceDataEntry
*)mono_image_lookup_resource (image
, MONO_PE_RESOURCE_ID_ASPNET_STRING
, 0, NULL
);
7676 *result
= mono_image_rva_map (image
, entry
->rde_data_offset
);
7681 *size
= entry
->rde_size
;
7686 ICALL_EXPORT MonoBoolean
7687 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7689 return mono_is_debugger_attached ();
7692 ICALL_EXPORT MonoBoolean
7693 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7695 if (mono_get_runtime_callbacks ()->debug_log_is_enabled
)
7696 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7702 ves_icall_System_Diagnostics_Debugger_Log (int level
, MonoString
*category
, MonoString
*message
)
7704 if (mono_get_runtime_callbacks ()->debug_log
)
7705 mono_get_runtime_callbacks ()->debug_log (level
, category
, message
);
7709 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString
*message
)
7711 #if defined (HOST_WIN32)
7712 OutputDebugString (mono_string_chars (message
));
7714 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7718 /* Only used for value types */
7719 ICALL_EXPORT MonoObject
*
7720 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType
*type
)
7727 domain
= mono_object_domain (type
);
7728 klass
= mono_class_from_mono_type (type
->type
);
7729 mono_class_init_checked (klass
, &error
);
7730 if (mono_error_set_pending_exception (&error
))
7733 if (mono_class_is_nullable (klass
))
7734 /* No arguments -> null */
7737 result
= mono_object_new_checked (domain
, klass
, &error
);
7738 mono_error_set_pending_exception (&error
);
7742 ICALL_EXPORT MonoReflectionMethod
*
7743 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod
*m
, gboolean definition
)
7745 MonoReflectionMethod
*ret
= NULL
;
7748 MonoClass
*klass
, *parent
;
7749 MonoGenericContext
*generic_inst
= NULL
;
7750 MonoMethod
*method
= m
->method
;
7751 MonoMethod
*result
= NULL
;
7754 if (method
->klass
== NULL
)
7757 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
7758 MONO_CLASS_IS_INTERFACE (method
->klass
) ||
7759 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
7762 slot
= mono_method_get_vtable_slot (method
);
7766 klass
= method
->klass
;
7767 if (klass
->generic_class
) {
7768 generic_inst
= mono_class_get_context (klass
);
7769 klass
= klass
->generic_class
->container_class
;
7773 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7774 for (parent
= klass
->parent
; parent
!= NULL
; parent
= parent
->parent
) {
7775 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7776 or klass is the generic container class and generic_inst is the instantiation.
7778 when we go to the parent, if the parent is an open constructed type, we need to
7779 replace the type parameters by the definitions from the generic_inst, and then take it
7780 apart again into the klass and the generic_inst.
7782 For cases like this:
7783 class C<T> : B<T, int> {
7784 public override void Foo () { ... }
7786 class B<U,V> : A<HashMap<U,V>> {
7787 public override void Foo () { ... }
7790 public virtual void Foo () { ... }
7793 if at each iteration the parent isn't open, we can skip inflating it. if at some
7794 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7797 MonoGenericContext
*parent_inst
= NULL
;
7798 if (mono_class_is_open_constructed_type (mono_class_get_type (parent
))) {
7799 parent
= mono_class_inflate_generic_class_checked (parent
, generic_inst
, &error
);
7800 if (!mono_error_ok (&error
)) {
7801 mono_error_set_pending_exception (&error
);
7805 if (parent
->generic_class
) {
7806 parent_inst
= mono_class_get_context (parent
);
7807 parent
= parent
->generic_class
->container_class
;
7810 mono_class_setup_vtable (parent
);
7811 if (parent
->vtable_size
<= slot
)
7814 generic_inst
= parent_inst
;
7817 klass
= klass
->parent
;
7820 if (mono_class_is_open_constructed_type (mono_class_get_type (klass
))) {
7821 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, &error
);
7822 if (!mono_error_ok (&error
)) {
7823 mono_error_set_pending_exception (&error
);
7827 generic_inst
= NULL
;
7829 if (klass
->generic_class
) {
7830 generic_inst
= mono_class_get_context (klass
);
7831 klass
= klass
->generic_class
->container_class
;
7837 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, &error
);
7838 if (!mono_error_ok (&error
)) {
7839 mono_error_set_pending_exception (&error
);
7844 if (klass
== method
->klass
)
7847 /*This is possible if definition == FALSE.
7848 * Do it here to be really sure we don't read invalid memory.
7850 if (slot
>= klass
->vtable_size
)
7853 mono_class_setup_vtable (klass
);
7855 result
= klass
->vtable
[slot
];
7856 if (result
== NULL
) {
7857 /* It is an abstract method */
7858 gpointer iter
= NULL
;
7859 while ((result
= mono_class_get_methods (klass
, &iter
)))
7860 if (result
->slot
== slot
)
7867 ret
= mono_method_get_object_checked (mono_domain_get (), result
, NULL
, &error
);
7868 mono_error_set_pending_exception (&error
);
7872 ICALL_EXPORT MonoString
*
7873 ves_icall_MonoMethod_get_name (MonoReflectionMethod
*m
)
7875 MonoMethod
*method
= m
->method
;
7877 MONO_OBJECT_SETREF (m
, name
, mono_string_new (mono_object_domain (m
), method
->name
));
7882 mono_ArgIterator_Setup (MonoArgIterator
*iter
, char* argsp
, char* start
)
7884 iter
->sig
= *(MonoMethodSignature
**)argsp
;
7886 g_assert (iter
->sig
->sentinelpos
<= iter
->sig
->param_count
);
7887 g_assert (iter
->sig
->call_convention
== MONO_CALL_VARARG
);
7890 /* FIXME: it's not documented what start is exactly... */
7894 iter
->args
= argsp
+ sizeof (gpointer
);
7896 iter
->num_args
= iter
->sig
->param_count
- iter
->sig
->sentinelpos
;
7898 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7901 ICALL_EXPORT MonoTypedRef
7902 mono_ArgIterator_IntGetNextArg (MonoArgIterator
*iter
)
7904 guint32 i
, arg_size
;
7908 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7910 g_assert (i
< iter
->sig
->param_count
);
7912 res
.type
= iter
->sig
->params
[i
];
7913 res
.klass
= mono_class_from_mono_type (res
.type
);
7914 arg_size
= mono_type_stack_size (res
.type
, &align
);
7915 #if defined(__arm__) || defined(__mips__)
7916 iter
->args
= (guint8
*)(((gsize
)iter
->args
+ (align
) - 1) & ~(align
- 1));
7918 res
.value
= iter
->args
;
7919 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7920 /* Values are stored as 8 byte register sized objects, but 'value'
7921 * is dereferenced as a pointer in other routines.
7923 res
.value
= (char*)res
.value
+ 4;
7925 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7926 if (arg_size
<= sizeof (gpointer
)) {
7928 int padding
= arg_size
- mono_type_size (res
.type
, &dummy
);
7929 res
.value
= (guint8
*)res
.value
+ padding
;
7932 iter
->args
= (char*)iter
->args
+ arg_size
;
7935 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7940 ICALL_EXPORT MonoTypedRef
7941 mono_ArgIterator_IntGetNextArgT (MonoArgIterator
*iter
, MonoType
*type
)
7943 guint32 i
, arg_size
;
7947 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7949 g_assert (i
< iter
->sig
->param_count
);
7951 while (i
< iter
->sig
->param_count
) {
7952 if (!mono_metadata_type_equal (type
, iter
->sig
->params
[i
]))
7954 res
.type
= iter
->sig
->params
[i
];
7955 res
.klass
= mono_class_from_mono_type (res
.type
);
7956 /* FIXME: endianess issue... */
7957 arg_size
= mono_type_stack_size (res
.type
, &align
);
7958 #if defined(__arm__) || defined(__mips__)
7959 iter
->args
= (guint8
*)(((gsize
)iter
->args
+ (align
) - 1) & ~(align
- 1));
7961 res
.value
= iter
->args
;
7962 iter
->args
= (char*)iter
->args
+ arg_size
;
7964 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7967 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7975 ICALL_EXPORT MonoType
*
7976 mono_ArgIterator_IntGetNextArgType (MonoArgIterator
*iter
)
7980 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7982 g_assert (i
< iter
->sig
->param_count
);
7984 return iter
->sig
->params
[i
];
7987 ICALL_EXPORT MonoObject
*
7988 mono_TypedReference_ToObject (MonoTypedRef
* tref
)
7991 MonoObject
*result
= NULL
;
7992 if (MONO_TYPE_IS_REFERENCE (tref
->type
)) {
7993 MonoObject
** objp
= (MonoObject
**)tref
->value
;
7997 result
= mono_value_box_checked (mono_domain_get (), tref
->klass
, tref
->value
, &error
);
7998 mono_error_set_pending_exception (&error
);
8002 ICALL_EXPORT MonoTypedRef
8003 mono_TypedReference_MakeTypedReferenceInternal (MonoObject
*target
, MonoArray
*fields
)
8006 MonoReflectionField
*f
;
8008 MonoType
*ftype
= NULL
;
8012 memset (&res
, 0, sizeof (res
));
8015 g_assert (mono_array_length (fields
) > 0);
8017 klass
= target
->vtable
->klass
;
8019 for (i
= 0; i
< mono_array_length (fields
); ++i
) {
8020 f
= mono_array_get (fields
, MonoReflectionField
*, i
);
8022 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
8025 if (f
->field
->parent
!= klass
) {
8026 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
8030 p
= (guint8
*)target
+ f
->field
->offset
;
8032 p
+= f
->field
->offset
- sizeof (MonoObject
);
8033 klass
= mono_class_from_mono_type (f
->field
->type
);
8034 ftype
= f
->field
->type
;
8038 res
.klass
= mono_class_from_mono_type (ftype
);
8045 prelink_method (MonoMethod
*method
, MonoError
*error
)
8047 const char *exc_class
, *exc_arg
;
8049 mono_error_init (error
);
8050 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
8052 mono_lookup_pinvoke_call (method
, &exc_class
, &exc_arg
);
8054 mono_error_set_exception_instance (error
,
8055 mono_exception_from_name_msg (mono_defaults
.corlib
, "System", exc_class
, exc_arg
));
8058 /* create the wrapper, too? */
8062 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod
*method
)
8066 prelink_method (method
->method
, &error
);
8067 mono_error_set_pending_exception (&error
);
8071 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType
*type
)
8074 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
8076 gpointer iter
= NULL
;
8078 mono_class_init_checked (klass
, &error
);
8079 if (mono_error_set_pending_exception (&error
))
8082 while ((m
= mono_class_get_methods (klass
, &iter
))) {
8083 prelink_method (m
, &error
);
8084 if (mono_error_set_pending_exception (&error
))
8089 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8091 ves_icall_System_NumberFormatter_GetFormatterTables (guint64
const **mantissas
,
8092 gint32
const **exponents
,
8093 gunichar2
const **digitLowerTable
,
8094 gunichar2
const **digitUpperTable
,
8095 gint64
const **tenPowersList
,
8096 gint32
const **decHexDigits
)
8098 *mantissas
= Formatter_MantissaBitsTable
;
8099 *exponents
= Formatter_TensExponentTable
;
8100 *digitLowerTable
= Formatter_DigitLowerTable
;
8101 *digitUpperTable
= Formatter_DigitUpperTable
;
8102 *tenPowersList
= Formatter_TenPowersList
;
8103 *decHexDigits
= Formatter_DecHexDigits
;
8107 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8108 * and avoid useless allocations.
8111 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
, MonoError
*error
)
8113 MonoReflectionType
*rt
;
8117 mono_error_init (error
);
8118 for (i
= 0; i
< type
->num_mods
; ++i
) {
8119 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
))
8124 res
= mono_array_new_checked (mono_domain_get (), mono_defaults
.systemtype_class
, count
, error
);
8125 return_val_if_nok (error
, NULL
);
8127 for (i
= 0; i
< type
->num_mods
; ++i
) {
8128 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
)) {
8129 MonoClass
*klass
= mono_class_get_checked (image
, type
->modifiers
[i
].token
, error
);
8130 return_val_if_nok (error
, NULL
);
8132 rt
= mono_type_get_object_checked (mono_domain_get (), &klass
->byval_arg
, error
);
8133 return_val_if_nok (error
, NULL
);
8135 mono_array_setref (res
, count
, rt
);
8142 ICALL_EXPORT MonoArray
*
8143 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter
*param
, MonoBoolean optional
)
8146 MonoType
*type
= param
->ClassImpl
->type
;
8147 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
8148 MonoMethod
*method
= NULL
;
8151 MonoMethodSignature
*sig
;
8154 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
8155 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
8156 method
= rmethod
->method
;
8157 } else if (member_class
->image
== mono_defaults
.corlib
&& !strcmp ("MonoProperty", member_class
->name
)) {
8158 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
8159 if (!(method
= prop
->property
->get
))
8160 method
= prop
->property
->set
;
8163 char *type_name
= mono_type_get_full_name (member_class
);
8164 char *msg
= g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name
);
8165 MonoException
*ex
= mono_get_exception_not_supported (msg
);
8168 mono_set_pending_exception (ex
);
8172 image
= method
->klass
->image
;
8173 pos
= param
->PositionImpl
;
8174 sig
= mono_method_signature (method
);
8178 type
= sig
->params
[pos
];
8180 res
= type_array_from_modifiers (image
, type
, optional
, &error
);
8181 mono_error_set_pending_exception (&error
);
8186 get_property_type (MonoProperty
*prop
)
8188 MonoMethodSignature
*sig
;
8190 sig
= mono_method_signature (prop
->get
);
8192 } else if (prop
->set
) {
8193 sig
= mono_method_signature (prop
->set
);
8194 return sig
->params
[sig
->param_count
- 1];
8199 ICALL_EXPORT MonoArray
*
8200 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty
*property
, MonoBoolean optional
)
8203 MonoType
*type
= get_property_type (property
->property
);
8204 MonoImage
*image
= property
->klass
->image
;
8209 res
= type_array_from_modifiers (image
, type
, optional
, &error
);
8210 mono_error_set_pending_exception (&error
);
8215 *Construct a MonoType suited to be used to decode a constant blob object.
8217 * @type is the target type which will be constructed
8218 * @blob_type is the blob type, for example, that comes from the constant table
8219 * @real_type is the expected constructed type.
8222 mono_type_from_blob_type (MonoType
*type
, MonoTypeEnum blob_type
, MonoType
*real_type
)
8224 type
->type
= blob_type
;
8225 type
->data
.klass
= NULL
;
8226 if (blob_type
== MONO_TYPE_CLASS
)
8227 type
->data
.klass
= mono_defaults
.object_class
;
8228 else if (real_type
->type
== MONO_TYPE_VALUETYPE
&& real_type
->data
.klass
->enumtype
) {
8229 /* For enums, we need to use the base type */
8230 type
->type
= MONO_TYPE_VALUETYPE
;
8231 type
->data
.klass
= mono_class_from_mono_type (real_type
);
8233 type
->data
.klass
= mono_class_from_mono_type (real_type
);
8236 ICALL_EXPORT MonoObject
*
8237 property_info_get_default_value (MonoReflectionProperty
*property
)
8241 MonoProperty
*prop
= property
->property
;
8242 MonoType
*type
= get_property_type (prop
);
8243 MonoDomain
*domain
= mono_object_domain (property
);
8244 MonoTypeEnum def_type
;
8245 const char *def_value
;
8248 mono_class_init (prop
->parent
);
8250 if (!(prop
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
)) {
8251 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL
));
8255 def_value
= mono_class_get_property_default_value (prop
, &def_type
);
8257 mono_type_from_blob_type (&blob_type
, def_type
, type
);
8258 o
= mono_get_object_from_blob (domain
, &blob_type
, def_value
, &error
);
8260 mono_error_set_pending_exception (&error
);
8264 ICALL_EXPORT MonoBoolean
8265 custom_attrs_defined_internal (MonoObject
*obj
, MonoReflectionType
*attr_type
)
8268 MonoClass
*attr_class
= mono_class_from_mono_type (attr_type
->type
);
8269 MonoCustomAttrInfo
*cinfo
;
8272 mono_class_init_checked (attr_class
, &error
);
8273 if (mono_error_set_pending_exception (&error
))
8276 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, &error
);
8277 if (!is_ok (&error
)) {
8278 mono_error_set_pending_exception (&error
);
8283 found
= mono_custom_attrs_has_attr (cinfo
, attr_class
);
8285 mono_custom_attrs_free (cinfo
);
8289 ICALL_EXPORT MonoArray
*
8290 custom_attrs_get_by_type (MonoObject
*obj
, MonoReflectionType
*attr_type
)
8292 MonoClass
*attr_class
= attr_type
? mono_class_from_mono_type (attr_type
->type
) : NULL
;
8297 mono_class_init_checked (attr_class
, &error
);
8298 if (mono_error_set_pending_exception (&error
))
8302 res
= mono_reflection_get_custom_attrs_by_type (obj
, attr_class
, &error
);
8303 if (!mono_error_ok (&error
)) {
8304 mono_error_set_pending_exception (&error
);
8311 ICALL_EXPORT MonoArray
*
8312 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject
*obj
)
8316 result
= mono_reflection_get_custom_attrs_data_checked (obj
, &error
);
8317 mono_error_set_pending_exception (&error
);
8322 ICALL_EXPORT MonoString
*
8323 ves_icall_Mono_Runtime_GetDisplayName (void)
8326 MonoString
*display_name
;
8328 info
= mono_get_runtime_callbacks ()->get_runtime_build_info ();
8329 display_name
= mono_string_new (mono_domain_get (), info
);
8331 return display_name
;
8334 ICALL_EXPORT MonoString
*
8335 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code
)
8338 MonoString
*message
;
8342 ret
= FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
8343 FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, code
, 0,
8346 message
= mono_string_new (mono_domain_get (), "Error looking up error string");
8348 message
= mono_string_new_utf16_checked (mono_domain_get (), buf
, ret
, &error
);
8349 if (mono_error_set_pending_exception (&error
))
8356 ICALL_EXPORT gpointer
8357 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8359 return GetCurrentProcess ();
8362 ICALL_EXPORT MonoBoolean
8363 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle
, gint32
*exitcode
)
8365 return GetExitCodeProcess (handle
, (guint32
*) exitcode
);
8368 ICALL_EXPORT MonoBoolean
8369 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle
)
8371 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8372 return CloseHandle (handle
);
8374 return CloseProcess (handle
);
8378 ICALL_EXPORT MonoBoolean
8379 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle
, gint32 exitcode
)
8381 return TerminateProcess (handle
, exitcode
);
8385 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle
, gint32 milliseconds
)
8387 return WaitForInputIdle (handle
, milliseconds
);
8390 ICALL_EXPORT MonoBoolean
8391 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle
, gsize
*min
, gsize
*max
)
8393 return GetProcessWorkingSetSize (handle
, min
, max
);
8396 ICALL_EXPORT MonoBoolean
8397 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle
, gsize min
, gsize max
)
8399 return SetProcessWorkingSetSize (handle
, min
, max
);
8402 ICALL_EXPORT MonoBoolean
8403 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle
, gint64
*creationtime
, gint64
*exittime
, gint64
*kerneltime
, gint64
*usertime
)
8405 return GetProcessTimes (handle
, (LPFILETIME
) creationtime
, (LPFILETIME
) exittime
, (LPFILETIME
) kerneltime
, (LPFILETIME
) usertime
);
8409 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8411 return mono_process_current_pid ();
8415 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle
)
8417 return GetPriorityClass (handle
);
8420 ICALL_EXPORT MonoBoolean
8421 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle
, gint32 priorityClass
)
8423 return SetPriorityClass (handle
, priorityClass
);
8426 #ifndef DISABLE_ICALL_TABLES
8428 #define ICALL_TYPE(id,name,first)
8429 #define ICALL(id,name,func) Icall_ ## id,
8432 #include "metadata/icall-def.h"
8438 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8439 #define ICALL(id,name,func)
8441 #include "metadata/icall-def.h"
8447 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8448 #define ICALL(id,name,func)
8450 guint16 first_icall
;
8453 static const IcallTypeDesc
8454 icall_type_descs
[] = {
8455 #include "metadata/icall-def.h"
8459 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8462 #define ICALL_TYPE(id,name,first)
8465 #ifdef HAVE_ARRAY_ELEM_INIT
8466 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8467 #define MSGSTRFIELD1(line) str##line
8469 static const struct msgstrtn_t
{
8470 #define ICALL(id,name,func)
8472 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8473 #include "metadata/icall-def.h"
8475 } icall_type_names_str
= {
8476 #define ICALL_TYPE(id,name,first) (name),
8477 #include "metadata/icall-def.h"
8480 static const guint16 icall_type_names_idx
[] = {
8481 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8482 #include "metadata/icall-def.h"
8485 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8487 static const struct msgstr_t
{
8489 #define ICALL_TYPE(id,name,first)
8490 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8491 #include "metadata/icall-def.h"
8493 } icall_names_str
= {
8494 #define ICALL(id,name,func) (name),
8495 #include "metadata/icall-def.h"
8498 static const guint16 icall_names_idx
[] = {
8499 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8500 #include "metadata/icall-def.h"
8503 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8509 #define ICALL_TYPE(id,name,first) name,
8510 #define ICALL(id,name,func)
8511 static const char* const
8512 icall_type_names
[] = {
8513 #include "metadata/icall-def.h"
8517 #define icall_type_name_get(id) (icall_type_names [(id)])
8521 #define ICALL_TYPE(id,name,first)
8522 #define ICALL(id,name,func) name,
8523 static const char* const
8525 #include "metadata/icall-def.h"
8528 #define icall_name_get(id) icall_names [(id)]
8530 #endif /* !HAVE_ARRAY_ELEM_INIT */
8534 #define ICALL_TYPE(id,name,first)
8535 #define ICALL(id,name,func) func,
8536 static const gconstpointer
8537 icall_functions
[] = {
8538 #include "metadata/icall-def.h"
8542 #ifdef ENABLE_ICALL_SYMBOL_MAP
8545 #define ICALL_TYPE(id,name,first)
8546 #define ICALL(id,name,func) #func,
8547 static const gconstpointer
8548 icall_symbols
[] = {
8549 #include "metadata/icall-def.h"
8554 #endif /* DISABLE_ICALL_TABLES */
8556 static mono_mutex_t icall_mutex
;
8557 static GHashTable
*icall_hash
= NULL
;
8558 static GHashTable
*jit_icall_hash_name
= NULL
;
8559 static GHashTable
*jit_icall_hash_addr
= NULL
;
8562 mono_icall_init (void)
8564 #ifndef DISABLE_ICALL_TABLES
8567 /* check that tables are sorted: disable in release */
8570 const char *prev_class
= NULL
;
8571 const char *prev_method
;
8573 for (i
= 0; i
< Icall_type_num
; ++i
) {
8574 const IcallTypeDesc
*desc
;
8577 if (prev_class
&& strcmp (prev_class
, icall_type_name_get (i
)) >= 0)
8578 g_print ("class %s should come before class %s\n", icall_type_name_get (i
), prev_class
);
8579 prev_class
= icall_type_name_get (i
);
8580 desc
= &icall_type_descs
[i
];
8581 num_icalls
= icall_desc_num_icalls (desc
);
8582 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8583 for (j
= 0; j
< num_icalls
; ++j
) {
8584 const char *methodn
= icall_name_get (desc
->first_icall
+ j
);
8585 if (prev_method
&& strcmp (prev_method
, methodn
) >= 0)
8586 g_print ("method %s should come before method %s\n", methodn
, prev_method
);
8587 prev_method
= methodn
;
8593 icall_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
8594 mono_os_mutex_init (&icall_mutex
);
8598 mono_icall_lock (void)
8600 mono_locks_os_acquire (&icall_mutex
, IcallLock
);
8604 mono_icall_unlock (void)
8606 mono_locks_os_release (&icall_mutex
, IcallLock
);
8610 mono_icall_cleanup (void)
8612 g_hash_table_destroy (icall_hash
);
8613 g_hash_table_destroy (jit_icall_hash_name
);
8614 g_hash_table_destroy (jit_icall_hash_addr
);
8615 mono_os_mutex_destroy (&icall_mutex
);
8619 * mono_add_internal_call:
8620 * @name: method specification to surface to the managed world
8621 * @method: pointer to a C method to invoke when the method is called
8623 * This method surfaces the C function pointed by @method as a method
8624 * that has been surfaced in managed code with the method specified in
8625 * @name as an internal call.
8627 * Internal calls are surfaced to all app domains loaded and they are
8628 * accessibly by a type with the specified name.
8630 * You must provide a fully qualified type name, that is namespaces
8631 * and type name, followed by a colon and the method name, with an
8632 * optional signature to bind.
8634 * For example, the following are all valid declarations:
8636 * "MyApp.Services.ScriptService:Accelerate"
8637 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8639 * You use method parameters in cases where there might be more than
8640 * one surface method to managed code. That way you can register different
8641 * internal calls for different method overloads.
8643 * The internal calls are invoked with no marshalling. This means that .NET
8644 * types like System.String are exposed as `MonoString *` parameters. This is
8645 * different than the way that strings are surfaced in P/Invoke.
8647 * For more information on how the parameters are marshalled, see the
8648 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8651 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8652 * reference for more information on the format of method descriptions.
8655 mono_add_internal_call (const char *name
, gconstpointer method
)
8659 g_hash_table_insert (icall_hash
, g_strdup (name
), (gpointer
) method
);
8661 mono_icall_unlock ();
8664 #ifndef DISABLE_ICALL_TABLES
8666 #ifdef HAVE_ARRAY_ELEM_INIT
8668 compare_method_imap (const void *key
, const void *elem
)
8670 const char* method_name
= (const char*)&icall_names_str
+ (*(guint16
*)elem
);
8671 return strcmp (key
, method_name
);
8675 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
8677 const guint16
*nameslot
= (const guint16
*)mono_binary_search (name
, icall_names_idx
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names_idx
[0]), compare_method_imap
);
8680 return (gpointer
)icall_functions
[(nameslot
- &icall_names_idx
[0])];
8684 compare_class_imap (const void *key
, const void *elem
)
8686 const char* class_name
= (const char*)&icall_type_names_str
+ (*(guint16
*)elem
);
8687 return strcmp (key
, class_name
);
8690 static const IcallTypeDesc
*
8691 find_class_icalls (const char *name
)
8693 const guint16
*nameslot
= (const guint16
*)mono_binary_search (name
, icall_type_names_idx
, Icall_type_num
, sizeof (icall_type_names_idx
[0]), compare_class_imap
);
8696 return &icall_type_descs
[nameslot
- &icall_type_names_idx
[0]];
8699 #else /* HAVE_ARRAY_ELEM_INIT */
8702 compare_method_imap (const void *key
, const void *elem
)
8704 const char** method_name
= (const char**)elem
;
8705 return strcmp (key
, *method_name
);
8709 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
8711 const char **nameslot
= mono_binary_search (name
, icall_names
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names
[0]), compare_method_imap
);
8714 return (gpointer
)icall_functions
[(nameslot
- icall_names
)];
8718 compare_class_imap (const void *key
, const void *elem
)
8720 const char** class_name
= (const char**)elem
;
8721 return strcmp (key
, *class_name
);
8724 static const IcallTypeDesc
*
8725 find_class_icalls (const char *name
)
8727 const char **nameslot
= mono_binary_search (name
, icall_type_names
, Icall_type_num
, sizeof (icall_type_names
[0]), compare_class_imap
);
8730 return &icall_type_descs
[nameslot
- icall_type_names
];
8733 #endif /* HAVE_ARRAY_ELEM_INIT */
8735 #endif /* DISABLE_ICALL_TABLES */
8738 * we should probably export this as an helper (handle nested types).
8739 * Returns the number of chars written in buf.
8742 concat_class_name (char *buf
, int bufsize
, MonoClass
*klass
)
8744 int nspacelen
, cnamelen
;
8745 nspacelen
= strlen (klass
->name_space
);
8746 cnamelen
= strlen (klass
->name
);
8747 if (nspacelen
+ cnamelen
+ 2 > bufsize
)
8750 memcpy (buf
, klass
->name_space
, nspacelen
);
8751 buf
[nspacelen
++] = '.';
8753 memcpy (buf
+ nspacelen
, klass
->name
, cnamelen
);
8754 buf
[nspacelen
+ cnamelen
] = 0;
8755 return nspacelen
+ cnamelen
;
8758 #ifdef DISABLE_ICALL_TABLES
8760 no_icall_table (void)
8762 g_assert_not_reached ();
8767 mono_lookup_internal_call (MonoMethod
*method
)
8772 int typelen
= 0, mlen
, siglen
;
8774 #ifndef DISABLE_ICALL_TABLES
8775 const IcallTypeDesc
*imap
= NULL
;
8778 g_assert (method
!= NULL
);
8780 if (method
->is_inflated
)
8781 method
= ((MonoMethodInflated
*) method
)->declaring
;
8783 if (method
->klass
->nested_in
) {
8784 int pos
= concat_class_name (mname
, sizeof (mname
)-2, method
->klass
->nested_in
);
8788 mname
[pos
++] = '/';
8791 typelen
= concat_class_name (mname
+pos
, sizeof (mname
)-pos
-1, method
->klass
);
8797 typelen
= concat_class_name (mname
, sizeof (mname
), method
->klass
);
8802 #ifndef DISABLE_ICALL_TABLES
8803 imap
= find_class_icalls (mname
);
8806 mname
[typelen
] = ':';
8807 mname
[typelen
+ 1] = ':';
8809 mlen
= strlen (method
->name
);
8810 memcpy (mname
+ typelen
+ 2, method
->name
, mlen
);
8811 sigstart
= mname
+ typelen
+ 2 + mlen
;
8814 tmpsig
= mono_signature_get_desc (mono_method_signature (method
), TRUE
);
8815 siglen
= strlen (tmpsig
);
8816 if (typelen
+ mlen
+ siglen
+ 6 > sizeof (mname
))
8819 memcpy (sigstart
+ 1, tmpsig
, siglen
);
8820 sigstart
[siglen
+ 1] = ')';
8821 sigstart
[siglen
+ 2] = 0;
8826 res
= g_hash_table_lookup (icall_hash
, mname
);
8828 mono_icall_unlock ();;
8831 /* try without signature */
8833 res
= g_hash_table_lookup (icall_hash
, mname
);
8835 mono_icall_unlock ();
8839 #ifdef DISABLE_ICALL_TABLES
8840 mono_icall_unlock ();
8841 /* Fail only when the result is actually used */
8842 /* mono_marshal_get_native_wrapper () depends on this */
8843 if (method
->klass
== mono_defaults
.string_class
&& !strcmp (method
->name
, ".ctor"))
8844 return ves_icall_System_String_ctor_RedirectToCreateString
;
8846 return no_icall_table
;
8848 /* it wasn't found in the static call tables */
8850 mono_icall_unlock ();
8853 res
= find_method_icall (imap
, sigstart
- mlen
);
8855 mono_icall_unlock ();
8858 /* try _with_ signature */
8860 res
= find_method_icall (imap
, sigstart
- mlen
);
8862 mono_icall_unlock ();
8866 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname
);
8867 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8868 g_print ("The out of sync library is: %s\n", method
->klass
->image
->name
);
8869 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8870 g_print ("Do not report this as a bug unless you're sure you have updated correctly:\nyou probably have a broken mono install.\n");
8871 g_print ("If you see other errors or faults after this message they are probably related\n");
8872 g_print ("and you need to fix your mono install first.\n");
8874 mono_icall_unlock ();
8880 #ifdef ENABLE_ICALL_SYMBOL_MAP
8882 func_cmp (gconstpointer key
, gconstpointer p
)
8884 return (gsize
)key
- (gsize
)*(gsize
*)p
;
8889 * mono_lookup_icall_symbol:
8891 * Given the icall METHOD, returns its C symbol.
8894 mono_lookup_icall_symbol (MonoMethod
*m
)
8896 #ifdef DISABLE_ICALL_TABLES
8897 g_assert_not_reached ();
8900 #ifdef ENABLE_ICALL_SYMBOL_MAP
8904 static gconstpointer
*functions_sorted
;
8905 static const char**symbols_sorted
;
8906 static gboolean inited
;
8911 functions_sorted
= g_malloc (G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
8912 memcpy (functions_sorted
, icall_functions
, G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
8913 symbols_sorted
= g_malloc (G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
8914 memcpy (symbols_sorted
, icall_symbols
, G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
8915 /* Bubble sort the two arrays */
8919 for (i
= 0; i
< G_N_ELEMENTS (icall_functions
) - 1; ++i
) {
8920 if (functions_sorted
[i
] > functions_sorted
[i
+ 1]) {
8923 tmp
= functions_sorted
[i
];
8924 functions_sorted
[i
] = functions_sorted
[i
+ 1];
8925 functions_sorted
[i
+ 1] = tmp
;
8926 tmp
= symbols_sorted
[i
];
8927 symbols_sorted
[i
] = symbols_sorted
[i
+ 1];
8928 symbols_sorted
[i
+ 1] = tmp
;
8935 func
= mono_lookup_internal_call (m
);
8938 slot
= mono_binary_search (func
, functions_sorted
, G_N_ELEMENTS (icall_functions
), sizeof (gpointer
), func_cmp
);
8942 return symbols_sorted
[(gpointer
*)slot
- (gpointer
*)functions_sorted
];
8944 fprintf (stderr
, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8945 g_assert_not_reached ();
8952 type_from_typename (char *type_name
)
8954 MonoClass
*klass
= NULL
; /* assignment to shut GCC warning up */
8956 if (!strcmp (type_name
, "int"))
8957 klass
= mono_defaults
.int_class
;
8958 else if (!strcmp (type_name
, "ptr"))
8959 klass
= mono_defaults
.int_class
;
8960 else if (!strcmp (type_name
, "void"))
8961 klass
= mono_defaults
.void_class
;
8962 else if (!strcmp (type_name
, "int32"))
8963 klass
= mono_defaults
.int32_class
;
8964 else if (!strcmp (type_name
, "uint32"))
8965 klass
= mono_defaults
.uint32_class
;
8966 else if (!strcmp (type_name
, "int8"))
8967 klass
= mono_defaults
.sbyte_class
;
8968 else if (!strcmp (type_name
, "uint8"))
8969 klass
= mono_defaults
.byte_class
;
8970 else if (!strcmp (type_name
, "int16"))
8971 klass
= mono_defaults
.int16_class
;
8972 else if (!strcmp (type_name
, "uint16"))
8973 klass
= mono_defaults
.uint16_class
;
8974 else if (!strcmp (type_name
, "long"))
8975 klass
= mono_defaults
.int64_class
;
8976 else if (!strcmp (type_name
, "ulong"))
8977 klass
= mono_defaults
.uint64_class
;
8978 else if (!strcmp (type_name
, "float"))
8979 klass
= mono_defaults
.single_class
;
8980 else if (!strcmp (type_name
, "double"))
8981 klass
= mono_defaults
.double_class
;
8982 else if (!strcmp (type_name
, "object"))
8983 klass
= mono_defaults
.object_class
;
8984 else if (!strcmp (type_name
, "obj"))
8985 klass
= mono_defaults
.object_class
;
8986 else if (!strcmp (type_name
, "string"))
8987 klass
= mono_defaults
.string_class
;
8988 else if (!strcmp (type_name
, "bool"))
8989 klass
= mono_defaults
.boolean_class
;
8990 else if (!strcmp (type_name
, "boolean"))
8991 klass
= mono_defaults
.boolean_class
;
8993 g_error ("%s", type_name
);
8994 g_assert_not_reached ();
8996 return &klass
->byval_arg
;
9000 * LOCKING: Take the corlib image lock.
9002 MonoMethodSignature
*
9003 mono_create_icall_signature (const char *sigstr
)
9008 MonoMethodSignature
*res
, *res2
;
9009 MonoImage
*corlib
= mono_defaults
.corlib
;
9011 mono_image_lock (corlib
);
9012 res
= (MonoMethodSignature
*)g_hash_table_lookup (corlib
->helper_signatures
, sigstr
);
9013 mono_image_unlock (corlib
);
9018 parts
= g_strsplit (sigstr
, " ", 256);
9027 res
= mono_metadata_signature_alloc (corlib
, len
- 1);
9032 * Under windows, the default pinvoke calling convention is STDCALL but
9035 res
->call_convention
= MONO_CALL_C
;
9038 res
->ret
= type_from_typename (parts
[0]);
9039 for (i
= 1; i
< len
; ++i
) {
9040 res
->params
[i
- 1] = type_from_typename (parts
[i
]);
9045 mono_image_lock (corlib
);
9046 res2
= (MonoMethodSignature
*)g_hash_table_lookup (corlib
->helper_signatures
, sigstr
);
9048 res
= res2
; /*Value is allocated in the image pool*/
9050 g_hash_table_insert (corlib
->helper_signatures
, (gpointer
)sigstr
, res
);
9051 mono_image_unlock (corlib
);
9057 mono_find_jit_icall_by_name (const char *name
)
9059 MonoJitICallInfo
*info
;
9060 g_assert (jit_icall_hash_name
);
9063 info
= (MonoJitICallInfo
*)g_hash_table_lookup (jit_icall_hash_name
, name
);
9064 mono_icall_unlock ();
9069 mono_find_jit_icall_by_addr (gconstpointer addr
)
9071 MonoJitICallInfo
*info
;
9072 g_assert (jit_icall_hash_addr
);
9075 info
= (MonoJitICallInfo
*)g_hash_table_lookup (jit_icall_hash_addr
, (gpointer
)addr
);
9076 mono_icall_unlock ();
9082 * mono_get_jit_icall_info:
9084 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9085 * caller should access it while holding the icall lock.
9088 mono_get_jit_icall_info (void)
9090 return jit_icall_hash_name
;
9094 * mono_lookup_jit_icall_symbol:
9096 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9099 mono_lookup_jit_icall_symbol (const char *name
)
9101 MonoJitICallInfo
*info
;
9102 const char *res
= NULL
;
9105 info
= (MonoJitICallInfo
*)g_hash_table_lookup (jit_icall_hash_name
, name
);
9107 res
= info
->c_symbol
;
9108 mono_icall_unlock ();
9113 mono_register_jit_icall_wrapper (MonoJitICallInfo
*info
, gconstpointer wrapper
)
9116 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)wrapper
, info
);
9117 mono_icall_unlock ();
9121 * If NO_RAISE is set, that means the icall is not calling mono_raise_exception () directly or indirectly. The JIT might be able to call these
9122 * icalls without wrappers in some cases.
9125 mono_register_jit_icall_full (gconstpointer func
, const char *name
, MonoMethodSignature
*sig
, gboolean is_save
, gboolean no_raise
, const char *c_symbol
)
9127 MonoJitICallInfo
*info
;
9134 if (!jit_icall_hash_name
) {
9135 jit_icall_hash_name
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, g_free
);
9136 jit_icall_hash_addr
= g_hash_table_new (NULL
, NULL
);
9139 if (g_hash_table_lookup (jit_icall_hash_name
, name
)) {
9140 g_warning ("jit icall already defined \"%s\"\n", name
);
9141 g_assert_not_reached ();
9144 info
= g_new0 (MonoJitICallInfo
, 1);
9149 info
->c_symbol
= c_symbol
;
9150 info
->no_raise
= no_raise
;
9153 info
->wrapper
= func
;
9155 info
->wrapper
= NULL
;
9158 g_hash_table_insert (jit_icall_hash_name
, (gpointer
)info
->name
, info
);
9159 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)func
, info
);
9161 mono_icall_unlock ();
9166 mono_register_jit_icall (gconstpointer func
, const char *name
, MonoMethodSignature
*sig
, gboolean is_save
)
9168 return mono_register_jit_icall_full (func
, name
, sig
, is_save
, FALSE
, NULL
);