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
);
1539 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray
*ptr_array
, MonoBoolean freeSeg
)
1541 g_ptr_array_free (ptr_array
, freeSeg
);
1544 /* System.TypeCode */
1563 TYPECODE_STRING
= 18
1566 ICALL_EXPORT guint32
1567 ves_icall_type_GetTypeCodeInternal (MonoReflectionType
*type
)
1569 int t
= type
->type
->type
;
1571 if (type
->type
->byref
)
1572 return TYPECODE_OBJECT
;
1576 case MONO_TYPE_VOID
:
1577 return TYPECODE_OBJECT
;
1578 case MONO_TYPE_BOOLEAN
:
1579 return TYPECODE_BOOLEAN
;
1581 return TYPECODE_BYTE
;
1583 return TYPECODE_SBYTE
;
1585 return TYPECODE_UINT16
;
1587 return TYPECODE_INT16
;
1588 case MONO_TYPE_CHAR
:
1589 return TYPECODE_CHAR
;
1593 return TYPECODE_OBJECT
;
1595 return TYPECODE_UINT32
;
1597 return TYPECODE_INT32
;
1599 return TYPECODE_UINT64
;
1601 return TYPECODE_INT64
;
1603 return TYPECODE_SINGLE
;
1605 return TYPECODE_DOUBLE
;
1606 case MONO_TYPE_VALUETYPE
: {
1607 MonoClass
*klass
= type
->type
->data
.klass
;
1609 if (klass
->enumtype
) {
1610 t
= mono_class_enum_basetype (klass
)->type
;
1612 } else if (mono_is_corlib_image (klass
->image
)) {
1613 if (strcmp (klass
->name_space
, "System") == 0) {
1614 if (strcmp (klass
->name
, "Decimal") == 0)
1615 return TYPECODE_DECIMAL
;
1616 else if (strcmp (klass
->name
, "DateTime") == 0)
1617 return TYPECODE_DATETIME
;
1620 return TYPECODE_OBJECT
;
1622 case MONO_TYPE_STRING
:
1623 return TYPECODE_STRING
;
1624 case MONO_TYPE_SZARRAY
:
1625 case MONO_TYPE_ARRAY
:
1626 case MONO_TYPE_OBJECT
:
1628 case MONO_TYPE_MVAR
:
1629 case MONO_TYPE_TYPEDBYREF
:
1630 return TYPECODE_OBJECT
;
1631 case MONO_TYPE_CLASS
:
1633 MonoClass
*klass
= type
->type
->data
.klass
;
1634 if (klass
->image
== mono_defaults
.corlib
&& strcmp (klass
->name_space
, "System") == 0) {
1635 if (strcmp (klass
->name
, "DBNull") == 0)
1636 return TYPECODE_DBNULL
;
1639 return TYPECODE_OBJECT
;
1640 case MONO_TYPE_GENERICINST
:
1641 return TYPECODE_OBJECT
;
1643 g_error ("type 0x%02x not handled in GetTypeCode()", t
);
1649 mono_type_is_primitive (MonoType
*type
)
1651 return (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_R8
) ||
1652 type
-> type
== MONO_TYPE_I
|| type
->type
== MONO_TYPE_U
;
1656 mono_type_get_underlying_type_ignore_byref (MonoType
*type
)
1658 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
)
1659 return mono_class_enum_basetype (type
->data
.klass
);
1660 if (type
->type
== MONO_TYPE_GENERICINST
&& type
->data
.generic_class
->container_class
->enumtype
)
1661 return mono_class_enum_basetype (type
->data
.generic_class
->container_class
);
1665 ICALL_EXPORT guint32
1666 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType
*type
, MonoReflectionType
*c
)
1671 g_assert (type
!= NULL
);
1673 klass
= mono_class_from_mono_type (type
->type
);
1674 klassc
= mono_class_from_mono_type (c
->type
);
1676 if (type
->type
->byref
^ c
->type
->byref
)
1679 if (type
->type
->byref
) {
1680 MonoType
*t
= mono_type_get_underlying_type_ignore_byref (type
->type
);
1681 MonoType
*ot
= mono_type_get_underlying_type_ignore_byref (c
->type
);
1683 klass
= mono_class_from_mono_type (t
);
1684 klassc
= mono_class_from_mono_type (ot
);
1686 if (mono_type_is_primitive (t
)) {
1687 return mono_type_is_primitive (ot
) && klass
->instance_size
== klassc
->instance_size
;
1688 } else if (t
->type
== MONO_TYPE_VAR
|| t
->type
== MONO_TYPE_MVAR
) {
1689 return t
->type
== ot
->type
&& t
->data
.generic_param
->num
== ot
->data
.generic_param
->num
;
1690 } else if (t
->type
== MONO_TYPE_PTR
|| t
->type
== MONO_TYPE_FNPTR
) {
1691 return t
->type
== ot
->type
;
1693 if (ot
->type
== MONO_TYPE_VAR
|| ot
->type
== MONO_TYPE_MVAR
)
1696 if (klass
->valuetype
)
1697 return klass
== klassc
;
1698 return klass
->valuetype
== klassc
->valuetype
;
1701 return mono_class_is_assignable_from (klass
, klassc
);
1704 ICALL_EXPORT guint32
1705 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType
*type
, MonoObject
*obj
)
1708 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1709 mono_class_init_checked (klass
, &error
);
1710 if (!is_ok (&error
)) {
1711 mono_error_set_pending_exception (&error
);
1714 guint32 result
= (mono_object_isinst_checked (obj
, klass
, &error
) != NULL
);
1715 mono_error_set_pending_exception (&error
);
1719 ICALL_EXPORT guint32
1720 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType
*type
)
1722 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1723 return klass
->flags
;
1726 ICALL_EXPORT MonoReflectionMarshalAsAttribute
*
1727 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField
*field
)
1730 MonoClass
*klass
= field
->field
->parent
;
1731 MonoMarshalType
*info
;
1735 if (klass
->generic_container
||
1736 (klass
->generic_class
&& klass
->generic_class
->context
.class_inst
->is_open
))
1739 ftype
= mono_field_get_type (field
->field
);
1740 if (ftype
&& !(ftype
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL
))
1743 info
= mono_marshal_load_type_info (klass
);
1745 for (i
= 0; i
< info
->num_fields
; ++i
) {
1746 if (info
->fields
[i
].field
== field
->field
) {
1747 if (!info
->fields
[i
].mspec
)
1750 MonoReflectionMarshalAsAttribute
* obj
;
1751 obj
= mono_reflection_marshal_as_attribute_from_marshal_spec (field
->object
.vtable
->domain
, klass
, info
->fields
[i
].mspec
, &error
);
1752 if (!mono_error_ok (&error
))
1753 mono_error_set_pending_exception (&error
);
1762 ICALL_EXPORT MonoReflectionField
*
1763 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField
*handle
, MonoType
*type
)
1766 gboolean found
= FALSE
;
1773 klass
= handle
->parent
;
1775 klass
= mono_class_from_mono_type (type
);
1777 /* Check that the field belongs to the class */
1778 for (k
= klass
; k
; k
= k
->parent
) {
1779 if (k
== handle
->parent
) {
1786 /* The managed code will throw the exception */
1790 MonoReflectionField
*result
= mono_field_get_object_checked (mono_domain_get (), klass
, handle
, &error
);
1791 mono_error_set_pending_exception (&error
);
1795 ICALL_EXPORT MonoArray
*
1796 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField
*field
, MonoBoolean optional
)
1799 MonoType
*type
= mono_field_get_type_checked (field
->field
, &error
);
1802 if (!mono_error_ok (&error
)) {
1803 mono_error_set_pending_exception (&error
);
1807 res
= type_array_from_modifiers (field
->field
->parent
->image
, type
, optional
, &error
);
1808 mono_error_set_pending_exception (&error
);
1813 vell_icall_get_method_attributes (MonoMethod
*method
)
1815 return method
->flags
;
1819 ves_icall_get_method_info (MonoMethod
*method
, MonoMethodInfo
*info
)
1822 MonoReflectionType
*rt
;
1823 MonoDomain
*domain
= mono_domain_get ();
1824 MonoMethodSignature
* sig
;
1826 sig
= mono_method_signature_checked (method
, &error
);
1827 if (!mono_error_ok (&error
)) {
1828 mono_error_set_pending_exception (&error
);
1832 rt
= mono_type_get_object_checked (domain
, &method
->klass
->byval_arg
, &error
);
1833 if (!mono_error_ok (&error
)) {
1834 mono_error_set_pending_exception (&error
);
1838 MONO_STRUCT_SETREF (info
, parent
, rt
);
1840 rt
= mono_type_get_object_checked (domain
, sig
->ret
, &error
);
1841 if (!mono_error_ok (&error
)) {
1842 mono_error_set_pending_exception (&error
);
1846 MONO_STRUCT_SETREF (info
, ret
, rt
);
1848 info
->attrs
= method
->flags
;
1849 info
->implattrs
= method
->iflags
;
1850 if (sig
->call_convention
== MONO_CALL_DEFAULT
)
1851 info
->callconv
= sig
->sentinelpos
>= 0 ? 2 : 1;
1853 if (sig
->call_convention
== MONO_CALL_VARARG
|| sig
->sentinelpos
>= 0)
1858 info
->callconv
|= (sig
->hasthis
<< 5) | (sig
->explicit_this
<< 6);
1861 ICALL_EXPORT MonoArray
*
1862 ves_icall_get_parameter_info (MonoMethod
*method
, MonoReflectionMethod
*member
)
1865 MonoDomain
*domain
= mono_domain_get ();
1867 MonoArray
*result
= mono_param_get_objects_internal (domain
, method
, member
->reftype
? mono_class_from_mono_type (member
->reftype
->type
) : NULL
, &error
);
1868 mono_error_set_pending_exception (&error
);
1872 ICALL_EXPORT MonoReflectionMarshalAsAttribute
*
1873 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod
*method
)
1876 MonoDomain
*domain
= mono_domain_get ();
1877 MonoReflectionMarshalAsAttribute
* res
= NULL
;
1878 MonoMarshalSpec
**mspecs
;
1881 mspecs
= g_new (MonoMarshalSpec
*, mono_method_signature (method
)->param_count
+ 1);
1882 mono_method_get_marshal_info (method
, mspecs
);
1885 res
= mono_reflection_marshal_as_attribute_from_marshal_spec (domain
, method
->klass
, mspecs
[0], &error
);
1886 if (!mono_error_ok (&error
)) {
1887 mono_error_set_pending_exception (&error
);
1892 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
1894 mono_metadata_free_marshal_spec (mspecs
[i
]);
1901 ves_icall_MonoField_GetFieldOffset (MonoReflectionField
*field
)
1903 MonoClass
*parent
= field
->field
->parent
;
1904 if (!parent
->size_inited
)
1905 mono_class_init (parent
);
1906 mono_class_setup_fields_locking (parent
);
1908 return field
->field
->offset
- sizeof (MonoObject
);
1911 ICALL_EXPORT MonoReflectionType
*
1912 ves_icall_MonoField_GetParentType (MonoReflectionField
*field
, MonoBoolean declaring
)
1915 MonoReflectionType
*ret
;
1918 parent
= declaring
? field
->field
->parent
: field
->klass
;
1920 ret
= mono_type_get_object_checked (mono_object_domain (field
), &parent
->byval_arg
, &error
);
1921 mono_error_set_pending_exception (&error
);
1927 ICALL_EXPORT MonoObject
*
1928 ves_icall_MonoField_GetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
)
1931 MonoClass
*fklass
= field
->klass
;
1932 MonoClassField
*cf
= field
->field
;
1933 MonoDomain
*domain
= mono_object_domain (field
);
1935 if (fklass
->image
->assembly
->ref_only
) {
1936 mono_set_pending_exception (mono_get_exception_invalid_operation (
1937 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1941 if (mono_security_core_clr_enabled () &&
1942 !mono_security_core_clr_ensure_reflection_access_field (cf
, &error
)) {
1943 mono_error_set_pending_exception (&error
);
1947 MonoObject
* result
= mono_field_get_value_object_checked (domain
, cf
, obj
, &error
);
1948 mono_error_set_pending_exception (&error
);
1953 ves_icall_MonoField_SetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
, MonoObject
*value
)
1956 MonoClassField
*cf
= field
->field
;
1960 if (field
->klass
->image
->assembly
->ref_only
) {
1961 mono_set_pending_exception (mono_get_exception_invalid_operation (
1962 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1966 if (mono_security_core_clr_enabled () &&
1967 !mono_security_core_clr_ensure_reflection_access_field (cf
, &error
)) {
1968 mono_error_set_pending_exception (&error
);
1972 type
= mono_field_get_type_checked (cf
, &error
);
1973 if (!mono_error_ok (&error
)) {
1974 mono_error_set_pending_exception (&error
);
1978 v
= (gchar
*) value
;
1980 switch (type
->type
) {
1983 case MONO_TYPE_BOOLEAN
:
1986 case MONO_TYPE_CHAR
:
1995 case MONO_TYPE_VALUETYPE
:
1998 v
+= sizeof (MonoObject
);
2000 case MONO_TYPE_STRING
:
2001 case MONO_TYPE_OBJECT
:
2002 case MONO_TYPE_CLASS
:
2003 case MONO_TYPE_ARRAY
:
2004 case MONO_TYPE_SZARRAY
:
2007 case MONO_TYPE_GENERICINST
: {
2008 MonoGenericClass
*gclass
= type
->data
.generic_class
;
2009 g_assert (!gclass
->context
.class_inst
->is_open
);
2011 if (mono_class_is_nullable (mono_class_from_mono_type (type
))) {
2012 MonoClass
*nklass
= mono_class_from_mono_type (type
);
2013 MonoObject
*nullable
;
2016 * Convert the boxed vtype into a Nullable structure.
2017 * This is complicated by the fact that Nullables have
2018 * a variable structure.
2020 nullable
= mono_object_new_checked (mono_domain_get (), nklass
, &error
);
2021 if (!mono_error_ok (&error
)) {
2022 mono_error_set_pending_exception (&error
);
2026 mono_nullable_init ((guint8
*)mono_object_unbox (nullable
), value
, nklass
);
2028 v
= (gchar
*)mono_object_unbox (nullable
);
2031 if (gclass
->container_class
->valuetype
&& (v
!= NULL
))
2032 v
+= sizeof (MonoObject
);
2036 g_error ("type 0x%x not handled in "
2037 "ves_icall_FieldInfo_SetValueInternal", type
->type
);
2042 if (type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
2043 MonoVTable
*vtable
= mono_class_vtable_full (mono_object_domain (field
), cf
->parent
, &error
);
2044 if (!is_ok (&error
)) {
2045 mono_error_set_pending_exception (&error
);
2048 if (!vtable
->initialized
) {
2049 if (!mono_runtime_class_init_full (vtable
, &error
)) {
2050 mono_error_set_pending_exception (&error
);
2054 mono_field_static_set_value (vtable
, cf
, v
);
2056 mono_field_set_value (obj
, cf
, v
);
2061 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField
*field
, MonoReflectionType
*field_type
, MonoTypedRef
*obj
, MonoObject
*value
, MonoReflectionType
*context_type
)
2070 if (!MONO_TYPE_ISSTRUCT (&f
->parent
->byval_arg
)) {
2071 mono_set_pending_exception (mono_get_exception_not_implemented (NULL
));
2075 if (MONO_TYPE_IS_REFERENCE (f
->type
))
2076 mono_copy_value (f
->type
, (guint8
*)obj
->value
+ f
->offset
- sizeof (MonoObject
), value
, FALSE
);
2078 mono_copy_value (f
->type
, (guint8
*)obj
->value
+ f
->offset
- sizeof (MonoObject
), mono_object_unbox (value
), FALSE
);
2081 ICALL_EXPORT MonoObject
*
2082 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField
*rfield
)
2084 MonoObject
*o
= NULL
;
2085 MonoClassField
*field
= rfield
->field
;
2087 MonoDomain
*domain
= mono_object_domain (rfield
);
2089 MonoTypeEnum def_type
;
2090 const char *def_value
;
2094 mono_class_init (field
->parent
);
2096 t
= mono_field_get_type_checked (field
, &error
);
2097 if (!mono_error_ok (&error
)) {
2098 mono_error_set_pending_exception (&error
);
2102 if (!(t
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
)) {
2103 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL
));
2107 if (image_is_dynamic (field
->parent
->image
)) {
2108 MonoClass
*klass
= field
->parent
;
2109 int fidx
= field
- klass
->fields
;
2111 g_assert (fidx
>= 0 && fidx
< klass
->field
.count
);
2112 g_assert (klass
->ext
);
2113 g_assert (klass
->ext
->field_def_values
);
2114 def_type
= klass
->ext
->field_def_values
[fidx
].def_type
;
2115 def_value
= klass
->ext
->field_def_values
[fidx
].data
;
2116 if (def_type
== MONO_TYPE_END
) {
2117 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL
));
2121 def_value
= mono_class_get_field_default_value (field
, &def_type
);
2122 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2124 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL
));
2129 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2133 case MONO_TYPE_BOOLEAN
:
2136 case MONO_TYPE_CHAR
:
2144 case MONO_TYPE_R8
: {
2147 /* boxed value type */
2148 t
= g_new0 (MonoType
, 1);
2150 klass
= mono_class_from_mono_type (t
);
2152 o
= mono_object_new_checked (domain
, klass
, &error
);
2153 if (!mono_error_ok (&error
)) {
2154 mono_error_set_pending_exception (&error
);
2157 v
= ((gchar
*) o
) + sizeof (MonoObject
);
2158 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, v
, &error
);
2159 if (mono_error_set_pending_exception (&error
))
2163 case MONO_TYPE_STRING
:
2164 case MONO_TYPE_CLASS
:
2165 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, &o
, &error
);
2166 if (mono_error_set_pending_exception (&error
))
2170 g_assert_not_reached ();
2176 ICALL_EXPORT MonoReflectionType
*
2177 ves_icall_MonoField_ResolveType (MonoReflectionField
*ref_field
)
2180 MonoReflectionType
*ret
;
2183 type
= mono_field_get_type_checked (ref_field
->field
, &error
);
2184 if (!mono_error_ok (&error
)) {
2185 mono_error_set_pending_exception (&error
);
2189 ret
= mono_type_get_object_checked (mono_object_domain (ref_field
), type
, &error
);
2190 if (!mono_error_ok (&error
)) {
2191 mono_error_set_pending_exception (&error
);
2198 /* From MonoProperty.cs */
2200 PInfo_Attributes
= 1,
2201 PInfo_GetMethod
= 1 << 1,
2202 PInfo_SetMethod
= 1 << 2,
2203 PInfo_ReflectedType
= 1 << 3,
2204 PInfo_DeclaringType
= 1 << 4,
2209 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty
*property
, MonoPropertyInfo
*info
, PInfo req_info
)
2212 MonoReflectionType
*rt
;
2213 MonoReflectionMethod
*rm
;
2214 MonoDomain
*domain
= mono_object_domain (property
);
2215 const MonoProperty
*pproperty
= property
->property
;
2217 if ((req_info
& PInfo_ReflectedType
) != 0) {
2218 rt
= mono_type_get_object_checked (domain
, &property
->klass
->byval_arg
, &error
);
2219 if (mono_error_set_pending_exception (&error
))
2222 MONO_STRUCT_SETREF (info
, parent
, rt
);
2224 if ((req_info
& PInfo_DeclaringType
) != 0) {
2225 rt
= mono_type_get_object_checked (domain
, &pproperty
->parent
->byval_arg
, &error
);
2226 if (mono_error_set_pending_exception (&error
))
2229 MONO_STRUCT_SETREF (info
, declaring_type
, rt
);
2232 if ((req_info
& PInfo_Name
) != 0)
2233 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, pproperty
->name
));
2235 if ((req_info
& PInfo_Attributes
) != 0)
2236 info
->attrs
= pproperty
->attrs
;
2238 if ((req_info
& PInfo_GetMethod
) != 0) {
2239 if (pproperty
->get
&&
2240 (((pproperty
->get
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) ||
2241 pproperty
->get
->klass
== property
->klass
)) {
2242 rm
= mono_method_get_object_checked (domain
, pproperty
->get
, property
->klass
, &error
);
2243 if (mono_error_set_pending_exception (&error
))
2249 MONO_STRUCT_SETREF (info
, get
, rm
);
2251 if ((req_info
& PInfo_SetMethod
) != 0) {
2252 if (pproperty
->set
&&
2253 (((pproperty
->set
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) ||
2254 pproperty
->set
->klass
== property
->klass
)) {
2255 rm
= mono_method_get_object_checked (domain
, pproperty
->set
, property
->klass
, &error
);
2256 if (mono_error_set_pending_exception (&error
))
2262 MONO_STRUCT_SETREF (info
, set
, rm
);
2265 * There may be other methods defined for properties, though, it seems they are not exposed
2266 * in the reflection API
2271 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent
*event
, MonoEventInfo
*info
)
2274 MonoReflectionType
*rt
;
2275 MonoReflectionMethod
*rm
;
2276 MonoDomain
*domain
= mono_object_domain (event
);
2278 rt
= mono_type_get_object_checked (domain
, &event
->klass
->byval_arg
, &error
);
2279 if (mono_error_set_pending_exception (&error
))
2282 MONO_STRUCT_SETREF (info
, reflected_type
, rt
);
2284 rt
= mono_type_get_object_checked (domain
, &event
->event
->parent
->byval_arg
, &error
);
2285 if (mono_error_set_pending_exception (&error
))
2288 MONO_STRUCT_SETREF (info
, declaring_type
, rt
);
2290 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, event
->event
->name
));
2291 info
->attrs
= event
->event
->attrs
;
2293 if (event
->event
->add
) {
2294 rm
= mono_method_get_object_checked (domain
, event
->event
->add
, NULL
, &error
);
2295 if (mono_error_set_pending_exception (&error
))
2301 MONO_STRUCT_SETREF (info
, add_method
, rm
);
2303 if (event
->event
->remove
) {
2304 rm
= mono_method_get_object_checked (domain
, event
->event
->remove
, NULL
, &error
);
2305 if (mono_error_set_pending_exception (&error
))
2311 MONO_STRUCT_SETREF (info
, remove_method
, rm
);
2313 if (event
->event
->raise
) {
2314 rm
= mono_method_get_object_checked (domain
, event
->event
->raise
, NULL
, &error
);
2315 if (mono_error_set_pending_exception (&error
))
2321 MONO_STRUCT_SETREF (info
, raise_method
, rm
);
2323 #ifndef MONO_SMALL_CONFIG
2324 if (event
->event
->other
) {
2326 while (event
->event
->other
[n
])
2328 MonoArray
*info_arr
= mono_array_new_checked (domain
, mono_defaults
.method_info_class
, n
, &error
);
2329 if (mono_error_set_pending_exception (&error
))
2331 MONO_STRUCT_SETREF (info
, other_methods
, info_arr
);
2333 for (i
= 0; i
< n
; i
++) {
2334 rm
= mono_method_get_object_checked (domain
, event
->event
->other
[i
], NULL
, &error
);
2335 if (mono_error_set_pending_exception (&error
))
2337 mono_array_setref (info
->other_methods
, i
, rm
);
2344 collect_interfaces (MonoClass
*klass
, GHashTable
*ifaces
, MonoError
*error
)
2349 mono_class_setup_interfaces (klass
, error
);
2350 if (!mono_error_ok (error
))
2353 for (i
= 0; i
< klass
->interface_count
; i
++) {
2354 ic
= klass
->interfaces
[i
];
2355 g_hash_table_insert (ifaces
, ic
, ic
);
2357 collect_interfaces (ic
, ifaces
, error
);
2358 if (!mono_error_ok (error
))
2364 MonoArray
*iface_array
;
2365 MonoGenericContext
*context
;
2369 } FillIfaceArrayData
;
2372 fill_iface_array (gpointer key
, gpointer value
, gpointer user_data
)
2374 MonoReflectionType
*rt
;
2375 FillIfaceArrayData
*data
= (FillIfaceArrayData
*)user_data
;
2376 MonoClass
*ic
= (MonoClass
*)key
;
2377 MonoType
*ret
= &ic
->byval_arg
, *inflated
= NULL
;
2379 if (!mono_error_ok (data
->error
))
2382 if (data
->context
&& ic
->generic_class
&& ic
->generic_class
->context
.class_inst
->is_open
) {
2383 inflated
= ret
= mono_class_inflate_generic_type_checked (ret
, data
->context
, data
->error
);
2384 if (!mono_error_ok (data
->error
))
2388 rt
= mono_type_get_object_checked (data
->domain
, ret
, data
->error
);
2389 if (!mono_error_ok (data
->error
))
2392 mono_array_setref (data
->iface_array
, data
->next_idx
++, rt
);
2395 mono_metadata_free_type (inflated
);
2399 get_interfaces_hash (gconstpointer v1
)
2401 MonoClass
*k
= (MonoClass
*)v1
;
2403 return k
->type_token
;
2406 ICALL_EXPORT MonoArray
*
2407 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType
* type
)
2410 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2412 FillIfaceArrayData data
= { 0 };
2415 GHashTable
*iface_hash
= g_hash_table_new (get_interfaces_hash
, NULL
);
2417 if (klass
->generic_class
&& klass
->generic_class
->context
.class_inst
->is_open
) {
2418 data
.context
= mono_class_get_context (klass
);
2419 klass
= klass
->generic_class
->container_class
;
2422 for (parent
= klass
; parent
; parent
= parent
->parent
) {
2423 mono_class_setup_interfaces (parent
, &error
);
2424 if (!mono_error_ok (&error
))
2426 collect_interfaces (parent
, iface_hash
, &error
);
2427 if (!mono_error_ok (&error
))
2431 data
.error
= &error
;
2432 data
.domain
= mono_object_domain (type
);
2434 len
= g_hash_table_size (iface_hash
);
2436 g_hash_table_destroy (iface_hash
);
2437 if (!data
.domain
->empty_types
) {
2438 data
.domain
->empty_types
= mono_array_new_cached (data
.domain
, mono_defaults
.runtimetype_class
, 0, &error
);
2439 if (!is_ok (&error
))
2442 return data
.domain
->empty_types
;
2445 data
.iface_array
= mono_array_new_cached (data
.domain
, mono_defaults
.runtimetype_class
, len
, &error
);
2446 if (!is_ok (&error
))
2448 g_hash_table_foreach (iface_hash
, fill_iface_array
, &data
);
2449 if (!mono_error_ok (&error
))
2452 g_hash_table_destroy (iface_hash
);
2453 return data
.iface_array
;
2456 g_hash_table_destroy (iface_hash
);
2457 mono_error_set_pending_exception (&error
);
2462 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType
*type
, MonoReflectionType
*iface
, MonoArray
**targets
, MonoArray
**methods
)
2464 gboolean variance_used
;
2465 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2466 MonoClass
*iclass
= mono_class_from_mono_type (iface
->type
);
2467 MonoReflectionMethod
*member
;
2470 int i
= 0, len
, ioffset
;
2474 mono_class_init_checked (klass
, &error
);
2475 if (mono_error_set_pending_exception (&error
))
2477 mono_class_init_checked (iclass
, &error
);
2478 if (mono_error_set_pending_exception (&error
))
2481 mono_class_setup_vtable (klass
);
2483 ioffset
= mono_class_interface_offset_with_variance (klass
, iclass
, &variance_used
);
2487 len
= mono_class_num_methods (iclass
);
2488 domain
= mono_object_domain (type
);
2489 MonoArray
*targets_arr
= mono_array_new_checked (domain
, mono_defaults
.method_info_class
, len
, &error
);
2490 if (mono_error_set_pending_exception (&error
))
2492 mono_gc_wbarrier_generic_store (targets
, (MonoObject
*) targets_arr
);
2493 MonoArray
*methods_arr
= mono_array_new_checked (domain
, mono_defaults
.method_info_class
, len
, &error
);
2494 if (mono_error_set_pending_exception (&error
))
2496 mono_gc_wbarrier_generic_store (methods
, (MonoObject
*) methods_arr
);
2498 while ((method
= mono_class_get_methods (iclass
, &iter
))) {
2499 member
= mono_method_get_object_checked (domain
, method
, iclass
, &error
);
2500 if (mono_error_set_pending_exception (&error
))
2502 mono_array_setref (*methods
, i
, member
);
2503 member
= mono_method_get_object_checked (domain
, klass
->vtable
[i
+ ioffset
], klass
, &error
);
2504 if (mono_error_set_pending_exception (&error
))
2506 mono_array_setref (*targets
, i
, member
);
2513 ves_icall_RuntimeType_GetPacking (MonoReflectionType
*type
, guint32
*packing
, guint32
*size
)
2516 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2518 mono_class_init_checked (klass
, &error
);
2519 if (mono_error_set_pending_exception (&error
))
2522 if (image_is_dynamic (klass
->image
)) {
2523 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)type
;
2524 *packing
= tb
->packing_size
;
2525 *size
= tb
->class_size
;
2527 mono_metadata_packing_from_typedef (klass
->image
, klass
->type_token
, packing
, size
);
2531 ICALL_EXPORT MonoReflectionType
*
2532 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType
*type
)
2535 MonoReflectionType
*ret
;
2538 if (!type
->type
->byref
&& type
->type
->type
== MONO_TYPE_SZARRAY
) {
2539 ret
= mono_type_get_object_checked (mono_object_domain (type
), &type
->type
->data
.klass
->byval_arg
, &error
);
2540 mono_error_set_pending_exception (&error
);
2544 klass
= mono_class_from_mono_type (type
->type
);
2545 mono_class_init_checked (klass
, &error
);
2546 if (mono_error_set_pending_exception (&error
))
2550 // GetElementType should only return a type for:
2551 // Array Pointer PassedByRef
2552 if (type
->type
->byref
)
2553 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->byval_arg
, &error
);
2554 else if (klass
->element_class
&& MONO_CLASS_IS_ARRAY (klass
))
2555 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->element_class
->byval_arg
, &error
);
2556 else if (klass
->element_class
&& type
->type
->type
== MONO_TYPE_PTR
)
2557 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->element_class
->byval_arg
, &error
);
2561 mono_error_set_pending_exception (&error
);
2566 ICALL_EXPORT MonoReflectionType
*
2567 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType
*type
)
2570 MonoReflectionType
*ret
;
2572 if (type
->type
->byref
)
2575 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2579 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->parent
->byval_arg
, &error
);
2580 mono_error_set_pending_exception (&error
);
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType
*type
)
2588 return type
->type
->type
== MONO_TYPE_PTR
;
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType
*type
)
2594 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
)));
2597 ICALL_EXPORT MonoBoolean
2598 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType
*type
)
2600 return type
->type
->byref
;
2603 ICALL_EXPORT MonoBoolean
2604 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType
*type
)
2607 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2608 mono_class_init_checked (klass
, &error
);
2609 if (mono_error_set_pending_exception (&error
))
2612 return mono_class_is_com_object (klass
);
2615 ICALL_EXPORT guint32
2616 ves_icall_reflection_get_token (MonoObject
* obj
)
2619 guint32 result
= mono_reflection_get_token_checked (obj
, &error
);
2620 mono_error_set_pending_exception (&error
);
2624 ICALL_EXPORT MonoReflectionModule
*
2625 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType
*type
)
2628 MonoReflectionModule
*result
= NULL
;
2629 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2630 result
= mono_module_get_object_checked (mono_object_domain (type
), klass
->image
, &error
);
2631 mono_error_set_pending_exception (&error
);
2635 ICALL_EXPORT MonoReflectionAssembly
*
2636 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType
*type
)
2639 MonoDomain
*domain
= mono_domain_get ();
2640 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2641 MonoReflectionAssembly
*result
= mono_assembly_get_object_checked (domain
, klass
->image
->assembly
, &error
);
2642 mono_error_set_pending_exception (&error
);
2646 ICALL_EXPORT MonoReflectionType
*
2647 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType
*type
)
2650 MonoReflectionType
*ret
;
2651 MonoDomain
*domain
= mono_domain_get ();
2654 if (type
->type
->byref
)
2656 if (type
->type
->type
== MONO_TYPE_VAR
) {
2657 MonoGenericContainer
*param
= mono_type_get_generic_param_owner (type
->type
);
2658 klass
= param
? param
->owner
.klass
: NULL
;
2659 } else if (type
->type
->type
== MONO_TYPE_MVAR
) {
2660 MonoGenericContainer
*param
= mono_type_get_generic_param_owner (type
->type
);
2661 klass
= param
? param
->owner
.method
->klass
: NULL
;
2663 klass
= mono_class_from_mono_type (type
->type
)->nested_in
;
2669 ret
= mono_type_get_object_checked (domain
, &klass
->byval_arg
, &error
);
2670 mono_error_set_pending_exception (&error
);
2675 ICALL_EXPORT MonoString
*
2676 ves_icall_RuntimeType_get_Name (MonoReflectionType
*type
)
2678 MonoDomain
*domain
= mono_domain_get ();
2679 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2681 if (type
->type
->byref
) {
2682 char *n
= g_strdup_printf ("%s&", klass
->name
);
2683 MonoString
*res
= mono_string_new (domain
, n
);
2689 return mono_string_new (domain
, klass
->name
);
2693 ICALL_EXPORT MonoString
*
2694 ves_icall_RuntimeType_get_Namespace (MonoReflectionType
*type
)
2696 MonoDomain
*domain
= mono_domain_get ();
2697 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2699 while (klass
->nested_in
)
2700 klass
= klass
->nested_in
;
2702 if (klass
->name_space
[0] == '\0')
2705 return mono_string_new (domain
, klass
->name_space
);
2709 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType
*type
)
2713 if (type
->type
->type
!= MONO_TYPE_ARRAY
&& type
->type
->type
!= MONO_TYPE_SZARRAY
) {
2714 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2718 klass
= mono_class_from_mono_type (type
->type
);
2724 create_type_array (MonoDomain
*domain
, MonoBoolean runtimeTypeArray
, int count
, MonoError
*error
)
2726 return mono_array_new_checked (domain
, runtimeTypeArray
? mono_defaults
.runtimetype_class
: mono_defaults
.systemtype_class
, count
, error
);
2729 ICALL_EXPORT MonoArray
*
2730 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType
*type
, MonoBoolean runtimeTypeArray
)
2733 MonoReflectionType
*rt
;
2735 MonoClass
*klass
, *pklass
;
2736 MonoDomain
*domain
= mono_object_domain (type
);
2739 klass
= mono_class_from_mono_type (type
->type
);
2741 if (klass
->generic_container
) {
2742 MonoGenericContainer
*container
= klass
->generic_container
;
2743 res
= create_type_array (domain
, runtimeTypeArray
, container
->type_argc
, &error
);
2744 if (mono_error_set_pending_exception (&error
))
2746 for (i
= 0; i
< container
->type_argc
; ++i
) {
2747 pklass
= mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container
, i
));
2749 rt
= mono_type_get_object_checked (domain
, &pklass
->byval_arg
, &error
);
2750 if (mono_error_set_pending_exception (&error
))
2753 mono_array_setref (res
, i
, rt
);
2755 } else if (klass
->generic_class
) {
2756 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
2757 res
= create_type_array (domain
, runtimeTypeArray
, inst
->type_argc
, &error
);
2758 if (mono_error_set_pending_exception (&error
))
2760 for (i
= 0; i
< inst
->type_argc
; ++i
) {
2761 rt
= mono_type_get_object_checked (domain
, inst
->type_argv
[i
], &error
);
2762 if (mono_error_set_pending_exception (&error
))
2765 mono_array_setref (res
, i
, rt
);
2773 ICALL_EXPORT gboolean
2774 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType
*type
)
2778 if (!IS_MONOTYPE (type
))
2781 if (type
->type
->byref
)
2784 klass
= mono_class_from_mono_type (type
->type
);
2785 return klass
->generic_container
!= NULL
;
2788 ICALL_EXPORT MonoReflectionType
*
2789 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType
*type
)
2792 MonoReflectionType
*ret
;
2795 if (type
->type
->byref
)
2798 klass
= mono_class_from_mono_type (type
->type
);
2800 if (klass
->generic_container
) {
2801 return type
; /* check this one */
2803 if (klass
->generic_class
) {
2804 MonoClass
*generic_class
= klass
->generic_class
->container_class
;
2807 tb
= mono_class_get_ref_info (generic_class
);
2809 if (generic_class
->wastypebuilder
&& tb
)
2810 return (MonoReflectionType
*)tb
;
2812 ret
= mono_type_get_object_checked (mono_object_domain (type
), &generic_class
->byval_arg
, &error
);
2813 mono_error_set_pending_exception (&error
);
2821 ICALL_EXPORT MonoReflectionType
*
2822 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType
*type
, MonoArray
*type_array
)
2825 MonoReflectionType
*ret
;
2827 MonoType
*geninst
, **types
;
2830 g_assert (IS_MONOTYPE (type
));
2831 mono_class_init_checked (mono_class_from_mono_type (type
->type
), &error
);
2832 if (mono_error_set_pending_exception (&error
))
2835 count
= mono_array_length (type_array
);
2836 types
= g_new0 (MonoType
*, count
);
2838 for (i
= 0; i
< count
; i
++) {
2839 MonoReflectionType
*t
= (MonoReflectionType
*)mono_array_get (type_array
, gpointer
, i
);
2840 types
[i
] = t
->type
;
2843 geninst
= mono_reflection_bind_generic_parameters (type
, count
, types
, &error
);
2846 mono_error_set_pending_exception (&error
);
2850 klass
= mono_class_from_mono_type (geninst
);
2852 /*we might inflate to the GTD*/
2853 if (klass
->generic_class
&& !mono_verifier_class_is_valid_generic_instantiation (klass
)) {
2854 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2858 ret
= mono_type_get_object_checked (mono_object_domain (type
), geninst
, &error
);
2859 mono_error_set_pending_exception (&error
);
2864 ICALL_EXPORT gboolean
2865 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType
*type
)
2869 if (!IS_MONOTYPE (type
))
2872 if (type
->type
->byref
)
2875 klass
= mono_class_from_mono_type (type
->type
);
2876 return klass
->generic_class
!= NULL
|| klass
->generic_container
!= NULL
;
2880 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType
*type
)
2882 if (!IS_MONOTYPE (type
))
2885 if (is_generic_parameter (type
->type
))
2886 return mono_type_get_generic_param_num (type
->type
);
2890 ICALL_EXPORT MonoGenericParamInfo
*
2891 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType
*type
)
2893 return mono_generic_param_info (type
->type
->data
.generic_param
);
2896 ICALL_EXPORT MonoBoolean
2897 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType
*type
)
2899 return is_generic_parameter (type
->type
);
2902 ICALL_EXPORT MonoBoolean
2903 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder
*tb
)
2905 return is_generic_parameter (tb
->type
.type
);
2909 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType
*enumtype
,
2910 MonoReflectionType
*t
)
2912 enumtype
->type
= t
->type
;
2915 ICALL_EXPORT MonoReflectionMethod
*
2916 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType
*type
,
2917 MonoReflectionMethod
* generic
)
2924 MonoReflectionMethod
*ret
= NULL
;
2926 domain
= ((MonoObject
*)type
)->vtable
->domain
;
2928 klass
= mono_class_from_mono_type (type
->type
);
2929 mono_class_init_checked (klass
, &error
);
2930 if (mono_error_set_pending_exception (&error
))
2934 while ((method
= mono_class_get_methods (klass
, &iter
))) {
2935 if (method
->token
== generic
->method
->token
) {
2936 ret
= mono_method_get_object_checked (domain
, method
, klass
, &error
);
2937 if (mono_error_set_pending_exception (&error
))
2945 ICALL_EXPORT MonoReflectionMethod
*
2946 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType
*ref_type
)
2949 MonoType
*type
= ref_type
->type
;
2951 MonoReflectionMethod
*ret
= NULL
;
2953 if (type
->byref
|| (type
->type
!= MONO_TYPE_MVAR
&& type
->type
!= MONO_TYPE_VAR
)) {
2954 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2957 if (type
->type
== MONO_TYPE_VAR
)
2960 method
= mono_type_get_generic_param_owner (type
)->owner
.method
;
2963 ret
= mono_method_get_object_checked (mono_object_domain (ref_type
), method
, method
->klass
, &error
);
2964 if (!mono_error_ok (&error
))
2965 mono_set_pending_exception (mono_error_convert_to_exception (&error
));
2969 ICALL_EXPORT MonoBoolean
2970 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2972 mono_set_pending_exception (mono_get_exception_not_implemented (NULL
));
2976 ICALL_EXPORT MonoBoolean
2977 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2979 mono_set_pending_exception (mono_get_exception_not_implemented (NULL
));
2984 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod
*method
, int* flags
, MonoString
** entry_point
, MonoString
** dll_name
)
2986 MonoDomain
*domain
= mono_domain_get ();
2987 MonoImage
*image
= method
->method
->klass
->image
;
2988 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)method
->method
;
2989 MonoTableInfo
*tables
= image
->tables
;
2990 MonoTableInfo
*im
= &tables
[MONO_TABLE_IMPLMAP
];
2991 MonoTableInfo
*mr
= &tables
[MONO_TABLE_MODULEREF
];
2992 guint32 im_cols
[MONO_IMPLMAP_SIZE
];
2993 guint32 scope_token
;
2994 const char *import
= NULL
;
2995 const char *scope
= NULL
;
2997 if (image_is_dynamic (image
)) {
2998 MonoReflectionMethodAux
*method_aux
=
2999 (MonoReflectionMethodAux
*)g_hash_table_lookup (((MonoDynamicImage
*)image
)->method_aux_hash
, method
->method
);
3001 import
= method_aux
->dllentry
;
3002 scope
= method_aux
->dll
;
3005 if (!import
|| !scope
) {
3006 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3011 if (piinfo
->implmap_idx
) {
3012 mono_metadata_decode_row (im
, piinfo
->implmap_idx
- 1, im_cols
, MONO_IMPLMAP_SIZE
);
3014 piinfo
->piflags
= im_cols
[MONO_IMPLMAP_FLAGS
];
3015 import
= mono_metadata_string_heap (image
, im_cols
[MONO_IMPLMAP_NAME
]);
3016 scope_token
= mono_metadata_decode_row_col (mr
, im_cols
[MONO_IMPLMAP_SCOPE
] - 1, MONO_MODULEREF_NAME
);
3017 scope
= mono_metadata_string_heap (image
, scope_token
);
3021 *flags
= piinfo
->piflags
;
3022 *entry_point
= mono_string_new (domain
, import
);
3023 *dll_name
= mono_string_new (domain
, scope
);
3026 ICALL_EXPORT MonoReflectionMethod
*
3027 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod
*method
)
3029 MonoMethodInflated
*imethod
;
3031 MonoReflectionMethod
*ret
= NULL
;
3034 if (method
->method
->is_generic
)
3037 if (!method
->method
->is_inflated
)
3040 imethod
= (MonoMethodInflated
*) method
->method
;
3042 result
= imethod
->declaring
;
3043 /* Not a generic method. */
3044 if (!result
->is_generic
)
3047 if (image_is_dynamic (method
->method
->klass
->image
)) {
3048 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->method
->klass
->image
;
3049 MonoReflectionMethod
*res
;
3052 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3053 * the dynamic case as well ?
3055 mono_image_lock ((MonoImage
*)image
);
3056 res
= (MonoReflectionMethod
*)mono_g_hash_table_lookup (image
->generic_def_objects
, imethod
);
3057 mono_image_unlock ((MonoImage
*)image
);
3063 if (imethod
->context
.class_inst
) {
3064 MonoClass
*klass
= ((MonoMethod
*) imethod
)->klass
;
3065 /*Generic methods gets the context of the GTD.*/
3066 if (mono_class_get_context (klass
)) {
3067 result
= mono_class_inflate_generic_method_full_checked (result
, klass
, mono_class_get_context (klass
), &error
);
3068 if (!mono_error_ok (&error
))
3073 ret
= mono_method_get_object_checked (mono_object_domain (method
), result
, NULL
, &error
);
3075 if (!mono_error_ok (&error
))
3076 mono_error_set_pending_exception (&error
);
3080 ICALL_EXPORT gboolean
3081 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod
*method
)
3083 return mono_method_signature (method
->method
)->generic_param_count
!= 0;
3086 ICALL_EXPORT gboolean
3087 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod
*method
)
3089 return method
->method
->is_generic
;
3092 ICALL_EXPORT MonoArray
*
3093 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod
*method
)
3096 MonoReflectionType
*rt
;
3101 domain
= mono_object_domain (method
);
3103 if (method
->method
->is_inflated
) {
3104 MonoGenericInst
*inst
= mono_method_get_context (method
->method
)->method_inst
;
3107 count
= inst
->type_argc
;
3108 res
= mono_array_new_checked (domain
, mono_defaults
.systemtype_class
, count
, &error
);
3109 if (mono_error_set_pending_exception (&error
))
3112 for (i
= 0; i
< count
; i
++) {
3113 rt
= mono_type_get_object_checked (domain
, inst
->type_argv
[i
], &error
);
3114 if (mono_error_set_pending_exception (&error
))
3117 mono_array_setref (res
, i
, rt
);
3124 count
= mono_method_signature (method
->method
)->generic_param_count
;
3125 res
= mono_array_new_checked (domain
, mono_defaults
.systemtype_class
, count
, &error
);
3126 if (mono_error_set_pending_exception (&error
))
3129 for (i
= 0; i
< count
; i
++) {
3130 MonoGenericContainer
*container
= mono_method_get_generic_container (method
->method
);
3131 MonoGenericParam
*param
= mono_generic_container_get_param (container
, i
);
3132 MonoClass
*pklass
= mono_class_from_generic_parameter_internal (param
);
3134 rt
= mono_type_get_object_checked (domain
, &pklass
->byval_arg
, &error
);
3135 if (mono_error_set_pending_exception (&error
))
3138 mono_array_setref (res
, i
, rt
);
3144 ICALL_EXPORT MonoObject
*
3145 ves_icall_InternalInvoke (MonoReflectionMethod
*method
, MonoObject
*this_arg
, MonoArray
*params
, MonoException
**exc
)
3149 * Invoke from reflection is supposed to always be a virtual call (the API
3150 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3151 * greater flexibility.
3153 MonoMethod
*m
= method
->method
;
3154 MonoMethodSignature
*sig
= mono_method_signature (m
);
3157 void *obj
= this_arg
;
3161 if (mono_security_core_clr_enabled () &&
3162 !mono_security_core_clr_ensure_reflection_access_method (m
, &error
)) {
3163 mono_error_set_pending_exception (&error
);
3167 if (!(m
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
3168 if (!mono_class_vtable_full (mono_object_domain (method
), m
->klass
, &error
)) {
3169 mono_error_cleanup (&error
); /* FIXME does this make sense? */
3170 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_class_get_exception_for_failure (m
->klass
));
3175 if (!mono_object_isinst_checked (this_arg
, m
->klass
, &error
)) {
3176 if (!is_ok (&error
)) {
3177 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_error_convert_to_exception (&error
));
3180 char *this_name
= mono_type_get_full_name (mono_object_get_class (this_arg
));
3181 char *target_name
= mono_type_get_full_name (m
->klass
);
3182 char *msg
= g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name
, target_name
);
3183 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", msg
));
3185 g_free (target_name
);
3189 m
= mono_object_get_virtual_method (this_arg
, m
);
3190 /* must pass the pointer to the value for valuetype methods */
3191 if (m
->klass
->valuetype
)
3192 obj
= mono_object_unbox (this_arg
);
3193 } else if (strcmp (m
->name
, ".ctor") && !m
->wrapper_type
) {
3194 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Non-static method requires a target."));
3199 if (sig
->ret
->byref
) {
3200 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"));
3204 pcount
= params
? mono_array_length (params
): 0;
3205 if (pcount
!= sig
->param_count
) {
3206 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name (mono_defaults
.corlib
, "System.Reflection", "TargetParameterCountException"));
3210 if ((m
->klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
) && !strcmp (m
->name
, ".ctor") && !this_arg
) {
3211 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."));
3215 image
= m
->klass
->image
;
3216 if (image
->assembly
->ref_only
) {
3217 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."));
3221 if (image_is_dynamic (image
) && !((MonoDynamicImage
*)image
)->run
) {
3222 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3226 if (m
->klass
->rank
&& !strcmp (m
->name
, ".ctor")) {
3230 intptr_t *lower_bounds
;
3231 pcount
= mono_array_length (params
);
3232 lengths
= (uintptr_t *)alloca (sizeof (uintptr_t) * pcount
);
3233 /* Note: the synthetized array .ctors have int32 as argument type */
3234 for (i
= 0; i
< pcount
; ++i
)
3235 lengths
[i
] = *(int32_t*) ((char*)mono_array_get (params
, gpointer
, i
) + sizeof (MonoObject
));
3237 if (m
->klass
->rank
== 1 && sig
->param_count
== 2 && m
->klass
->element_class
->rank
) {
3238 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3239 arr
= mono_array_new_full_checked (mono_object_domain (params
), m
->klass
, lengths
, NULL
, &error
);
3240 if (!mono_error_ok (&error
)) {
3241 mono_error_set_pending_exception (&error
);
3245 for (i
= 0; i
< mono_array_length (arr
); ++i
) {
3246 MonoArray
*subarray
= mono_array_new_full_checked (mono_object_domain (params
), m
->klass
->element_class
, &lengths
[1], NULL
, &error
);
3247 if (!mono_error_ok (&error
)) {
3248 mono_error_set_pending_exception (&error
);
3251 mono_array_setref_fast (arr
, i
, subarray
);
3253 return (MonoObject
*)arr
;
3256 if (m
->klass
->rank
== pcount
) {
3257 /* Only lengths provided. */
3258 arr
= mono_array_new_full_checked (mono_object_domain (params
), m
->klass
, lengths
, NULL
, &error
);
3259 if (!mono_error_ok (&error
)) {
3260 mono_error_set_pending_exception (&error
);
3264 return (MonoObject
*)arr
;
3266 g_assert (pcount
== (m
->klass
->rank
* 2));
3267 /* The arguments are lower-bound-length pairs */
3268 lower_bounds
= (intptr_t *)g_alloca (sizeof (intptr_t) * pcount
);
3270 for (i
= 0; i
< pcount
/ 2; ++i
) {
3271 lower_bounds
[i
] = *(int32_t*) ((char*)mono_array_get (params
, gpointer
, (i
* 2)) + sizeof (MonoObject
));
3272 lengths
[i
] = *(int32_t*) ((char*)mono_array_get (params
, gpointer
, (i
* 2) + 1) + sizeof (MonoObject
));
3275 arr
= mono_array_new_full_checked (mono_object_domain (params
), m
->klass
, lengths
, lower_bounds
, &error
);
3276 if (!mono_error_ok (&error
)) {
3277 mono_error_set_pending_exception (&error
);
3281 return (MonoObject
*)arr
;
3284 MonoObject
*result
= mono_runtime_invoke_array_checked (m
, obj
, params
, &error
);
3285 mono_error_set_pending_exception (&error
);
3289 #ifndef DISABLE_REMOTING
3290 ICALL_EXPORT MonoObject
*
3291 ves_icall_InternalExecute (MonoReflectionMethod
*method
, MonoObject
*this_arg
, MonoArray
*params
, MonoArray
**outArgs
)
3294 MonoDomain
*domain
= mono_object_domain (method
);
3295 MonoMethod
*m
= method
->method
;
3296 MonoMethodSignature
*sig
= mono_method_signature (m
);
3297 MonoArray
*out_args
;
3299 int i
, j
, outarg_count
= 0;
3301 if (m
->klass
== mono_defaults
.object_class
) {
3302 if (!strcmp (m
->name
, "FieldGetter")) {
3303 MonoClass
*k
= this_arg
->vtable
->klass
;
3307 /* If this is a proxy, then it must be a CBO */
3308 if (k
== mono_defaults
.transparent_proxy_class
) {
3309 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this_arg
;
3310 this_arg
= tp
->rp
->unwrapped_server
;
3311 g_assert (this_arg
);
3312 k
= this_arg
->vtable
->klass
;
3315 name
= mono_array_get (params
, MonoString
*, 1);
3316 str
= mono_string_to_utf8_checked (name
, &error
);
3317 if (mono_error_set_pending_exception (&error
))
3321 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
3324 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
3325 if (field_klass
->valuetype
) {
3326 result
= mono_value_box_checked (domain
, field_klass
, (char *)this_arg
+ field
->offset
, &error
);
3327 if (mono_error_set_pending_exception (&error
))
3330 result
= (MonoObject
*)*((gpointer
*)((char *)this_arg
+ field
->offset
));
3332 out_args
= mono_array_new_checked (domain
, mono_defaults
.object_class
, 1, &error
);
3333 if (mono_error_set_pending_exception (&error
))
3335 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
3336 mono_array_setref (out_args
, 0, result
);
3343 g_assert_not_reached ();
3345 } else if (!strcmp (m
->name
, "FieldSetter")) {
3346 MonoClass
*k
= this_arg
->vtable
->klass
;
3352 /* If this is a proxy, then it must be a CBO */
3353 if (k
== mono_defaults
.transparent_proxy_class
) {
3354 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this_arg
;
3355 this_arg
= tp
->rp
->unwrapped_server
;
3356 g_assert (this_arg
);
3357 k
= this_arg
->vtable
->klass
;
3360 name
= mono_array_get (params
, MonoString
*, 1);
3361 str
= mono_string_to_utf8_checked (name
, &error
);
3362 if (mono_error_set_pending_exception (&error
))
3366 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
3369 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
3370 MonoObject
*val
= (MonoObject
*)mono_array_get (params
, gpointer
, 2);
3372 if (field_klass
->valuetype
) {
3373 size
= mono_type_size (field
->type
, &align
);
3374 g_assert (size
== mono_class_value_size (field_klass
, NULL
));
3375 mono_gc_wbarrier_value_copy ((char *)this_arg
+ field
->offset
, (char*)val
+ sizeof (MonoObject
), 1, field_klass
);
3377 mono_gc_wbarrier_set_field (this_arg
, (char*)this_arg
+ field
->offset
, val
);
3380 out_args
= mono_array_new_checked (domain
, mono_defaults
.object_class
, 0, &error
);
3381 if (mono_error_set_pending_exception (&error
))
3383 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
3392 g_assert_not_reached ();
3397 for (i
= 0; i
< mono_array_length (params
); i
++) {
3398 if (sig
->params
[i
]->byref
)
3402 out_args
= mono_array_new_checked (domain
, mono_defaults
.object_class
, outarg_count
, &error
);
3403 if (mono_error_set_pending_exception (&error
))
3406 /* handle constructors only for objects already allocated */
3407 if (!strcmp (method
->method
->name
, ".ctor"))
3408 g_assert (this_arg
);
3410 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3411 g_assert (!method
->method
->klass
->valuetype
);
3412 result
= mono_runtime_invoke_array_checked (method
->method
, this_arg
, params
, &error
);
3413 if (mono_error_set_pending_exception (&error
))
3416 for (i
= 0, j
= 0; i
< mono_array_length (params
); i
++) {
3417 if (sig
->params
[i
]->byref
) {
3419 arg
= mono_array_get (params
, gpointer
, i
);
3420 mono_array_setref (out_args
, j
, arg
);
3425 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
3432 read_enum_value (const char *mem
, int type
)
3435 case MONO_TYPE_BOOLEAN
:
3437 return *(guint8
*)mem
;
3439 return *(gint8
*)mem
;
3440 case MONO_TYPE_CHAR
:
3442 return read16 (mem
);
3444 return (gint16
) read16 (mem
);
3446 return read32 (mem
);
3448 return (gint32
) read32 (mem
);
3451 return read64 (mem
);
3453 g_assert_not_reached ();
3459 write_enum_value (char *mem
, int type
, guint64 value
)
3463 case MONO_TYPE_I1
: {
3464 guint8
*p
= (guint8
*)mem
;
3470 case MONO_TYPE_CHAR
: {
3471 guint16
*p
= (guint16
*)mem
;
3476 case MONO_TYPE_I4
: {
3477 guint32
*p
= (guint32
*)mem
;
3482 case MONO_TYPE_I8
: {
3483 guint64
*p
= (guint64
*)mem
;
3488 g_assert_not_reached ();
3493 ICALL_EXPORT MonoObject
*
3494 ves_icall_System_Enum_ToObject (MonoReflectionType
*enumType
, guint64 value
)
3502 domain
= mono_object_domain (enumType
);
3503 enumc
= mono_class_from_mono_type (enumType
->type
);
3505 mono_class_init_checked (enumc
, &error
);
3506 if (mono_error_set_pending_exception (&error
))
3509 etype
= mono_class_enum_basetype (enumc
);
3511 res
= mono_object_new_checked (domain
, enumc
, &error
);
3512 if (mono_error_set_pending_exception (&error
))
3514 write_enum_value ((char *)res
+ sizeof (MonoObject
), etype
->type
, value
);
3519 ICALL_EXPORT MonoBoolean
3520 ves_icall_System_Enum_InternalHasFlag (MonoObject
*a
, MonoObject
*b
)
3522 int size
= mono_class_value_size (a
->vtable
->klass
, NULL
);
3523 guint64 a_val
= 0, b_val
= 0;
3525 memcpy (&a_val
, mono_object_unbox (a
), size
);
3526 memcpy (&b_val
, mono_object_unbox (b
), size
);
3528 return (a_val
& b_val
) == b_val
;
3531 ICALL_EXPORT MonoObject
*
3532 ves_icall_System_Enum_get_value (MonoObject
*eobj
)
3544 g_assert (eobj
->vtable
->klass
->enumtype
);
3546 enumc
= mono_class_from_mono_type (mono_class_enum_basetype (eobj
->vtable
->klass
));
3547 res
= mono_object_new_checked (mono_object_domain (eobj
), enumc
, &error
);
3548 if (mono_error_set_pending_exception (&error
))
3550 dst
= (char *)res
+ sizeof (MonoObject
);
3551 src
= (char *)eobj
+ sizeof (MonoObject
);
3552 size
= mono_class_value_size (enumc
, NULL
);
3554 memcpy (dst
, src
, size
);
3559 ICALL_EXPORT MonoReflectionType
*
3560 ves_icall_System_Enum_get_underlying_type (MonoReflectionType
*type
)
3563 MonoReflectionType
*ret
;
3567 klass
= mono_class_from_mono_type (type
->type
);
3568 mono_class_init_checked (klass
, &error
);
3569 if (mono_error_set_pending_exception (&error
))
3572 etype
= mono_class_enum_basetype (klass
);
3574 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3578 ret
= mono_type_get_object_checked (mono_object_domain (type
), etype
, &error
);
3579 mono_error_set_pending_exception (&error
);
3585 ves_icall_System_Enum_compare_value_to (MonoObject
*eobj
, MonoObject
*other
)
3587 gpointer tdata
= (char *)eobj
+ sizeof (MonoObject
);
3588 gpointer odata
= (char *)other
+ sizeof (MonoObject
);
3589 MonoType
*basetype
= mono_class_enum_basetype (eobj
->vtable
->klass
);
3590 g_assert (basetype
);
3595 if (eobj
->vtable
->klass
!= other
->vtable
->klass
)
3598 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3599 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3600 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3603 return me > other ? 1 : -1; \
3606 switch (basetype
->type
) {
3608 COMPARE_ENUM_VALUES (guint8
);
3610 COMPARE_ENUM_VALUES (gint8
);
3611 case MONO_TYPE_CHAR
:
3613 COMPARE_ENUM_VALUES (guint16
);
3615 COMPARE_ENUM_VALUES (gint16
);
3617 COMPARE_ENUM_VALUES (guint32
);
3619 COMPARE_ENUM_VALUES (gint32
);
3621 COMPARE_ENUM_VALUES (guint64
);
3623 COMPARE_ENUM_VALUES (gint64
);
3627 #undef COMPARE_ENUM_VALUES
3628 /* indicates that the enum was of an unsupported unerlying type */
3633 ves_icall_System_Enum_get_hashcode (MonoObject
*eobj
)
3635 gpointer data
= (char *)eobj
+ sizeof (MonoObject
);
3636 MonoType
*basetype
= mono_class_enum_basetype (eobj
->vtable
->klass
);
3637 g_assert (basetype
);
3639 switch (basetype
->type
) {
3640 case MONO_TYPE_I1
: {
3641 gint8 value
= *((gint8
*)data
);
3642 return ((int)value
^ (int)value
<< 8);
3645 return *((guint8
*)data
);
3646 case MONO_TYPE_CHAR
:
3648 return *((guint16
*)data
);
3650 case MONO_TYPE_I2
: {
3651 gint16 value
= *((gint16
*)data
);
3652 return ((int)(guint16
)value
| (((int)value
) << 16));
3655 return *((guint32
*)data
);
3657 return *((gint32
*)data
);
3659 case MONO_TYPE_I8
: {
3660 gint64 value
= *((gint64
*)data
);
3661 return (gint
)(value
& 0xffffffff) ^ (int)(value
>> 32);
3664 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3669 ICALL_EXPORT MonoBoolean
3670 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType
*type
, MonoArray
**values
, MonoArray
**names
)
3673 MonoDomain
*domain
= mono_object_domain (type
);
3674 MonoClass
*enumc
= mono_class_from_mono_type (type
->type
);
3675 guint j
= 0, nvalues
;
3677 MonoClassField
*field
;
3679 guint64 field_value
, previous_value
= 0;
3680 gboolean sorted
= TRUE
;
3682 mono_class_init_checked (enumc
, &error
);
3683 if (mono_error_set_pending_exception (&error
))
3687 if (!enumc
->enumtype
) {
3688 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3692 base_type
= mono_class_enum_basetype (enumc
)->type
;
3694 nvalues
= mono_class_num_fields (enumc
) ? mono_class_num_fields (enumc
) - 1 : 0;
3695 *names
= mono_array_new_checked (domain
, mono_defaults
.string_class
, nvalues
, &error
);
3696 if (mono_error_set_pending_exception (&error
))
3698 *values
= mono_array_new_checked (domain
, mono_defaults
.uint64_class
, nvalues
, &error
);
3699 if (mono_error_set_pending_exception (&error
))
3703 while ((field
= mono_class_get_fields (enumc
, &iter
))) {
3705 MonoTypeEnum def_type
;
3707 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
3709 if (strcmp ("value__", mono_field_get_name (field
)) == 0)
3711 if (mono_field_is_deleted (field
))
3713 mono_array_setref (*names
, j
, mono_string_new (domain
, mono_field_get_name (field
)));
3715 p
= mono_class_get_field_default_value (field
, &def_type
);
3716 /* len = */ mono_metadata_decode_blob_size (p
, &p
);
3718 field_value
= read_enum_value (p
, base_type
);
3719 mono_array_set (*values
, guint64
, j
, field_value
);
3721 if (previous_value
> field_value
)
3724 previous_value
= field_value
;
3732 BFLAGS_IgnoreCase
= 1,
3733 BFLAGS_DeclaredOnly
= 2,
3734 BFLAGS_Instance
= 4,
3736 BFLAGS_Public
= 0x10,
3737 BFLAGS_NonPublic
= 0x20,
3738 BFLAGS_FlattenHierarchy
= 0x40,
3739 BFLAGS_InvokeMethod
= 0x100,
3740 BFLAGS_CreateInstance
= 0x200,
3741 BFLAGS_GetField
= 0x400,
3742 BFLAGS_SetField
= 0x800,
3743 BFLAGS_GetProperty
= 0x1000,
3744 BFLAGS_SetProperty
= 0x2000,
3745 BFLAGS_ExactBinding
= 0x10000,
3746 BFLAGS_SuppressChangeType
= 0x20000,
3747 BFLAGS_OptionalParamBinding
= 0x40000
3750 ICALL_EXPORT GPtrArray
*
3751 ves_icall_RuntimeType_GetFields_native (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3755 MonoClass
*startklass
, *klass
;
3758 char *utf8_name
= NULL
;
3759 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3760 MonoClassField
*field
;
3762 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3763 if (type
->type
->byref
) {
3764 return g_ptr_array_new ();
3767 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3769 GPtrArray
*ptr_array
= g_ptr_array_sized_new (16);
3772 if (mono_class_has_failure (klass
)) {
3773 mono_error_init (&error
);
3774 mono_error_set_for_class_failure (&error
, klass
);
3779 while ((field
= mono_class_get_fields_lazy (klass
, &iter
))) {
3780 guint32 flags
= mono_field_get_flags (field
);
3782 if (mono_field_is_deleted_with_flags (field
, flags
))
3784 if ((flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3785 if (bflags
& BFLAGS_Public
)
3787 } else if ((klass
== startklass
) || (flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3788 if (bflags
& BFLAGS_NonPublic
) {
3795 if (flags
& FIELD_ATTRIBUTE_STATIC
) {
3796 if (bflags
& BFLAGS_Static
)
3797 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3800 if (bflags
& BFLAGS_Instance
)
3808 if (utf8_name
== NULL
) {
3809 utf8_name
= mono_string_to_utf8_checked (name
, &error
);
3810 if (!is_ok (&error
))
3812 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
3815 if (compare_func (mono_field_get_name (field
), utf8_name
))
3819 g_ptr_array_add (ptr_array
, field
);
3821 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3824 if (utf8_name
!= NULL
)
3829 g_ptr_array_free (ptr_array
, FALSE
);
3830 mono_error_set_pending_exception (&error
);
3835 method_nonpublic (MonoMethod
* method
, gboolean start_klass
)
3837 switch (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) {
3838 case METHOD_ATTRIBUTE_ASSEM
:
3839 return (start_klass
|| mono_defaults
.generic_ilist_class
);
3840 case METHOD_ATTRIBUTE_PRIVATE
:
3842 case METHOD_ATTRIBUTE_PUBLIC
:
3850 mono_class_get_methods_by_name (MonoClass
*klass
, const char *name
, guint32 bflags
, gboolean ignore_case
, gboolean allow_ctors
, MonoException
**ex
)
3853 MonoClass
*startklass
;
3857 /*FIXME, use MonoBitSet*/
3858 guint32 method_slots_default
[8];
3859 guint32
*method_slots
= NULL
;
3860 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3862 array
= g_ptr_array_new ();
3867 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3869 /* An optimization for calls made from Delegate:CreateDelegate () */
3870 if (klass
->delegate
&& name
&& !strcmp (name
, "Invoke") && (bflags
== (BFLAGS_Public
| BFLAGS_Static
| BFLAGS_Instance
))) {
3871 method
= mono_get_delegate_invoke (klass
);
3874 g_ptr_array_add (array
, method
);
3878 mono_class_setup_methods (klass
);
3879 mono_class_setup_vtable (klass
);
3880 if (mono_class_has_failure (klass
))
3883 if (is_generic_parameter (&klass
->byval_arg
))
3884 nslots
= mono_class_get_vtable_size (klass
->parent
);
3886 nslots
= MONO_CLASS_IS_INTERFACE (klass
) ? mono_class_num_methods (klass
) : mono_class_get_vtable_size (klass
);
3887 if (nslots
>= sizeof (method_slots_default
) * 8) {
3888 method_slots
= g_new0 (guint32
, nslots
/ 32 + 1);
3890 method_slots
= method_slots_default
;
3891 memset (method_slots
, 0, sizeof (method_slots_default
));
3894 mono_class_setup_methods (klass
);
3895 mono_class_setup_vtable (klass
);
3896 if (mono_class_has_failure (klass
))
3900 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3902 if (method
->slot
!= -1) {
3903 g_assert (method
->slot
< nslots
);
3904 if (method_slots
[method
->slot
>> 5] & (1 << (method
->slot
& 0x1f)))
3906 if (!(method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
))
3907 method_slots
[method
->slot
>> 5] |= 1 << (method
->slot
& 0x1f);
3910 if (!allow_ctors
&& method
->name
[0] == '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0))
3912 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3913 if (bflags
& BFLAGS_Public
)
3915 } else if ((bflags
& BFLAGS_NonPublic
) && method_nonpublic (method
, (klass
== startklass
))) {
3921 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3922 if (bflags
& BFLAGS_Static
)
3923 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3926 if (bflags
& BFLAGS_Instance
)
3934 if (compare_func (name
, method
->name
))
3939 g_ptr_array_add (array
, method
);
3941 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3943 if (method_slots
!= method_slots_default
)
3944 g_free (method_slots
);
3949 if (method_slots
!= method_slots_default
)
3950 g_free (method_slots
);
3951 g_ptr_array_free (array
, TRUE
);
3953 if (mono_class_has_failure (klass
)) {
3954 *ex
= mono_class_get_exception_for_failure (klass
);
3956 *ex
= mono_get_exception_execution_engine ("Unknown error");
3961 ICALL_EXPORT MonoArray
*
3962 ves_icall_RuntimeType_GetMethodsByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3964 static MonoClass
*MethodInfo_array
;
3968 MonoVTable
*array_vtable
;
3969 MonoException
*ex
= NULL
;
3970 const char *mname
= NULL
;
3971 GPtrArray
*method_array
;
3972 MonoClass
*klass
, *refklass
;
3975 mono_error_init (&error
);
3977 if (!MethodInfo_array
) {
3978 MonoClass
*klass
= mono_array_class_get (mono_defaults
.method_info_class
, 1);
3979 mono_memory_barrier ();
3980 MethodInfo_array
= klass
;
3983 klass
= mono_class_from_mono_type (type
->type
);
3984 refklass
= mono_class_from_mono_type (reftype
->type
);
3985 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3986 array_vtable
= mono_class_vtable_full (domain
, MethodInfo_array
, &error
);
3987 if (!is_ok (&error
)) {
3988 mono_error_set_pending_exception (&error
);
3991 if (type
->type
->byref
) {
3992 res
= mono_array_new_specific_checked (array_vtable
, 0, &error
);
3993 mono_error_set_pending_exception (&error
);
3999 mname
= mono_string_to_utf8_checked (name
, &error
);
4000 if (mono_error_set_pending_exception (&error
))
4004 method_array
= mono_class_get_methods_by_name (klass
, mname
, bflags
, ignore_case
, FALSE
, &ex
);
4005 g_free ((char*)mname
);
4007 mono_set_pending_exception (ex
);
4011 res
= mono_array_new_specific_checked (array_vtable
, method_array
->len
, &error
);
4012 if (!mono_error_ok (&error
)) {
4013 mono_error_set_pending_exception (&error
);
4017 for (i
= 0; i
< method_array
->len
; ++i
) {
4018 MonoMethod
*method
= (MonoMethod
*)g_ptr_array_index (method_array
, i
);
4019 MonoReflectionMethod
*rm
= mono_method_get_object_checked (domain
, method
, refklass
, &error
);
4020 if (!mono_error_ok (&error
))
4022 mono_array_setref (res
, i
, rm
);
4026 g_ptr_array_free (method_array
, TRUE
);
4027 if (!mono_error_ok (&error
))
4028 mono_set_pending_exception (mono_error_convert_to_exception (&error
));
4032 ICALL_EXPORT MonoArray
*
4033 ves_icall_RuntimeType_GetConstructors_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
4036 MonoClass
*startklass
, *klass
, *refklass
;
4037 MonoArray
*res
= NULL
;
4041 gpointer iter
= NULL
;
4042 MonoPtrArray tmp_array
;
4045 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4046 if (type
->type
->byref
) {
4047 res
= mono_array_new_cached (domain
, mono_defaults
.method_info_class
, 0, &error
);
4048 mono_error_set_pending_exception (&error
);
4052 mono_ptr_array_init (tmp_array
, 4, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection constructors list"); /*FIXME, guestimating*/
4055 klass
= startklass
= mono_class_from_mono_type (type
->type
);
4056 refklass
= mono_class_from_mono_type (reftype
->type
);
4058 mono_class_setup_methods (klass
);
4059 if (mono_class_has_failure (klass
)) {
4060 mono_set_pending_exception (mono_class_get_exception_for_failure (klass
));
4065 while ((method
= mono_class_get_methods (klass
, &iter
))) {
4067 if (strcmp (method
->name
, ".ctor") && strcmp (method
->name
, ".cctor"))
4069 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
4070 if (bflags
& BFLAGS_Public
)
4073 if (bflags
& BFLAGS_NonPublic
)
4079 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
4080 if (bflags
& BFLAGS_Static
)
4081 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
4084 if (bflags
& BFLAGS_Instance
)
4090 member
= (MonoObject
*)mono_method_get_object_checked (domain
, method
, refklass
, &error
);
4091 if (mono_error_set_pending_exception (&error
))
4094 mono_ptr_array_append (tmp_array
, member
);
4097 res
= mono_array_new_cached (domain
, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array
), &error
);
4098 if (mono_error_set_pending_exception (&error
))
4101 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4102 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4105 mono_ptr_array_destroy (tmp_array
);
4111 property_hash (gconstpointer data
)
4113 MonoProperty
*prop
= (MonoProperty
*)data
;
4115 return g_str_hash (prop
->name
);
4119 property_accessor_override (MonoMethod
*method1
, MonoMethod
*method2
)
4121 if (method1
->slot
!= -1 && method1
->slot
== method2
->slot
)
4124 if (mono_class_get_generic_type_definition (method1
->klass
) == mono_class_get_generic_type_definition (method2
->klass
)) {
4125 if (method1
->is_inflated
)
4126 method1
= ((MonoMethodInflated
*) method1
)->declaring
;
4127 if (method2
->is_inflated
)
4128 method2
= ((MonoMethodInflated
*) method2
)->declaring
;
4131 return mono_metadata_signature_equal (mono_method_signature (method1
), mono_method_signature (method2
));
4135 property_equal (MonoProperty
*prop1
, MonoProperty
*prop2
)
4137 // Properties are hide-by-name-and-signature
4138 if (!g_str_equal (prop1
->name
, prop2
->name
))
4141 /* If we see a property in a generic method, we want to
4142 compare the generic signatures, not the inflated signatures
4143 because we might conflate two properties that were
4147 public T this[T t] { getter { return t; } } // method 1
4148 public U this[U u] { getter { return u; } } // method 2
4151 If we see int Foo<int,int>::Item[int] we need to know if
4152 the indexer came from method 1 or from method 2, and we
4153 shouldn't conflate them. (Bugzilla 36283)
4155 if (prop1
->get
&& prop2
->get
&& !property_accessor_override (prop1
->get
, prop2
->get
))
4158 if (prop1
->set
&& prop2
->set
&& !property_accessor_override (prop1
->set
, prop2
->set
))
4165 property_accessor_nonpublic (MonoMethod
* accessor
, gboolean start_klass
)
4170 return method_nonpublic (accessor
, start_klass
);
4173 ICALL_EXPORT MonoArray
*
4174 ves_icall_RuntimeType_GetPropertiesByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
4178 MonoClass
*startklass
, *klass
;
4184 gchar
*propname
= NULL
;
4185 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
4187 GHashTable
*properties
= NULL
;
4188 MonoPtrArray tmp_array
;
4190 mono_error_init (&error
);
4192 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4193 if (type
->type
->byref
) {
4194 res
= mono_array_new_cached (domain
, mono_class_get_property_info_class (), 0, &error
);
4195 mono_error_set_pending_exception (&error
);
4199 mono_ptr_array_init (tmp_array
, 8, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4201 klass
= startklass
= mono_class_from_mono_type (type
->type
);
4204 propname
= mono_string_to_utf8_checked (name
, &error
);
4205 if (mono_error_set_pending_exception (&error
))
4207 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
4210 properties
= g_hash_table_new (property_hash
, (GEqualFunc
)property_equal
);
4212 mono_class_setup_methods (klass
);
4213 mono_class_setup_vtable (klass
);
4214 if (mono_class_has_failure (klass
))
4218 while ((prop
= mono_class_get_properties (klass
, &iter
))) {
4224 flags
= method
->flags
;
4227 if ((prop
->get
&& ((prop
->get
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
)) ||
4228 (prop
->set
&& ((prop
->set
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
))) {
4229 if (bflags
& BFLAGS_Public
)
4231 } else if (bflags
& BFLAGS_NonPublic
) {
4232 if (property_accessor_nonpublic(prop
->get
, startklass
== klass
) ||
4233 property_accessor_nonpublic(prop
->set
, startklass
== klass
)) {
4240 if (flags
& METHOD_ATTRIBUTE_STATIC
) {
4241 if (bflags
& BFLAGS_Static
)
4242 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
4245 if (bflags
& BFLAGS_Instance
)
4254 if (compare_func (propname
, prop
->name
))
4258 if (g_hash_table_lookup (properties
, prop
))
4261 MonoReflectionProperty
*pr
= mono_property_get_object_checked (domain
, startklass
, prop
, &error
);
4264 mono_ptr_array_append (tmp_array
, pr
);
4266 g_hash_table_insert (properties
, prop
, prop
);
4268 if ((!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
)))
4271 g_hash_table_destroy (properties
);
4274 res
= mono_array_new_cached (domain
, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array
), &error
);
4275 if (!is_ok (&error
))
4277 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4278 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4280 mono_ptr_array_destroy (tmp_array
);
4287 if (mono_class_has_failure (klass
))
4288 mono_error_set_for_class_failure (&error
, klass
);
4292 g_hash_table_destroy (properties
);
4295 mono_ptr_array_destroy (tmp_array
);
4297 mono_error_set_pending_exception (&error
);
4303 event_hash (gconstpointer data
)
4305 MonoEvent
*event
= (MonoEvent
*)data
;
4307 return g_str_hash (event
->name
);
4311 event_equal (MonoEvent
*event1
, MonoEvent
*event2
)
4313 // Events are hide-by-name
4314 return g_str_equal (event1
->name
, event2
->name
);
4317 ICALL_EXPORT MonoArray
*
4318 ves_icall_RuntimeType_GetEvents_internal (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoReflectionType
*reftype
)
4322 MonoClass
*startklass
, *klass
;
4328 char *utf8_name
= NULL
;
4329 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
4330 GHashTable
*events
= NULL
;
4331 MonoPtrArray tmp_array
;
4333 mono_error_init (&error
);
4335 domain
= mono_object_domain (type
);
4336 if (type
->type
->byref
) {
4337 res
= mono_array_new_cached (domain
, mono_class_get_event_info_class (), 0, &error
);
4338 mono_error_set_pending_exception (&error
);
4342 mono_ptr_array_init (tmp_array
, 4, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection events list");
4344 klass
= startklass
= mono_class_from_mono_type (type
->type
);
4346 events
= g_hash_table_new (event_hash
, (GEqualFunc
)event_equal
);
4348 mono_class_setup_methods (klass
);
4349 mono_class_setup_vtable (klass
);
4350 if (mono_class_has_failure (klass
))
4354 while ((event
= mono_class_get_events (klass
, &iter
))) {
4356 method
= event
->add
;
4358 method
= event
->remove
;
4360 method
= event
->raise
;
4362 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
4363 if (bflags
& BFLAGS_Public
)
4365 } else if ((klass
== startklass
) || (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) {
4366 if (bflags
& BFLAGS_NonPublic
)
4371 if (bflags
& BFLAGS_NonPublic
)
4377 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
4378 if (bflags
& BFLAGS_Static
)
4379 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
4382 if (bflags
& BFLAGS_Instance
)
4387 if (bflags
& BFLAGS_Instance
)
4393 if (utf8_name
== NULL
) {
4394 utf8_name
= mono_string_to_utf8_checked (name
, &error
);
4395 if (!is_ok (&error
))
4397 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
4400 if (compare_func (event
->name
, utf8_name
))
4404 if (g_hash_table_lookup (events
, event
))
4407 MonoReflectionEvent
*ev_obj
;
4408 ev_obj
= mono_event_get_object_checked (domain
, startklass
, event
, &error
);
4411 mono_ptr_array_append (tmp_array
, ev_obj
);
4413 g_hash_table_insert (events
, event
, event
);
4415 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
4418 g_hash_table_destroy (events
);
4420 res
= mono_array_new_cached (domain
, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array
), &error
);
4421 if (!is_ok (&error
))
4424 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4425 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4427 mono_ptr_array_destroy (tmp_array
);
4429 if (utf8_name
!= NULL
)
4435 if (mono_class_has_failure (klass
))
4436 mono_error_set_for_class_failure (&error
, klass
);
4441 g_hash_table_destroy (events
);
4442 if (utf8_name
!= NULL
)
4445 mono_ptr_array_destroy (tmp_array
);
4447 mono_error_set_pending_exception (&error
);
4451 ICALL_EXPORT MonoArray
*
4452 ves_icall_RuntimeType_GetNestedTypes (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
4455 MonoReflectionType
*rt
;
4458 MonoArray
*res
= NULL
;
4463 MonoPtrArray tmp_array
;
4465 mono_error_init (&error
);
4467 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4468 if (type
->type
->byref
) {
4469 MonoArray
*result
= mono_array_new_cached (domain
, mono_defaults
.runtimetype_class
, 0, &error
);
4470 mono_error_set_pending_exception (&error
);
4473 klass
= mono_class_from_mono_type (type
->type
);
4476 * If a nested type is generic, return its generic type definition.
4477 * Note that this means that the return value is essentially the set
4478 * of nested types of the generic type definition of @klass.
4480 * A note in MSDN claims that a generic type definition can have
4481 * nested types that aren't generic. In any case, the container of that
4482 * nested type would be the generic type definition.
4484 if (klass
->generic_class
)
4485 klass
= klass
->generic_class
->container_class
;
4487 mono_ptr_array_init (tmp_array
, 1, MONO_ROOT_SOURCE_REFLECTION
, "temporary reflection nested types list");
4489 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
4491 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
4492 if (bflags
& BFLAGS_Public
)
4495 if (bflags
& BFLAGS_NonPublic
)
4503 str
= mono_string_to_utf8_checked (name
, &error
);
4504 if (!is_ok (&error
))
4506 mono_identifier_unescape_type_name_chars (str
);
4509 if (strcmp (nested
->name
, str
))
4513 rt
= mono_type_get_object_checked (domain
, &nested
->byval_arg
, &error
);
4514 if (!is_ok (&error
))
4517 mono_ptr_array_append (tmp_array
, (MonoObject
*) rt
);
4520 res
= mono_array_new_cached (domain
, mono_defaults
.runtimetype_class
, mono_ptr_array_size (tmp_array
), &error
);
4521 if (!is_ok (&error
))
4524 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4525 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4528 mono_ptr_array_destroy (tmp_array
);
4532 mono_error_set_pending_exception (&error
);
4536 ICALL_EXPORT MonoReflectionType
*
4537 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly
*assembly
, MonoReflectionModule
*module
, MonoString
*name
, MonoBoolean throwOnError
, MonoBoolean ignoreCase
)
4540 MonoReflectionType
*ret
;
4542 MonoType
*type
= NULL
;
4543 MonoTypeNameParse info
;
4544 gboolean type_resolve
;
4546 /* On MS.NET, this does not fire a TypeResolve event */
4547 type_resolve
= TRUE
;
4548 str
= mono_string_to_utf8_checked (name
, &error
);
4549 if (mono_error_set_pending_exception (&error
))
4551 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4552 if (!mono_reflection_parse_type (str
, &info
)) {
4554 mono_reflection_free_type_info (&info
);
4556 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4559 /*g_print ("failed parse\n");*/
4563 if (info
.assembly
.name
) {
4565 mono_reflection_free_type_info (&info
);
4567 /* 1.0 and 2.0 throw different exceptions */
4568 if (mono_defaults
.generic_ilist_class
)
4569 mono_set_pending_exception (mono_get_exception_argument (NULL
, "Type names passed to Assembly.GetType() must not specify an assembly."));
4571 mono_set_pending_exception (mono_get_exception_type_load (name
, NULL
));
4577 if (module
!= NULL
) {
4578 if (module
->image
) {
4579 type
= mono_reflection_get_type_checked (module
->image
, module
->image
, &info
, ignoreCase
, &type_resolve
, &error
);
4580 if (!is_ok (&error
)) {
4582 mono_reflection_free_type_info (&info
);
4583 mono_error_set_pending_exception (&error
);
4590 if (assembly_is_dynamic (assembly
->assembly
)) {
4591 /* Enumerate all modules */
4592 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)assembly
;
4596 if (abuilder
->modules
) {
4597 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
4598 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
4599 type
= mono_reflection_get_type_checked (&mb
->dynamic_image
->image
, &mb
->dynamic_image
->image
, &info
, ignoreCase
, &type_resolve
, &error
);
4600 if (!is_ok (&error
)) {
4602 mono_reflection_free_type_info (&info
);
4603 mono_error_set_pending_exception (&error
);
4611 if (!type
&& abuilder
->loaded_modules
) {
4612 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
4613 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
4614 type
= mono_reflection_get_type_checked (mod
->image
, mod
->image
, &info
, ignoreCase
, &type_resolve
, &error
);
4615 if (!is_ok (&error
)) {
4617 mono_reflection_free_type_info (&info
);
4618 mono_error_set_pending_exception (&error
);
4627 type
= mono_reflection_get_type_checked (assembly
->assembly
->image
, assembly
->assembly
->image
, &info
, ignoreCase
, &type_resolve
, &error
);
4628 if (!is_ok (&error
)) {
4630 mono_reflection_free_type_info (&info
);
4631 mono_error_set_pending_exception (&error
);
4636 mono_reflection_free_type_info (&info
);
4638 MonoException
*e
= NULL
;
4641 e
= mono_get_exception_type_load (name
, NULL
);
4644 mono_set_pending_exception (e
);
4648 if (type
->type
== MONO_TYPE_CLASS
) {
4649 MonoClass
*klass
= mono_type_get_class (type
);
4651 /* need to report exceptions ? */
4652 if (throwOnError
&& mono_class_has_failure (klass
)) {
4653 /* report SecurityException (or others) that occured when loading the assembly */
4654 MonoException
*exc
= mono_class_get_exception_for_failure (klass
);
4655 mono_set_pending_exception (exc
);
4660 /* g_print ("got it\n"); */
4661 ret
= mono_type_get_object_checked (mono_object_domain (assembly
), type
, &error
);
4662 mono_error_set_pending_exception (&error
);
4668 replace_shadow_path (MonoDomain
*domain
, gchar
*dirname
, gchar
**filename
)
4671 gchar
*shadow_ini_file
;
4674 /* Check for shadow-copied assembly */
4675 if (mono_is_shadow_copy_enabled (domain
, dirname
)) {
4676 shadow_ini_file
= g_build_filename (dirname
, "__AssemblyInfo__.ini", NULL
);
4678 if (!g_file_get_contents (shadow_ini_file
, &content
, &len
, NULL
) ||
4679 !g_file_test (content
, G_FILE_TEST_IS_REGULAR
)) {
4685 g_free (shadow_ini_file
);
4686 if (content
!= NULL
) {
4689 *filename
= content
;
4696 ICALL_EXPORT MonoString
*
4697 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly
*assembly
, MonoBoolean escaped
)
4699 MonoDomain
*domain
= mono_object_domain (assembly
);
4700 MonoAssembly
*mass
= assembly
->assembly
;
4701 MonoString
*res
= NULL
;
4706 if (g_path_is_absolute (mass
->image
->name
)) {
4707 absolute
= g_strdup (mass
->image
->name
);
4708 dirname
= g_path_get_dirname (absolute
);
4710 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
4711 dirname
= g_strdup (mass
->basedir
);
4714 replace_shadow_path (domain
, dirname
, &absolute
);
4719 for (i
= strlen (absolute
) - 1; i
>= 0; i
--)
4720 if (absolute
[i
] == '\\')
4725 uri
= g_filename_to_uri (absolute
, NULL
, NULL
);
4727 const char *prepend
= "file://";
4729 if (*absolute
== '/' && *(absolute
+ 1) == '/') {
4732 prepend
= "file:///";
4735 uri
= g_strconcat (prepend
, absolute
, NULL
);
4739 res
= mono_string_new (domain
, uri
);
4746 ICALL_EXPORT MonoBoolean
4747 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly
*assembly
)
4749 MonoAssembly
*mass
= assembly
->assembly
;
4751 return mass
->in_gac
;
4754 ICALL_EXPORT MonoReflectionAssembly
*
4755 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString
*mname
, MonoObject
*evidence
)
4760 MonoImageOpenStatus status
;
4761 MonoReflectionAssembly
* result
= NULL
;
4763 name
= mono_string_to_utf8_checked (mname
, &error
);
4764 if (mono_error_set_pending_exception (&error
))
4766 res
= mono_assembly_load_with_partial_name (name
, &status
);
4772 result
= mono_assembly_get_object_checked (mono_domain_get (), res
, &error
);
4774 mono_error_set_pending_exception (&error
);
4778 ICALL_EXPORT MonoString
*
4779 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly
*assembly
)
4781 MonoDomain
*domain
= mono_object_domain (assembly
);
4784 res
= mono_string_new (domain
, mono_image_get_filename (assembly
->assembly
->image
));
4789 ICALL_EXPORT MonoBoolean
4790 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly
*assembly
)
4792 return assembly
->assembly
->ref_only
;
4795 ICALL_EXPORT MonoString
*
4796 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly
*assembly
)
4798 MonoDomain
*domain
= mono_object_domain (assembly
);
4800 return mono_string_new (domain
, assembly
->assembly
->image
->version
);
4803 ICALL_EXPORT MonoReflectionMethod
*
4804 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly
*assembly
)
4807 MonoReflectionMethod
*res
= NULL
;
4810 guint32 token
= mono_image_get_entry_point (assembly
->assembly
->image
);
4814 method
= mono_get_method_checked (assembly
->assembly
->image
, token
, NULL
, NULL
, &error
);
4815 if (!mono_error_ok (&error
))
4818 res
= mono_method_get_object_checked (mono_object_domain (assembly
), method
, NULL
, &error
);
4821 if (!mono_error_ok (&error
))
4822 mono_error_set_pending_exception (&error
);
4826 ICALL_EXPORT MonoReflectionModule
*
4827 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly
*assembly
)
4830 MonoReflectionModule
*result
= NULL
;
4831 result
= mono_module_get_object_checked (mono_object_domain (assembly
), assembly
->assembly
->image
, &error
);
4832 if (!mono_error_ok (&error
))
4833 mono_error_set_pending_exception (&error
);
4837 ICALL_EXPORT MonoArray
*
4838 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly
*assembly
)
4841 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4842 MonoArray
*result
= mono_array_new_checked (mono_object_domain (assembly
), mono_defaults
.string_class
, table
->rows
, &error
);
4843 if (mono_error_set_pending_exception (&error
))
4848 for (i
= 0; i
< table
->rows
; ++i
) {
4849 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_MANIFEST_NAME
));
4850 mono_array_setref (result
, i
, mono_string_new (mono_object_domain (assembly
), val
));
4855 ICALL_EXPORT MonoString
*
4856 ves_icall_System_Reflection_Assembly_GetAotId ()
4859 guint8 aotid_sum
= 0;
4860 MonoDomain
* domain
= mono_domain_get ();
4862 if (!domain
->entry_assembly
|| !domain
->entry_assembly
->image
)
4865 guint8 (*aotid
)[16] = &domain
->entry_assembly
->image
->aotid
;
4867 for (i
= 0; i
< 16; ++i
)
4868 aotid_sum
|= (*aotid
)[i
];
4873 return mono_string_new (domain
, mono_guid_to_string((guint8
*) aotid
));
4877 create_version (MonoDomain
*domain
, guint32 major
, guint32 minor
, guint32 build
, guint32 revision
, MonoError
*error
)
4879 static MonoMethod
*create_version
= NULL
;
4883 mono_error_init (error
);
4886 if (!create_version
) {
4887 MonoMethodDesc
*desc
= mono_method_desc_new (":.ctor(int,int,int,int)", FALSE
);
4888 create_version
= mono_method_desc_search_in_class (desc
, mono_class_get_system_version_class ());
4889 g_assert (create_version
);
4890 mono_method_desc_free (desc
);
4896 args
[3] = &revision
;
4897 result
= mono_object_new_checked (domain
, mono_class_get_system_version_class (), error
);
4898 return_val_if_nok (error
, NULL
);
4900 mono_runtime_invoke_checked (create_version
, result
, args
, error
);
4901 return_val_if_nok (error
, NULL
);
4906 ICALL_EXPORT MonoArray
*
4907 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly
*assembly
)
4911 MonoDomain
*domain
= mono_object_domain (assembly
);
4913 static MonoMethod
*create_culture
= NULL
;
4914 MonoImage
*image
= assembly
->assembly
->image
;
4918 t
= &assembly
->assembly
->image
->tables
[MONO_TABLE_ASSEMBLYREF
];
4921 result
= mono_array_new_checked (domain
, mono_class_get_assembly_name_class (), count
, &error
);
4922 if (mono_error_set_pending_exception (&error
))
4926 if (count
> 0 && !create_culture
) {
4927 MonoMethodDesc
*desc
= mono_method_desc_new (
4928 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4929 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4930 g_assert (create_culture
);
4931 mono_method_desc_free (desc
);
4934 for (i
= 0; i
< count
; i
++) {
4935 MonoObject
*version
;
4936 MonoReflectionAssemblyName
*aname
;
4937 guint32 cols
[MONO_ASSEMBLYREF_SIZE
];
4939 mono_metadata_decode_row (t
, i
, cols
, MONO_ASSEMBLYREF_SIZE
);
4941 aname
= (MonoReflectionAssemblyName
*) mono_object_new_checked (
4942 domain
, mono_class_get_assembly_name_class (), &error
);
4943 if (mono_error_set_pending_exception (&error
))
4946 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_NAME
])));
4948 aname
->major
= cols
[MONO_ASSEMBLYREF_MAJOR_VERSION
];
4949 aname
->minor
= cols
[MONO_ASSEMBLYREF_MINOR_VERSION
];
4950 aname
->build
= cols
[MONO_ASSEMBLYREF_BUILD_NUMBER
];
4951 aname
->revision
= cols
[MONO_ASSEMBLYREF_REV_NUMBER
];
4952 aname
->flags
= cols
[MONO_ASSEMBLYREF_FLAGS
];
4953 aname
->versioncompat
= 1; /* SameMachine (default) */
4954 aname
->hashalg
= ASSEMBLY_HASH_SHA1
; /* SHA1 (default) */
4956 version
= create_version (domain
, aname
->major
, aname
->minor
, aname
->build
, aname
->revision
, &error
);
4957 if (mono_error_set_pending_exception (&error
))
4960 MONO_OBJECT_SETREF (aname
, version
, version
);
4962 if (create_culture
) {
4964 MonoBoolean assembly_ref
= 1;
4965 args
[0] = mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_CULTURE
]));
4966 args
[1] = &assembly_ref
;
4968 o
= mono_runtime_invoke_checked (create_culture
, NULL
, args
, &error
);
4969 if (mono_error_set_pending_exception (&error
))
4972 MONO_OBJECT_SETREF (aname
, cultureInfo
, o
);
4975 if (cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]) {
4976 const gchar
*pkey_ptr
= mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]);
4977 guint32 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
4979 if ((cols
[MONO_ASSEMBLYREF_FLAGS
] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
)) {
4980 /* public key token isn't copied - the class library will
4981 automatically generate it from the public key if required */
4982 MonoArray
*pkey
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, pkey_len
, &error
);
4983 if (mono_error_set_pending_exception (&error
))
4986 MONO_OBJECT_SETREF (aname
, publicKey
, pkey
);
4987 memcpy (mono_array_addr (pkey
, guint8
, 0), pkey_ptr
, pkey_len
);
4989 MonoArray
*keyToken
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, pkey_len
, &error
);
4990 if (mono_error_set_pending_exception (&error
))
4993 MONO_OBJECT_SETREF (aname
, keyToken
, keyToken
);
4994 memcpy (mono_array_addr (keyToken
, guint8
, 0), pkey_ptr
, pkey_len
);
4997 MonoArray
*keyToken
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, 0, &error
);
4998 if (mono_error_set_pending_exception (&error
))
5001 MONO_OBJECT_SETREF (aname
, keyToken
, keyToken
);
5004 /* note: this function doesn't return the codebase on purpose (i.e. it can
5005 be used under partial trust as path information isn't present). */
5007 mono_array_setref (result
, i
, aname
);
5012 /* move this in some file in mono/util/ */
5014 g_concat_dir_and_file (const char *dir
, const char *file
)
5016 g_return_val_if_fail (dir
!= NULL
, NULL
);
5017 g_return_val_if_fail (file
!= NULL
, NULL
);
5020 * If the directory name doesn't have a / on the end, we need
5021 * to add one so we get a proper path to the file
5023 if (dir
[strlen(dir
) - 1] != G_DIR_SEPARATOR
)
5024 return g_strconcat (dir
, G_DIR_SEPARATOR_S
, file
, NULL
);
5026 return g_strconcat (dir
, file
, NULL
);
5030 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, gint32
*size
, MonoReflectionModule
**ref_module
)
5033 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
5035 guint32 cols
[MONO_MANIFEST_SIZE
];
5036 guint32 impl
, file_idx
;
5040 char *n
= mono_string_to_utf8_checked (name
, &error
);
5041 if (mono_error_set_pending_exception (&error
))
5044 for (i
= 0; i
< table
->rows
; ++i
) {
5045 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
5046 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
5047 if (strcmp (val
, n
) == 0)
5051 if (i
== table
->rows
)
5054 impl
= cols
[MONO_MANIFEST_IMPLEMENTATION
];
5057 * this code should only be called after obtaining the
5058 * ResourceInfo and handling the other cases.
5060 g_assert ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
);
5061 file_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
5063 module
= mono_image_load_file_for_image (assembly
->assembly
->image
, file_idx
);
5068 module
= assembly
->assembly
->image
;
5071 MonoReflectionModule
*rm
= mono_module_get_object_checked (mono_domain_get (), module
, &error
);
5072 if (mono_error_set_pending_exception (&error
))
5074 mono_gc_wbarrier_generic_store (ref_module
, (MonoObject
*) rm
);
5076 return (void*)mono_image_get_resource (module
, cols
[MONO_MANIFEST_OFFSET
], (guint32
*)size
);
5079 ICALL_EXPORT gboolean
5080 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoManifestResourceInfo
*info
)
5083 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
5085 guint32 cols
[MONO_MANIFEST_SIZE
];
5086 guint32 file_cols
[MONO_FILE_SIZE
];
5090 n
= mono_string_to_utf8_checked (name
, &error
);
5091 if (mono_error_set_pending_exception (&error
))
5093 for (i
= 0; i
< table
->rows
; ++i
) {
5094 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
5095 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
5096 if (strcmp (val
, n
) == 0)
5100 if (i
== table
->rows
)
5103 if (!cols
[MONO_MANIFEST_IMPLEMENTATION
]) {
5104 info
->location
= RESOURCE_LOCATION_EMBEDDED
| RESOURCE_LOCATION_IN_MANIFEST
;
5107 switch (cols
[MONO_MANIFEST_IMPLEMENTATION
] & MONO_IMPLEMENTATION_MASK
) {
5108 case MONO_IMPLEMENTATION_FILE
:
5109 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
5110 table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
5111 mono_metadata_decode_row (table
, i
- 1, file_cols
, MONO_FILE_SIZE
);
5112 val
= mono_metadata_string_heap (assembly
->assembly
->image
, file_cols
[MONO_FILE_NAME
]);
5113 MONO_OBJECT_SETREF (info
, filename
, mono_string_new (mono_object_domain (assembly
), val
));
5114 if (file_cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
5117 info
->location
= RESOURCE_LOCATION_EMBEDDED
;
5120 case MONO_IMPLEMENTATION_ASSEMBLYREF
:
5121 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
5122 mono_assembly_load_reference (assembly
->assembly
->image
, i
- 1);
5123 if (assembly
->assembly
->image
->references
[i
- 1] == (gpointer
)-1) {
5124 char *msg
= g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i
- 1, assembly
->assembly
->image
->name
);
5125 MonoException
*ex
= mono_get_exception_file_not_found2 (msg
, NULL
);
5127 mono_set_pending_exception (ex
);
5130 MonoReflectionAssembly
*assm_obj
;
5131 assm_obj
= mono_assembly_get_object_checked (mono_domain_get (), assembly
->assembly
->image
->references
[i
- 1], &error
);
5133 mono_error_set_pending_exception (&error
);
5136 MONO_OBJECT_SETREF (info
, assembly
, assm_obj
);
5138 /* Obtain info recursively */
5139 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info
->assembly
, name
, info
);
5140 info
->location
|= RESOURCE_LOCATION_ANOTHER_ASSEMBLY
;
5143 case MONO_IMPLEMENTATION_EXP_TYPE
:
5144 g_assert_not_reached ();
5152 ICALL_EXPORT MonoObject
*
5153 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoBoolean resource_modules
)
5156 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
5157 MonoArray
*result
= NULL
;
5162 /* check hash if needed */
5164 n
= mono_string_to_utf8_checked (name
, &error
);
5165 if (mono_error_set_pending_exception (&error
))
5168 for (i
= 0; i
< table
->rows
; ++i
) {
5169 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
5170 if (strcmp (val
, n
) == 0) {
5173 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
5174 fn
= mono_string_new (mono_object_domain (assembly
), n
);
5176 return (MonoObject
*)fn
;
5184 for (i
= 0; i
< table
->rows
; ++i
) {
5185 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
))
5189 result
= mono_array_new_checked (mono_object_domain (assembly
), mono_defaults
.string_class
, count
, &error
);
5190 if (mono_error_set_pending_exception (&error
))
5195 for (i
= 0; i
< table
->rows
; ++i
) {
5196 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
5197 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
5198 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
5199 mono_array_setref (result
, count
, mono_string_new (mono_object_domain (assembly
), n
));
5204 return (MonoObject
*)result
;
5207 ICALL_EXPORT MonoArray
*
5208 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly
*assembly
)
5211 MonoDomain
*domain
= mono_domain_get();
5214 int i
, j
, file_count
= 0;
5215 MonoImage
**modules
;
5216 guint32 module_count
, real_module_count
;
5217 MonoTableInfo
*table
;
5218 guint32 cols
[MONO_FILE_SIZE
];
5219 MonoImage
*image
= assembly
->assembly
->image
;
5221 g_assert (image
!= NULL
);
5222 g_assert (!assembly_is_dynamic (assembly
->assembly
));
5224 table
= &image
->tables
[MONO_TABLE_FILE
];
5225 file_count
= table
->rows
;
5227 modules
= image
->modules
;
5228 module_count
= image
->module_count
;
5230 real_module_count
= 0;
5231 for (i
= 0; i
< module_count
; ++i
)
5233 real_module_count
++;
5235 klass
= mono_class_get_module_class ();
5236 res
= mono_array_new_checked (domain
, klass
, 1 + real_module_count
+ file_count
, &error
);
5237 if (mono_error_set_pending_exception (&error
))
5240 MonoReflectionModule
*image_obj
= mono_module_get_object_checked (domain
, image
, &error
);
5241 if (mono_error_set_pending_exception (&error
))
5244 mono_array_setref (res
, 0, image_obj
);
5246 for (i
= 0; i
< module_count
; ++i
)
5248 MonoReflectionModule
*rm
= mono_module_get_object_checked (domain
, modules
[i
], &error
);
5249 if (mono_error_set_pending_exception (&error
))
5251 mono_array_setref (res
, j
, rm
);
5255 for (i
= 0; i
< file_count
; ++i
, ++j
) {
5256 mono_metadata_decode_row (table
, i
, cols
, MONO_FILE_SIZE
);
5257 if (cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
) {
5258 MonoReflectionModule
*rm
= mono_module_file_get_object_checked (domain
, image
, i
, &error
);
5259 if (mono_error_set_pending_exception (&error
))
5261 mono_array_setref (res
, j
, rm
);
5264 MonoImage
*m
= mono_image_load_file_for_image (image
, i
+ 1);
5266 MonoString
*fname
= mono_string_new (mono_domain_get (), mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]));
5267 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL
, fname
));
5270 MonoReflectionModule
*rm
= mono_module_get_object_checked (domain
, m
, &error
);
5271 if (mono_error_set_pending_exception (&error
))
5273 mono_array_setref (res
, j
, rm
);
5280 ICALL_EXPORT MonoReflectionMethod
*
5281 ves_icall_GetCurrentMethod (void)
5283 MonoReflectionMethod
*res
= NULL
;
5286 MonoMethod
*m
= mono_method_get_last_managed ();
5289 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5293 while (m
->is_inflated
)
5294 m
= ((MonoMethodInflated
*)m
)->declaring
;
5296 res
= mono_method_get_object_checked (mono_domain_get (), m
, NULL
, &error
);
5297 mono_error_set_pending_exception (&error
);
5303 mono_method_get_equivalent_method (MonoMethod
*method
, MonoClass
*klass
)
5306 if (method
->is_inflated
&& ((MonoMethodInflated
*)method
)->context
.method_inst
) {
5309 MonoMethodInflated
*inflated
= (MonoMethodInflated
*)method
;
5310 //method is inflated, we should inflate it on the other class
5311 MonoGenericContext ctx
;
5312 ctx
.method_inst
= inflated
->context
.method_inst
;
5313 ctx
.class_inst
= inflated
->context
.class_inst
;
5314 if (klass
->generic_class
)
5315 ctx
.class_inst
= klass
->generic_class
->context
.class_inst
;
5316 else if (klass
->generic_container
)
5317 ctx
.class_inst
= klass
->generic_container
->context
.class_inst
;
5318 result
= mono_class_inflate_generic_method_full_checked (inflated
->declaring
, klass
, &ctx
, &error
);
5319 g_assert (mono_error_ok (&error
)); /* FIXME don't swallow the error */
5323 mono_class_setup_methods (method
->klass
);
5324 if (mono_class_has_failure (method
->klass
))
5326 for (i
= 0; i
< method
->klass
->method
.count
; ++i
) {
5327 if (method
->klass
->methods
[i
] == method
) {
5332 mono_class_setup_methods (klass
);
5333 if (mono_class_has_failure (klass
))
5335 g_assert (offset
>= 0 && offset
< klass
->method
.count
);
5336 return klass
->methods
[offset
];
5339 ICALL_EXPORT MonoReflectionMethod
*
5340 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod
*method
, MonoType
*type
)
5342 MonoReflectionMethod
*res
= NULL
;
5346 klass
= mono_class_from_mono_type (type
);
5347 if (mono_class_get_generic_type_definition (method
->klass
) != mono_class_get_generic_type_definition (klass
))
5349 if (method
->klass
!= klass
) {
5350 method
= mono_method_get_equivalent_method (method
, klass
);
5355 klass
= method
->klass
;
5356 res
= mono_method_get_object_checked (mono_domain_get (), method
, klass
, &error
);
5357 mono_error_set_pending_exception (&error
);
5361 ICALL_EXPORT MonoReflectionMethodBody
*
5362 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod
*method
)
5365 MonoReflectionMethodBody
*result
= mono_method_body_get_object_checked (mono_domain_get (), method
, &error
);
5366 mono_error_set_pending_exception (&error
);
5370 ICALL_EXPORT MonoReflectionAssembly
*
5371 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5374 MonoReflectionAssembly
*result
;
5375 MonoMethod
*dest
= NULL
;
5377 mono_stack_walk_no_il (get_executing
, &dest
);
5379 result
= mono_assembly_get_object_checked (mono_domain_get (), dest
->klass
->image
->assembly
, &error
);
5381 mono_error_set_pending_exception (&error
);
5386 ICALL_EXPORT MonoReflectionAssembly
*
5387 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5390 MonoReflectionAssembly
*result
;
5391 MonoDomain
* domain
= mono_domain_get ();
5393 if (!domain
->entry_assembly
)
5396 result
= mono_assembly_get_object_checked (domain
, domain
->entry_assembly
, &error
);
5398 mono_error_set_pending_exception (&error
);
5402 ICALL_EXPORT MonoReflectionAssembly
*
5403 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5408 MonoReflectionAssembly
*result
;
5411 mono_stack_walk_no_il (get_executing
, &dest
);
5413 mono_stack_walk_no_il (get_caller_no_reflection
, &dest
);
5417 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5420 result
= mono_assembly_get_object_checked (mono_domain_get (), dest
->klass
->image
->assembly
, &error
);
5422 mono_error_set_pending_exception (&error
);
5426 ICALL_EXPORT MonoString
*
5427 ves_icall_System_MonoType_getFullName (MonoReflectionType
*object
, gboolean full_name
,
5428 gboolean assembly_qualified
)
5430 MonoDomain
*domain
= mono_object_domain (object
);
5431 MonoTypeNameFormat format
;
5436 format
= assembly_qualified
?
5437 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
:
5438 MONO_TYPE_NAME_FORMAT_FULL_NAME
;
5440 format
= MONO_TYPE_NAME_FORMAT_REFLECTION
;
5442 name
= mono_type_get_name_full (object
->type
, format
);
5446 if (full_name
&& (object
->type
->type
== MONO_TYPE_VAR
|| object
->type
->type
== MONO_TYPE_MVAR
)) {
5451 res
= mono_string_new (domain
, name
);
5458 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType
*rfield
)
5461 MonoClass
*klass
= mono_class_from_mono_type (rfield
->type
);
5463 mono_class_init_checked (klass
, &error
);
5464 mono_error_set_pending_exception (&error
);
5465 return mono_security_core_clr_class_level (klass
);
5469 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField
*rfield
)
5471 MonoClassField
*field
= rfield
->field
;
5472 return mono_security_core_clr_field_level (field
, TRUE
);
5476 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod
*rfield
)
5478 MonoMethod
*method
= rfield
->method
;
5479 return mono_security_core_clr_method_level (method
, TRUE
);
5483 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
)
5485 static MonoMethod
*create_culture
= NULL
;
5489 const char *pkey_ptr
;
5491 MonoBoolean assembly_ref
= 0;
5493 mono_error_init (error
);
5495 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, name
->name
));
5496 aname
->major
= name
->major
;
5497 aname
->minor
= name
->minor
;
5498 aname
->build
= name
->build
;
5499 aname
->flags
= name
->flags
;
5500 aname
->revision
= name
->revision
;
5501 aname
->hashalg
= name
->hash_alg
;
5502 aname
->versioncompat
= 1; /* SameMachine (default) */
5503 aname
->processor_architecture
= name
->arch
;
5505 if (by_default_version
) {
5506 MonoObject
*version
;
5508 version
= create_version (domain
, name
->major
, name
->minor
, name
->build
, name
->revision
, error
);
5509 return_if_nok (error
);
5511 MONO_OBJECT_SETREF (aname
, version
, version
);
5515 if (absolute
!= NULL
&& *absolute
!= '\0') {
5516 const gchar
*prepend
= "file://";
5519 codebase
= g_strdup (absolute
);
5524 for (i
= strlen (codebase
) - 1; i
>= 0; i
--)
5525 if (codebase
[i
] == '\\')
5528 if (*codebase
== '/' && *(codebase
+ 1) == '/') {
5531 prepend
= "file:///";
5535 result
= g_strconcat (prepend
, codebase
, NULL
);
5541 MONO_OBJECT_SETREF (aname
, codebase
, mono_string_new (domain
, codebase
));
5545 if (!create_culture
) {
5546 MonoMethodDesc
*desc
= mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
5547 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
5548 g_assert (create_culture
);
5549 mono_method_desc_free (desc
);
5552 if (name
->culture
) {
5553 args
[0] = mono_string_new (domain
, name
->culture
);
5554 args
[1] = &assembly_ref
;
5556 obj
= mono_runtime_invoke_checked (create_culture
, NULL
, args
, error
);
5557 return_if_nok (error
);
5559 MONO_OBJECT_SETREF (aname
, cultureInfo
, obj
);
5562 if (name
->public_key
) {
5563 pkey_ptr
= (char*)name
->public_key
;
5564 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
5566 MonoArray
*pkey
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, pkey_len
, error
);
5567 return_if_nok (error
);
5568 MONO_OBJECT_SETREF (aname
, publicKey
, pkey
);
5569 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
5570 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
5571 } else if (default_publickey
) {
5572 MonoArray
*pkey
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, 0, error
);
5573 return_if_nok (error
);
5574 MONO_OBJECT_SETREF (aname
, publicKey
, pkey
);
5575 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
5578 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5579 if (name
->public_key_token
[0]) {
5583 MonoArray
*keyToken
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, 8, error
);
5584 return_if_nok (error
);
5586 MONO_OBJECT_SETREF (aname
, keyToken
, keyToken
);
5587 p
= mono_array_addr (keyToken
, char, 0);
5589 for (i
= 0, j
= 0; i
< 8; i
++) {
5590 *p
= g_ascii_xdigit_value (name
->public_key_token
[j
++]) << 4;
5591 *p
|= g_ascii_xdigit_value (name
->public_key_token
[j
++]);
5594 } else if (default_token
) {
5595 MonoArray
*keyToken
= mono_array_new_checked (domain
, mono_defaults
.byte_class
, 0, error
);
5596 return_if_nok (error
);
5597 MONO_OBJECT_SETREF (aname
, keyToken
, keyToken
);
5601 ICALL_EXPORT MonoString
*
5602 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly
*assembly
)
5604 MonoDomain
*domain
= mono_object_domain (assembly
);
5605 MonoAssembly
*mass
= assembly
->assembly
;
5609 name
= mono_stringify_assembly_name (&mass
->aname
);
5610 res
= mono_string_new (domain
, name
);
5617 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly
*assembly
, MonoReflectionAssemblyName
*aname
)
5620 gchar
*absolute
, *dirname
;
5621 MonoAssembly
*mass
= assembly
->assembly
;
5623 /* XXX this is duplicated code to compute the codebase URI, unify it */
5624 if (g_path_is_absolute (mass
->image
->name
)) {
5625 absolute
= g_strdup (mass
->image
->name
);
5626 dirname
= g_path_get_dirname (absolute
);
5628 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
5629 dirname
= g_strdup (mass
->basedir
);
5632 replace_shadow_path (mono_object_domain (assembly
), dirname
, &absolute
);
5635 fill_reflection_assembly_name (mono_object_domain (assembly
), aname
, &mass
->aname
, absolute
, TRUE
, TRUE
, TRUE
, &error
);
5636 mono_error_set_pending_exception (&error
);
5642 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString
*fname
, MonoReflectionAssemblyName
*aname
)
5646 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
5649 MonoAssemblyName name
;
5652 filename
= mono_string_to_utf8_checked (fname
, &error
);
5653 if (mono_error_set_pending_exception (&error
))
5656 dirname
= g_path_get_dirname (filename
);
5657 replace_shadow_path (mono_domain_get (), dirname
, &filename
);
5660 image
= mono_image_open (filename
, &status
);
5666 if (status
== MONO_IMAGE_IMAGE_INVALID
)
5667 exc
= mono_get_exception_bad_image_format2 (NULL
, fname
);
5669 exc
= mono_get_exception_file_not_found2 (NULL
, fname
);
5670 mono_set_pending_exception (exc
);
5674 res
= mono_assembly_fill_assembly_name (image
, &name
);
5676 mono_image_close (image
);
5678 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5682 fill_reflection_assembly_name (mono_domain_get (), aname
, &name
, filename
, TRUE
, FALSE
, TRUE
, &error
);
5683 mono_error_set_pending_exception (&error
);
5685 mono_image_close (image
);
5689 ICALL_EXPORT MonoBoolean
5690 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly
*assembly
,
5691 char **minimum
, guint32
*minLength
, char **optional
, guint32
*optLength
, char **refused
, guint32
*refLength
)
5693 MonoBoolean result
= FALSE
;
5694 MonoDeclSecurityEntry entry
;
5696 /* SecurityAction.RequestMinimum */
5697 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQMIN
, &entry
)) {
5698 *minimum
= entry
.blob
;
5699 *minLength
= entry
.size
;
5702 /* SecurityAction.RequestOptional */
5703 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQOPT
, &entry
)) {
5704 *optional
= entry
.blob
;
5705 *optLength
= entry
.size
;
5708 /* SecurityAction.RequestRefuse */
5709 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQREFUSE
, &entry
)) {
5710 *refused
= entry
.blob
;
5711 *refLength
= entry
.size
;
5719 mono_module_type_is_visible (MonoTableInfo
*tdef
, MonoImage
*image
, int type
)
5721 guint32 attrs
, visibility
;
5723 attrs
= mono_metadata_decode_row_col (tdef
, type
- 1, MONO_TYPEDEF_FLAGS
);
5724 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5725 if (visibility
!= TYPE_ATTRIBUTE_PUBLIC
&& visibility
!= TYPE_ATTRIBUTE_NESTED_PUBLIC
)
5728 } while ((type
= mono_metadata_token_index (mono_metadata_nested_in_typedef (image
, type
))));
5734 mono_module_get_types (MonoDomain
*domain
, MonoImage
*image
, MonoArray
**exceptions
, MonoBoolean exportedOnly
, MonoError
*error
)
5736 MonoReflectionType
*rt
;
5739 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_TYPEDEF
];
5742 mono_error_init (error
);
5744 /* we start the count from 1 because we skip the special type <Module> */
5747 for (i
= 1; i
< tdef
->rows
; ++i
) {
5748 if (mono_module_type_is_visible (tdef
, image
, i
+ 1))
5752 count
= tdef
->rows
- 1;
5754 res
= mono_array_new_checked (domain
, mono_defaults
.runtimetype_class
, count
, error
);
5755 return_val_if_nok (error
, NULL
);
5756 *exceptions
= mono_array_new_checked (domain
, mono_defaults
.exception_class
, count
, error
);
5757 return_val_if_nok (error
, NULL
);
5759 for (i
= 1; i
< tdef
->rows
; ++i
) {
5760 if (!exportedOnly
|| mono_module_type_is_visible (tdef
, image
, i
+ 1)) {
5761 klass
= mono_class_get_checked (image
, (i
+ 1) | MONO_TOKEN_TYPE_DEF
, error
);
5764 rt
= mono_type_get_object_checked (domain
, &klass
->byval_arg
, error
);
5765 return_val_if_nok (error
, NULL
);
5767 mono_array_setref (res
, count
, rt
);
5769 MonoException
*ex
= mono_error_convert_to_exception (error
);
5770 mono_array_setref (*exceptions
, count
, ex
);
5779 ICALL_EXPORT MonoArray
*
5780 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly
*assembly
, MonoBoolean exportedOnly
)
5783 MonoArray
*res
= NULL
;
5784 MonoArray
*exceptions
= NULL
;
5785 MonoImage
*image
= NULL
;
5786 MonoTableInfo
*table
= NULL
;
5789 int i
, len
, ex_count
;
5791 domain
= mono_object_domain (assembly
);
5793 g_assert (!assembly_is_dynamic (assembly
->assembly
));
5794 image
= assembly
->assembly
->image
;
5795 table
= &image
->tables
[MONO_TABLE_FILE
];
5796 res
= mono_module_get_types (domain
, image
, &exceptions
, exportedOnly
, &error
);
5797 if (mono_error_set_pending_exception (&error
))
5800 /* Append data from all modules in the assembly */
5801 for (i
= 0; i
< table
->rows
; ++i
) {
5802 if (!(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
5803 MonoImage
*loaded_image
= mono_assembly_load_module (image
->assembly
, i
+ 1);
5808 res2
= mono_module_get_types (domain
, loaded_image
, &ex2
, exportedOnly
, &error
);
5809 if (mono_error_set_pending_exception (&error
))
5813 /* Append the new types to the end of the array */
5814 if (mono_array_length (res2
) > 0) {
5816 MonoArray
*res3
, *ex3
;
5818 len1
= mono_array_length (res
);
5819 len2
= mono_array_length (res2
);
5821 res3
= mono_array_new_checked (domain
, mono_defaults
.runtimetype_class
, len1
+ len2
, &error
);
5822 if (mono_error_set_pending_exception (&error
))
5824 mono_array_memcpy_refs (res3
, 0, res
, 0, len1
);
5825 mono_array_memcpy_refs (res3
, len1
, res2
, 0, len2
);
5828 ex3
= mono_array_new_checked (domain
, mono_defaults
.runtimetype_class
, len1
+ len2
, &error
);
5829 if (mono_error_set_pending_exception (&error
))
5831 mono_array_memcpy_refs (ex3
, 0, exceptions
, 0, len1
);
5832 mono_array_memcpy_refs (ex3
, len1
, ex2
, 0, len2
);
5839 /* the ReflectionTypeLoadException must have all the types (Types property),
5840 * NULL replacing types which throws an exception. The LoaderException must
5841 * contain all exceptions for NULL items.
5844 len
= mono_array_length (res
);
5847 for (i
= 0; i
< len
; i
++) {
5848 MonoReflectionType
*t
= (MonoReflectionType
*)mono_array_get (res
, gpointer
, i
);
5852 klass
= mono_type_get_class (t
->type
);
5853 if ((klass
!= NULL
) && mono_class_has_failure (klass
)) {
5854 /* keep the class in the list */
5855 list
= g_list_append (list
, klass
);
5856 /* and replace Type with NULL */
5857 mono_array_setref (res
, i
, NULL
);
5864 if (list
|| ex_count
) {
5866 MonoException
*exc
= NULL
;
5867 MonoArray
*exl
= NULL
;
5868 int j
, length
= g_list_length (list
) + ex_count
;
5870 exl
= mono_array_new_checked (domain
, mono_defaults
.exception_class
, length
, &error
);
5871 if (mono_error_set_pending_exception (&error
)) {
5875 /* Types for which mono_class_get_checked () succeeded */
5876 for (i
= 0, tmp
= list
; tmp
; i
++, tmp
= tmp
->next
) {
5877 MonoException
*exc
= mono_class_get_exception_for_failure ((MonoClass
*)tmp
->data
);
5878 mono_array_setref (exl
, i
, exc
);
5880 /* Types for which it don't */
5881 for (j
= 0; j
< mono_array_length (exceptions
); ++j
) {
5882 MonoException
*exc
= mono_array_get (exceptions
, MonoException
*, j
);
5884 g_assert (i
< length
);
5885 mono_array_setref (exl
, i
, exc
);
5892 exc
= mono_get_exception_reflection_type_load_checked (res
, exl
, &error
);
5893 if (!is_ok (&error
)) {
5894 mono_error_set_pending_exception (&error
);
5897 mono_set_pending_exception (exc
);
5904 ICALL_EXPORT gboolean
5905 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName
*name
, MonoString
*assname
)
5908 MonoAssemblyName aname
;
5909 MonoDomain
*domain
= mono_object_domain (name
);
5911 gboolean is_version_defined
;
5912 gboolean is_token_defined
;
5914 aname
.public_key
= NULL
;
5915 val
= mono_string_to_utf8_checked (assname
, &error
);
5916 if (mono_error_set_pending_exception (&error
))
5919 if (!mono_assembly_name_parse_full (val
, &aname
, TRUE
, &is_version_defined
, &is_token_defined
)) {
5920 g_free ((guint8
*) aname
.public_key
);
5925 fill_reflection_assembly_name (domain
, name
, &aname
, "", is_version_defined
, FALSE
, is_token_defined
, &error
);
5926 mono_error_set_pending_exception (&error
);
5928 mono_assembly_name_free (&aname
);
5929 g_free ((guint8
*) aname
.public_key
);
5935 ICALL_EXPORT MonoReflectionType
*
5936 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule
*module
)
5939 MonoReflectionType
*ret
;
5940 MonoDomain
*domain
= mono_object_domain (module
);
5943 g_assert (module
->image
);
5945 if (image_is_dynamic (module
->image
) && ((MonoDynamicImage
*)(module
->image
))->initial_image
)
5946 /* These images do not have a global type */
5949 klass
= mono_class_get_checked (module
->image
, 1 | MONO_TOKEN_TYPE_DEF
, &error
);
5950 if (!mono_error_ok (&error
)) {
5951 mono_error_set_pending_exception (&error
);
5955 ret
= mono_type_get_object_checked (domain
, &klass
->byval_arg
, &error
);
5956 if (!mono_error_ok (&error
)) {
5957 mono_error_set_pending_exception (&error
);
5965 ves_icall_System_Reflection_Module_Close (MonoReflectionModule
*module
)
5967 /*if (module->image)
5968 mono_image_close (module->image);*/
5971 ICALL_EXPORT MonoString
*
5972 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule
*module
)
5974 MonoDomain
*domain
= mono_object_domain (module
);
5976 g_assert (module
->image
);
5977 return mono_string_new (domain
, module
->image
->guid
);
5980 ICALL_EXPORT gpointer
5981 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule
*module
)
5984 if (module
->image
&& module
->image
->is_module_handle
)
5985 return module
->image
->raw_data
;
5988 return (gpointer
) (-1);
5992 ves_icall_System_Reflection_Module_GetPEKind (MonoImage
*image
, gint32
*pe_kind
, gint32
*machine
)
5994 if (image_is_dynamic (image
)) {
5995 MonoDynamicImage
*dyn
= (MonoDynamicImage
*)image
;
5996 *pe_kind
= dyn
->pe_kind
;
5997 *machine
= dyn
->machine
;
6000 *pe_kind
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_cli_header
.ch_flags
& 0x3;
6001 *machine
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_header
.coff
.coff_machine
;
6006 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage
*image
)
6008 return (image
->md_version_major
<< 16) | (image
->md_version_minor
);
6011 ICALL_EXPORT MonoArray
*
6012 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule
*module
)
6015 MonoArray
*exceptions
;
6018 if (!module
->image
) {
6019 MonoArray
*arr
= mono_array_new_checked (mono_object_domain (module
), mono_defaults
.runtimetype_class
, 0, &error
);
6020 mono_error_set_pending_exception (&error
);
6025 res
= mono_module_get_types (mono_object_domain (module
), module
->image
, &exceptions
, FALSE
, &error
);
6026 if (mono_error_set_pending_exception (&error
))
6029 for (i
= 0; i
< mono_array_length (exceptions
); ++i
) {
6030 MonoException
*ex
= mono_array_get (exceptions
, MonoException
*, i
);
6032 mono_set_pending_exception (ex
);
6041 mono_memberref_is_method (MonoImage
*image
, guint32 token
)
6043 if (!image_is_dynamic (image
)) {
6044 guint32 cols
[MONO_MEMBERREF_SIZE
];
6046 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
6047 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
6048 mono_metadata_decode_blob_size (sig
, &sig
);
6049 return (*sig
!= 0x6);
6052 MonoClass
*handle_class
;
6054 if (!mono_lookup_dynamic_token_class (image
, token
, FALSE
, &handle_class
, NULL
, &error
)) {
6055 mono_error_cleanup (&error
); /* just probing, ignore error */
6059 return mono_defaults
.methodhandle_class
== handle_class
;
6064 init_generic_context_from_args (MonoGenericContext
*context
, MonoArray
*type_args
, MonoArray
*method_args
)
6067 context
->class_inst
= mono_metadata_get_generic_inst (mono_array_length (type_args
),
6068 mono_array_addr (type_args
, MonoType
*, 0));
6070 context
->class_inst
= NULL
;
6072 context
->method_inst
= mono_metadata_get_generic_inst (mono_array_length (method_args
),
6073 mono_array_addr (method_args
, MonoType
*, 0));
6075 context
->method_inst
= NULL
;
6078 ICALL_EXPORT MonoType
*
6079 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*resolve_error
)
6082 int table
= mono_metadata_token_table (token
);
6083 int index
= mono_metadata_token_index (token
);
6084 MonoGenericContext context
;
6087 *resolve_error
= ResolveTokenError_Other
;
6089 /* Validate token */
6090 if ((table
!= MONO_TABLE_TYPEDEF
) && (table
!= MONO_TABLE_TYPEREF
) &&
6091 (table
!= MONO_TABLE_TYPESPEC
)) {
6092 *resolve_error
= ResolveTokenError_BadTable
;
6096 if (image_is_dynamic (image
)) {
6097 if ((table
== MONO_TABLE_TYPEDEF
) || (table
== MONO_TABLE_TYPEREF
)) {
6098 klass
= (MonoClass
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
, &error
);
6099 mono_error_cleanup (&error
);
6100 return klass
? &klass
->byval_arg
: NULL
;
6103 init_generic_context_from_args (&context
, type_args
, method_args
);
6104 klass
= (MonoClass
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
, &error
);
6105 mono_error_cleanup (&error
);
6106 return klass
? &klass
->byval_arg
: NULL
;
6109 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
6110 *resolve_error
= ResolveTokenError_OutOfRange
;
6114 init_generic_context_from_args (&context
, type_args
, method_args
);
6115 klass
= mono_class_get_checked (image
, token
, &error
);
6117 klass
= mono_class_inflate_generic_class_checked (klass
, &context
, &error
);
6118 if (!mono_error_ok (&error
)) {
6119 mono_error_set_pending_exception (&error
);
6124 return &klass
->byval_arg
;
6129 ICALL_EXPORT MonoMethod
*
6130 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*resolve_error
)
6133 int table
= mono_metadata_token_table (token
);
6134 int index
= mono_metadata_token_index (token
);
6135 MonoGenericContext context
;
6138 *resolve_error
= ResolveTokenError_Other
;
6140 /* Validate token */
6141 if ((table
!= MONO_TABLE_METHOD
) && (table
!= MONO_TABLE_METHODSPEC
) &&
6142 (table
!= MONO_TABLE_MEMBERREF
)) {
6143 *resolve_error
= ResolveTokenError_BadTable
;
6147 if (image_is_dynamic (image
)) {
6148 if (table
== MONO_TABLE_METHOD
) {
6149 method
= (MonoMethod
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
, &error
);
6150 mono_error_cleanup (&error
);
6154 if ((table
== MONO_TABLE_MEMBERREF
) && !(mono_memberref_is_method (image
, token
))) {
6155 *resolve_error
= ResolveTokenError_BadTable
;
6159 init_generic_context_from_args (&context
, type_args
, method_args
);
6160 method
= (MonoMethod
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
, &error
);
6161 mono_error_cleanup (&error
);
6165 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
6166 *resolve_error
= ResolveTokenError_OutOfRange
;
6169 if ((table
== MONO_TABLE_MEMBERREF
) && (!mono_memberref_is_method (image
, token
))) {
6170 *resolve_error
= ResolveTokenError_BadTable
;
6174 init_generic_context_from_args (&context
, type_args
, method_args
);
6175 method
= mono_get_method_checked (image
, token
, NULL
, &context
, &error
);
6176 mono_error_set_pending_exception (&error
);
6181 ICALL_EXPORT MonoString
*
6182 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*resolve_error
)
6185 int index
= mono_metadata_token_index (token
);
6187 *resolve_error
= ResolveTokenError_Other
;
6189 /* Validate token */
6190 if (mono_metadata_token_code (token
) != MONO_TOKEN_STRING
) {
6191 *resolve_error
= ResolveTokenError_BadTable
;
6195 if (image_is_dynamic (image
)) {
6196 MonoString
* result
= (MonoString
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
, &error
);
6197 mono_error_cleanup (&error
);
6201 if ((index
<= 0) || (index
>= image
->heap_us
.size
)) {
6202 *resolve_error
= ResolveTokenError_OutOfRange
;
6206 /* FIXME: What to do if the index points into the middle of a string ? */
6208 MonoString
*result
= mono_ldstr_checked (mono_domain_get (), image
, index
, &error
);
6209 mono_error_set_pending_exception (&error
);
6213 ICALL_EXPORT MonoClassField
*
6214 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*resolve_error
)
6218 int table
= mono_metadata_token_table (token
);
6219 int index
= mono_metadata_token_index (token
);
6220 MonoGenericContext context
;
6221 MonoClassField
*field
;
6223 *resolve_error
= ResolveTokenError_Other
;
6225 /* Validate token */
6226 if ((table
!= MONO_TABLE_FIELD
) && (table
!= MONO_TABLE_MEMBERREF
)) {
6227 *resolve_error
= ResolveTokenError_BadTable
;
6231 if (image_is_dynamic (image
)) {
6232 if (table
== MONO_TABLE_FIELD
) {
6233 field
= (MonoClassField
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
, &error
);
6234 mono_error_cleanup (&error
);
6238 if (mono_memberref_is_method (image
, token
)) {
6239 *resolve_error
= ResolveTokenError_BadTable
;
6243 init_generic_context_from_args (&context
, type_args
, method_args
);
6244 field
= (MonoClassField
*)mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
, &error
);
6245 mono_error_cleanup (&error
);
6249 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
6250 *resolve_error
= ResolveTokenError_OutOfRange
;
6253 if ((table
== MONO_TABLE_MEMBERREF
) && (mono_memberref_is_method (image
, token
))) {
6254 *resolve_error
= ResolveTokenError_BadTable
;
6258 init_generic_context_from_args (&context
, type_args
, method_args
);
6259 field
= mono_field_from_token_checked (image
, token
, &klass
, &context
, &error
);
6260 mono_error_set_pending_exception (&error
);
6266 ICALL_EXPORT MonoObject
*
6267 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
6271 int table
= mono_metadata_token_table (token
);
6273 *error
= ResolveTokenError_Other
;
6276 case MONO_TABLE_TYPEDEF
:
6277 case MONO_TABLE_TYPEREF
:
6278 case MONO_TABLE_TYPESPEC
: {
6279 MonoType
*t
= ves_icall_System_Reflection_Module_ResolveTypeToken (image
, token
, type_args
, method_args
, error
);
6281 ret
= (MonoObject
*) mono_type_get_object_checked (mono_domain_get (), t
, &merror
);
6282 mono_error_set_pending_exception (&merror
);
6289 case MONO_TABLE_METHOD
:
6290 case MONO_TABLE_METHODSPEC
: {
6291 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
6293 ret
= (MonoObject
*)mono_method_get_object_checked (mono_domain_get (), m
, m
->klass
, &merror
);
6294 mono_error_set_pending_exception (&merror
);
6300 case MONO_TABLE_FIELD
: {
6301 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
6303 ret
=(MonoObject
*)mono_field_get_object_checked (mono_domain_get (), f
->parent
, f
, &merror
);
6304 mono_error_set_pending_exception (&merror
);
6310 case MONO_TABLE_MEMBERREF
:
6311 if (mono_memberref_is_method (image
, token
)) {
6312 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
6314 ret
= (MonoObject
*)mono_method_get_object_checked (mono_domain_get (), m
, m
->klass
, &merror
);
6315 mono_error_set_pending_exception (&merror
);
6322 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
6324 ret
= (MonoObject
*)mono_field_get_object_checked (mono_domain_get (), f
->parent
, f
, &merror
);
6325 mono_error_set_pending_exception (&merror
);
6334 *error
= ResolveTokenError_BadTable
;
6340 ICALL_EXPORT MonoArray
*
6341 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*resolve_error
)
6344 int table
= mono_metadata_token_table (token
);
6345 int idx
= mono_metadata_token_index (token
);
6346 MonoTableInfo
*tables
= image
->tables
;
6351 *resolve_error
= ResolveTokenError_OutOfRange
;
6353 /* FIXME: Support other tables ? */
6354 if (table
!= MONO_TABLE_STANDALONESIG
)
6357 if (image_is_dynamic (image
))
6360 if ((idx
== 0) || (idx
> tables
[MONO_TABLE_STANDALONESIG
].rows
))
6363 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
6365 ptr
= mono_metadata_blob_heap (image
, sig
);
6366 len
= mono_metadata_decode_blob_size (ptr
, &ptr
);
6368 res
= mono_array_new_checked (mono_domain_get (), mono_defaults
.byte_class
, len
, &error
);
6369 if (mono_error_set_pending_exception (&error
))
6371 memcpy (mono_array_addr (res
, guint8
, 0), ptr
, len
);
6375 ICALL_EXPORT MonoReflectionType
*
6376 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder
*tb
, MonoString
*smodifiers
)
6379 MonoReflectionType
*ret
;
6381 int isbyref
= 0, rank
;
6383 char *str
= mono_string_to_utf8_checked (smodifiers
, &error
);
6384 if (mono_error_set_pending_exception (&error
))
6387 klass
= mono_class_from_mono_type (tb
->type
.type
);
6389 /* logic taken from mono_reflection_parse_type(): keep in sync */
6393 if (isbyref
) { /* only one level allowed by the spec */
6402 ret
= mono_type_get_object_checked (mono_object_domain (tb
), &klass
->this_arg
, &error
);
6403 mono_error_set_pending_exception (&error
);
6407 klass
= mono_ptr_class_get (&klass
->byval_arg
);
6408 mono_class_init (klass
);
6419 else if (*p
!= '*') { /* '*' means unknown lower bound */
6430 klass
= mono_array_class_get (klass
, rank
);
6431 mono_class_init (klass
);
6440 ret
= mono_type_get_object_checked (mono_object_domain (tb
), &klass
->byval_arg
, &error
);
6441 mono_error_set_pending_exception (&error
);
6446 ICALL_EXPORT MonoBoolean
6447 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType
*t
)
6453 res
= !type
->byref
&& (type
->type
== MONO_TYPE_ARRAY
|| type
->type
== MONO_TYPE_SZARRAY
);
6459 check_for_invalid_type (MonoClass
*klass
, MonoError
*error
)
6464 mono_error_init (error
);
6466 if (klass
->byval_arg
.type
!= MONO_TYPE_TYPEDBYREF
)
6469 name
= mono_type_get_full_name (klass
);
6470 str
= mono_string_new (mono_domain_get (), name
);
6472 mono_error_set_exception_instance (error
, mono_get_exception_type_load (str
, NULL
));
6475 ICALL_EXPORT MonoReflectionType
*
6476 ves_icall_RuntimeType_make_array_type (MonoReflectionType
*type
, int rank
)
6479 MonoReflectionType
*ret
;
6480 MonoClass
*klass
, *aklass
;
6482 klass
= mono_class_from_mono_type (type
->type
);
6483 check_for_invalid_type (klass
, &error
);
6484 mono_error_set_pending_exception (&error
);
6486 if (rank
== 0) //single dimentional array
6487 aklass
= mono_array_class_get (klass
, 1);
6489 aklass
= mono_bounded_array_class_get (klass
, rank
, TRUE
);
6491 ret
= mono_type_get_object_checked (mono_object_domain (type
), &aklass
->byval_arg
, &error
);
6492 mono_error_set_pending_exception (&error
);
6497 ICALL_EXPORT MonoReflectionType
*
6498 ves_icall_RuntimeType_make_byref_type (MonoReflectionType
*type
)
6501 MonoReflectionType
*ret
;
6504 klass
= mono_class_from_mono_type (type
->type
);
6505 mono_class_init_checked (klass
, &error
);
6506 if (mono_error_set_pending_exception (&error
))
6509 check_for_invalid_type (klass
, &error
);
6510 if (mono_error_set_pending_exception (&error
))
6513 ret
= mono_type_get_object_checked (mono_object_domain (type
), &klass
->this_arg
, &error
);
6514 mono_error_set_pending_exception (&error
);
6519 ICALL_EXPORT MonoReflectionType
*
6520 ves_icall_RuntimeType_MakePointerType (MonoReflectionType
*type
)
6523 MonoReflectionType
*ret
;
6524 MonoClass
*klass
, *pklass
;
6526 klass
= mono_class_from_mono_type (type
->type
);
6527 mono_class_init_checked (klass
, &error
);
6528 if (mono_error_set_pending_exception (&error
))
6530 check_for_invalid_type (klass
, &error
);
6531 if (mono_error_set_pending_exception (&error
))
6534 pklass
= mono_ptr_class_get (type
->type
);
6536 ret
= mono_type_get_object_checked (mono_object_domain (type
), &pklass
->byval_arg
, &error
);
6537 mono_error_set_pending_exception (&error
);
6542 ICALL_EXPORT MonoObject
*
6543 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType
*type
, MonoObject
*target
,
6544 MonoReflectionMethod
*info
, MonoBoolean throwOnBindFailure
)
6547 MonoClass
*delegate_class
= mono_class_from_mono_type (type
->type
);
6548 MonoObject
*delegate
;
6550 MonoMethod
*method
= info
->method
;
6552 mono_class_init_checked (delegate_class
, &error
);
6553 if (mono_error_set_pending_exception (&error
))
6556 if (!(delegate_class
->parent
== mono_defaults
.multicastdelegate_class
)) {
6557 /* FIXME improve this exception message */
6558 mono_error_set_execution_engine (&error
, "file %s: line %d (%s): assertion failed: (%s)", __FILE__
, __LINE__
,
6560 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6561 mono_error_set_pending_exception (&error
);
6565 if (mono_security_core_clr_enabled ()) {
6566 if (!mono_security_core_clr_ensure_delegate_creation (method
, &error
)) {
6567 if (throwOnBindFailure
)
6568 mono_error_set_pending_exception (&error
);
6570 mono_error_cleanup (&error
);
6575 delegate
= mono_object_new_checked (mono_object_domain (type
), delegate_class
, &error
);
6576 if (mono_error_set_pending_exception (&error
))
6579 if (method_is_dynamic (method
)) {
6580 /* Creating a trampoline would leak memory */
6581 func
= mono_compile_method_checked (method
, &error
);
6582 if (mono_error_set_pending_exception (&error
))
6585 if (target
&& method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
&& method
->klass
!= mono_object_class (target
))
6586 method
= mono_object_get_virtual_method (target
, method
);
6587 gpointer trampoline
= mono_runtime_create_jump_trampoline (mono_domain_get (), method
, TRUE
, &error
);
6588 if (mono_error_set_pending_exception (&error
))
6590 func
= mono_create_ftnptr (mono_domain_get (), trampoline
);
6593 mono_delegate_ctor_with_method (delegate
, target
, func
, method
, &error
);
6594 if (mono_error_set_pending_exception (&error
))
6599 ICALL_EXPORT MonoMulticastDelegate
*
6600 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate
*delegate
)
6603 MonoMulticastDelegate
*ret
;
6605 g_assert (mono_class_has_parent (mono_object_class (delegate
), mono_defaults
.multicastdelegate_class
));
6607 ret
= (MonoMulticastDelegate
*) mono_object_new_checked (mono_object_domain (delegate
), mono_object_class (delegate
), &error
);
6608 if (mono_error_set_pending_exception (&error
))
6611 ret
->delegate
.invoke_impl
= mono_runtime_create_delegate_trampoline (mono_object_class (delegate
));
6616 ICALL_EXPORT MonoReflectionMethod
*
6617 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate
*delegate
)
6619 MonoReflectionMethod
*ret
= NULL
;
6621 ret
= mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate
->target
, delegate
->method
), mono_object_class (delegate
->target
), &error
);
6622 mono_error_set_pending_exception (&error
);
6628 static inline gint32
6629 mono_array_get_byte_length (MonoArray
*array
)
6635 klass
= array
->obj
.vtable
->klass
;
6637 if (array
->bounds
== NULL
)
6638 length
= array
->max_length
;
6641 for (i
= 0; i
< klass
->rank
; ++ i
)
6642 length
*= array
->bounds
[i
].length
;
6645 switch (klass
->element_class
->byval_arg
.type
) {
6648 case MONO_TYPE_BOOLEAN
:
6652 case MONO_TYPE_CHAR
:
6660 return length
* sizeof (gpointer
);
6671 ves_icall_System_Buffer_ByteLengthInternal (MonoArray
*array
)
6673 return mono_array_get_byte_length (array
);
6677 ves_icall_System_Buffer_GetByteInternal (MonoArray
*array
, gint32 idx
)
6679 return mono_array_get (array
, gint8
, idx
);
6683 ves_icall_System_Buffer_SetByteInternal (MonoArray
*array
, gint32 idx
, gint8 value
)
6685 mono_array_set (array
, gint8
, idx
, value
);
6688 ICALL_EXPORT MonoBoolean
6689 ves_icall_System_Buffer_BlockCopyInternal (MonoArray
*src
, gint32 src_offset
, MonoArray
*dest
, gint32 dest_offset
, gint32 count
)
6691 guint8
*src_buf
, *dest_buf
;
6694 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6698 g_assert (count
>= 0);
6700 /* This is called directly from the class libraries without going through the managed wrapper */
6701 MONO_CHECK_ARG_NULL (src
, FALSE
);
6702 MONO_CHECK_ARG_NULL (dest
, FALSE
);
6704 /* watch out for integer overflow */
6705 if ((src_offset
> mono_array_get_byte_length (src
) - count
) || (dest_offset
> mono_array_get_byte_length (dest
) - count
))
6708 src_buf
= (guint8
*)src
->vector
+ src_offset
;
6709 dest_buf
= (guint8
*)dest
->vector
+ dest_offset
;
6712 memcpy (dest_buf
, src_buf
, count
);
6714 memmove (dest_buf
, src_buf
, count
); /* Source and dest are the same array */
6719 #ifndef DISABLE_REMOTING
6720 ICALL_EXPORT MonoObject
*
6721 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject
*this_obj
, MonoString
*class_name
)
6724 MonoDomain
*domain
= mono_object_domain (this_obj
);
6726 MonoRealProxy
*rp
= ((MonoRealProxy
*)this_obj
);
6727 MonoTransparentProxy
*tp
;
6731 res
= mono_object_new_checked (domain
, mono_defaults
.transparent_proxy_class
, &error
);
6732 if (mono_error_set_pending_exception (&error
))
6735 tp
= (MonoTransparentProxy
*) res
;
6737 MONO_OBJECT_SETREF (tp
, rp
, rp
);
6738 type
= ((MonoReflectionType
*)rp
->class_to_proxy
)->type
;
6739 klass
= mono_class_from_mono_type (type
);
6741 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6742 mono_class_setup_vtable (klass
);
6743 if (mono_class_has_failure (klass
)) {
6744 mono_set_pending_exception (mono_class_get_exception_for_failure (klass
));
6748 tp
->custom_type_info
= (mono_object_isinst_checked (this_obj
, mono_defaults
.iremotingtypeinfo_class
, &error
) != NULL
);
6749 if (mono_error_set_pending_exception (&error
))
6751 tp
->remote_class
= mono_remote_class (domain
, class_name
, klass
, &error
);
6752 if (mono_error_set_pending_exception (&error
))
6755 res
->vtable
= (MonoVTable
*)mono_remote_class_vtable (domain
, tp
->remote_class
, rp
, &error
);
6756 if (mono_error_set_pending_exception (&error
))
6761 ICALL_EXPORT MonoReflectionType
*
6762 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy
*tp
)
6765 MonoReflectionType
*ret
= mono_type_get_object_checked (mono_object_domain (tp
), &tp
->remote_class
->proxy_class
->byval_arg
, &error
);
6766 mono_error_set_pending_exception (&error
);
6772 /* System.Environment */
6775 ves_icall_System_Environment_get_UserName (void)
6777 /* using glib is more portable */
6778 return mono_string_new (mono_domain_get (), g_get_user_name ());
6782 ICALL_EXPORT MonoString
*
6783 ves_icall_System_Environment_get_MachineName (void)
6785 #if defined (HOST_WIN32)
6790 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
6791 buf
= g_new (gunichar2
, len
);
6794 if (GetComputerName (buf
, (PDWORD
) &len
)) {
6796 result
= mono_string_new_utf16_checked (mono_domain_get (), buf
, len
, &error
);
6797 mono_error_set_pending_exception (&error
);
6802 #elif !defined(DISABLE_SOCKETS)
6806 #if defined _SC_HOST_NAME_MAX
6807 n
= sysconf (_SC_HOST_NAME_MAX
);
6811 buf
= g_malloc (n
+1);
6813 if (gethostname (buf
, n
) == 0){
6815 result
= mono_string_new (mono_domain_get (), buf
);
6822 return mono_string_new (mono_domain_get (), "mono");
6827 ves_icall_System_Environment_get_Platform (void)
6829 #if defined (TARGET_WIN32)
6832 #elif defined(__MACH__)
6835 // Notice that the value is hidden from user code, and only exposed
6836 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6837 // define and making assumptions based on Unix/128/4 values before there
6838 // was a MacOS define. Lots of code would assume that not-Unix meant
6839 // Windows, but in this case, it would be OSX.
6848 ICALL_EXPORT MonoString
*
6849 ves_icall_System_Environment_get_NewLine (void)
6851 #if defined (HOST_WIN32)
6852 return mono_string_new (mono_domain_get (), "\r\n");
6854 return mono_string_new (mono_domain_get (), "\n");
6858 ICALL_EXPORT MonoBoolean
6859 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6861 #if SIZEOF_VOID_P == 8
6865 gboolean isWow64Process
= FALSE
;
6866 if (IsWow64Process (GetCurrentProcess (), &isWow64Process
)) {
6867 return (MonoBoolean
)isWow64Process
;
6869 #elif defined(HAVE_SYS_UTSNAME_H)
6870 struct utsname name
;
6872 if (uname (&name
) >= 0) {
6873 return strcmp (name
.machine
, "x86_64") == 0 || strncmp (name
.machine
, "aarch64", 7) == 0 || strncmp (name
.machine
, "ppc64", 5) == 0;
6880 ICALL_EXPORT MonoString
*
6881 ves_icall_System_Environment_GetEnvironmentVariable (MonoString
*name
)
6890 utf8_name
= mono_string_to_utf8_checked (name
, &error
); /* FIXME: this should be ascii */
6891 if (mono_error_set_pending_exception (&error
))
6893 value
= g_getenv (utf8_name
);
6900 return mono_string_new (mono_domain_get (), value
);
6904 * There is no standard way to get at environ.
6907 #ifndef __MINGW32_VERSION
6908 #if defined(__APPLE__)
6909 #if defined (TARGET_OSX)
6910 /* Apple defines this in crt_externs.h but doesn't provide that header for
6911 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6912 * in fact exist on all implementations (so far)
6914 gchar
***_NSGetEnviron(void);
6915 #define environ (*_NSGetEnviron())
6917 static char *mono_environ
[1] = { NULL
};
6918 #define environ mono_environ
6919 #endif /* defined (TARGET_OSX) */
6927 ICALL_EXPORT MonoArray
*
6928 ves_icall_System_Environment_GetCoomandLineArgs (void)
6931 MonoArray
*result
= mono_runtime_get_main_args_checked (&error
);
6932 mono_error_set_pending_exception (&error
);
6936 ICALL_EXPORT MonoArray
*
6937 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6949 env_strings
= GetEnvironmentStrings();
6952 env_string
= env_strings
;
6953 while (*env_string
!= '\0') {
6954 /* weird case that MS seems to skip */
6955 if (*env_string
!= '=')
6957 while (*env_string
!= '\0')
6963 domain
= mono_domain_get ();
6964 names
= mono_array_new_checked (domain
, mono_defaults
.string_class
, n
, &error
);
6965 if (mono_error_set_pending_exception (&error
))
6970 env_string
= env_strings
;
6971 while (*env_string
!= '\0') {
6972 /* weird case that MS seems to skip */
6973 if (*env_string
!= '=') {
6974 equal_str
= wcschr(env_string
, '=');
6975 g_assert(equal_str
);
6977 str
= mono_string_new_utf16_checked (domain
, env_string
, equal_str
-env_string
, &error
);
6978 if (mono_error_set_pending_exception (&error
))
6981 mono_array_setref (names
, n
, str
);
6984 while (*env_string
!= '\0')
6989 FreeEnvironmentStrings (env_strings
);
7003 for (e
= environ
; *e
!= 0; ++ e
)
7006 domain
= mono_domain_get ();
7007 names
= mono_array_new_checked (domain
, mono_defaults
.string_class
, n
, &error
);
7008 if (mono_error_set_pending_exception (&error
))
7012 for (e
= environ
; *e
!= 0; ++ e
) {
7013 parts
= g_strsplit (*e
, "=", 2);
7015 str
= mono_string_new (domain
, *parts
);
7016 mono_array_setref (names
, n
, str
);
7029 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString
*name
, MonoString
*value
)
7032 gunichar2
*utf16_name
, *utf16_value
;
7034 gchar
*utf8_name
, *utf8_value
;
7039 utf16_name
= mono_string_to_utf16 (name
);
7040 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
7041 SetEnvironmentVariable (utf16_name
, NULL
);
7042 g_free (utf16_name
);
7046 utf16_value
= mono_string_to_utf16 (value
);
7048 SetEnvironmentVariable (utf16_name
, utf16_value
);
7050 g_free (utf16_name
);
7051 g_free (utf16_value
);
7053 utf8_name
= mono_string_to_utf8_checked (name
, &error
); /* FIXME: this should be ascii */
7054 if (mono_error_set_pending_exception (&error
))
7057 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
7058 g_unsetenv (utf8_name
);
7063 utf8_value
= mono_string_to_utf8_checked (value
, &error
);
7064 if (!mono_error_ok (&error
)) {
7066 mono_error_set_pending_exception (&error
);
7069 g_setenv (utf8_name
, utf8_value
, TRUE
);
7072 g_free (utf8_value
);
7077 ves_icall_System_Environment_Exit (int result
)
7079 mono_environment_exitcode_set (result
);
7081 /* FIXME: There are some cleanup hangs that should be worked out, but
7082 * if the program is going to exit, everything will be cleaned up when
7083 * NaCl exits anyway.
7085 #ifndef __native_client__
7086 if (!mono_runtime_try_shutdown ())
7087 mono_thread_exit ();
7089 /* Suspend all managed threads since the runtime is going away */
7090 mono_thread_suspend_all_other_threads ();
7092 mono_runtime_quit ();
7095 /* we may need to do some cleanup here... */
7099 ICALL_EXPORT MonoString
*
7100 ves_icall_System_Environment_GetGacPath (void)
7102 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
7105 ICALL_EXPORT MonoString
*
7106 ves_icall_System_Environment_GetWindowsFolderPath (int folder
)
7108 #if defined (HOST_WIN32)
7109 #ifndef CSIDL_FLAG_CREATE
7110 #define CSIDL_FLAG_CREATE 0x8000
7113 WCHAR path
[MAX_PATH
];
7114 /* Create directory if no existing */
7115 if (SUCCEEDED (SHGetFolderPathW (NULL
, folder
| CSIDL_FLAG_CREATE
, NULL
, 0, path
))) {
7120 MonoString
*res
= mono_string_new_utf16_checked (mono_domain_get (), path
, len
, &error
);
7121 mono_error_set_pending_exception (&error
);
7125 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
7127 return mono_string_new (mono_domain_get (), "");
7130 ICALL_EXPORT MonoArray
*
7131 ves_icall_System_Environment_GetLogicalDrives (void)
7134 gunichar2 buf
[256], *ptr
, *dname
;
7136 guint initial_size
= 127, size
= 128;
7139 MonoString
*drivestr
;
7140 MonoDomain
*domain
= mono_domain_get ();
7146 while (size
> initial_size
) {
7147 size
= (guint
) GetLogicalDriveStrings (initial_size
, ptr
);
7148 if (size
> initial_size
) {
7151 ptr
= (gunichar2
*)g_malloc0 ((size
+ 1) * sizeof (gunichar2
));
7152 initial_size
= size
;
7166 result
= mono_array_new_checked (domain
, mono_defaults
.string_class
, ndrives
, &error
);
7167 if (mono_error_set_pending_exception (&error
))
7174 while (*u16
) { u16
++; len
++; }
7175 drivestr
= mono_string_new_utf16_checked (domain
, dname
, len
, &error
);
7176 if (mono_error_set_pending_exception (&error
))
7179 mono_array_setref (result
, ndrives
++, drivestr
);
7190 ICALL_EXPORT MonoString
*
7191 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString
*path
)
7194 gunichar2 volume_name
[MAX_PATH
+ 1];
7196 if (GetVolumeInformation (mono_string_chars (path
), NULL
, 0, NULL
, NULL
, NULL
, volume_name
, MAX_PATH
+ 1) == FALSE
)
7198 MonoString
*result
= mono_string_from_utf16_checked (volume_name
, &error
);
7199 mono_error_set_pending_exception (&error
);
7203 ICALL_EXPORT MonoString
*
7204 ves_icall_System_Environment_InternalGetHome (void)
7206 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7209 static const char *encodings
[] = {
7211 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7212 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7213 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7215 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7216 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7217 "x_unicode_2_0_utf_7",
7219 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7220 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7222 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7225 "unicodefffe", "utf_16be",
7232 * Returns the internal codepage, if the value of "int_code_page" is
7233 * 1 at entry, and we can not compute a suitable code page number,
7234 * returns the code page as a string
7236 ICALL_EXPORT MonoString
*
7237 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32
*int_code_page
)
7242 char *codepage
= NULL
;
7244 int want_name
= *int_code_page
;
7247 *int_code_page
= -1;
7249 g_get_charset (&cset
);
7250 c
= codepage
= strdup (cset
);
7251 for (c
= codepage
; *c
; c
++){
7252 if (isascii (*c
) && isalpha (*c
))
7257 /* g_print ("charset: %s\n", cset); */
7259 /* handle some common aliases */
7262 for (i
= 0; p
!= 0; ){
7265 p
= encodings
[++i
];
7268 if (strcmp (p
, codepage
) == 0){
7269 *int_code_page
= code
;
7272 p
= encodings
[++i
];
7275 if (strstr (codepage
, "utf_8") != NULL
)
7276 *int_code_page
|= 0x10000000;
7279 if (want_name
&& *int_code_page
== -1)
7280 return mono_string_new (mono_domain_get (), cset
);
7285 ICALL_EXPORT MonoBoolean
7286 ves_icall_System_Environment_get_HasShutdownStarted (void)
7288 if (mono_runtime_is_shutting_down ())
7291 if (mono_domain_is_unloading (mono_domain_get ()))
7298 ves_icall_System_Environment_BroadcastSettingChange (void)
7301 SendMessageTimeout (HWND_BROADCAST
, WM_SETTINGCHANGE
, (WPARAM
)NULL
, (LPARAM
)L
"Environment", SMTO_ABORTIFHUNG
, 2000, 0);
7307 ves_icall_System_Environment_get_TickCount (void)
7309 /* this will overflow after ~24 days */
7310 return (gint32
) (mono_msec_boottime () & 0xffffffff);
7314 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7319 #ifndef DISABLE_REMOTING
7320 ICALL_EXPORT MonoBoolean
7321 ves_icall_IsTransparentProxy (MonoObject
*proxy
)
7326 if (proxy
->vtable
->klass
== mono_defaults
.transparent_proxy_class
)
7332 ICALL_EXPORT MonoReflectionMethod
*
7333 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7334 MonoReflectionType
*rtype
, MonoReflectionMethod
*rmethod
)
7336 MonoReflectionMethod
*ret
= NULL
;
7341 MonoMethod
**vtable
;
7342 MonoMethod
*res
= NULL
;
7344 MONO_CHECK_ARG_NULL (rtype
, NULL
);
7345 MONO_CHECK_ARG_NULL (rmethod
, NULL
);
7347 method
= rmethod
->method
;
7348 klass
= mono_class_from_mono_type (rtype
->type
);
7349 mono_class_init_checked (klass
, &error
);
7350 if (mono_error_set_pending_exception (&error
))
7353 if (MONO_CLASS_IS_INTERFACE (klass
))
7356 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
)
7359 if ((method
->flags
& METHOD_ATTRIBUTE_FINAL
) || !(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
7360 if (klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
))
7366 mono_class_setup_vtable (klass
);
7367 vtable
= klass
->vtable
;
7369 if (method
->klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
7370 gboolean variance_used
= FALSE
;
7371 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7372 int offs
= mono_class_interface_offset_with_variance (klass
, method
->klass
, &variance_used
);
7374 res
= vtable
[offs
+ method
->slot
];
7376 if (!(klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
)))
7379 if (method
->slot
!= -1)
7380 res
= vtable
[method
->slot
];
7386 ret
= mono_method_get_object_checked (mono_domain_get (), res
, NULL
, &error
);
7387 mono_error_set_pending_exception (&error
);
7392 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType
*type
, MonoBoolean enable
)
7398 klass
= mono_class_from_mono_type (type
->type
);
7399 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, &error
);
7400 if (!is_ok (&error
)) {
7401 mono_error_set_pending_exception (&error
);
7405 mono_vtable_set_is_remote (vtable
, enable
);
7408 #else /* DISABLE_REMOTING */
7411 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType
*type
, MonoBoolean enable
)
7413 g_assert_not_reached ();
7418 ICALL_EXPORT MonoObject
*
7419 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType
*type
)
7426 domain
= mono_object_domain (type
);
7427 klass
= mono_class_from_mono_type (type
->type
);
7428 mono_class_init_checked (klass
, &error
);
7429 if (mono_error_set_pending_exception (&error
))
7432 if (MONO_CLASS_IS_INTERFACE (klass
) || (klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
)) {
7433 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7437 if (klass
->rank
>= 1) {
7438 g_assert (klass
->rank
== 1);
7439 ret
= (MonoObject
*) mono_array_new_checked (domain
, klass
->element_class
, 0, &error
);
7440 mono_error_set_pending_exception (&error
);
7443 MonoVTable
*vtable
= mono_class_vtable_full (domain
, klass
, &error
);
7444 if (!is_ok (&error
)) {
7445 mono_error_set_pending_exception (&error
);
7448 /* Bypass remoting object creation check */
7449 ret
= mono_object_new_alloc_specific_checked (vtable
, &error
);
7450 mono_error_set_pending_exception (&error
);
7456 ICALL_EXPORT MonoString
*
7457 ves_icall_System_IO_get_temp_path (void)
7459 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7462 #ifndef PLATFORM_NO_DRIVEINFO
7463 ICALL_EXPORT MonoBoolean
7464 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString
*path_name
, guint64
*free_bytes_avail
,
7465 guint64
*total_number_of_bytes
, guint64
*total_number_of_free_bytes
,
7469 ULARGE_INTEGER wapi_free_bytes_avail
;
7470 ULARGE_INTEGER wapi_total_number_of_bytes
;
7471 ULARGE_INTEGER wapi_total_number_of_free_bytes
;
7473 *error
= ERROR_SUCCESS
;
7474 result
= GetDiskFreeSpaceEx (mono_string_chars (path_name
), &wapi_free_bytes_avail
, &wapi_total_number_of_bytes
,
7475 &wapi_total_number_of_free_bytes
);
7478 *free_bytes_avail
= wapi_free_bytes_avail
.QuadPart
;
7479 *total_number_of_bytes
= wapi_total_number_of_bytes
.QuadPart
;
7480 *total_number_of_free_bytes
= wapi_total_number_of_free_bytes
.QuadPart
;
7482 *free_bytes_avail
= 0;
7483 *total_number_of_bytes
= 0;
7484 *total_number_of_free_bytes
= 0;
7485 *error
= GetLastError ();
7491 ICALL_EXPORT guint32
7492 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString
*root_path_name
)
7494 return GetDriveType (mono_string_chars (root_path_name
));
7498 ICALL_EXPORT gpointer
7499 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod
*method
)
7502 gpointer result
= mono_compile_method_checked (method
, &error
);
7503 mono_error_set_pending_exception (&error
);
7507 ICALL_EXPORT MonoString
*
7508 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7513 path
= g_build_path (G_DIR_SEPARATOR_S
, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version
, "machine.config", NULL
);
7515 #if defined (HOST_WIN32)
7516 /* Avoid mixing '/' and '\\' */
7519 for (i
= strlen (path
) - 1; i
>= 0; i
--)
7520 if (path
[i
] == '/')
7524 mcpath
= mono_string_new (mono_domain_get (), path
);
7530 /* this is an icall */
7532 get_bundled_app_config (void)
7535 const gchar
*app_config
;
7538 gchar
*config_file_name
, *config_file_path
;
7539 gsize len
, config_file_path_length
, config_ext_length
;
7542 domain
= mono_domain_get ();
7543 file
= domain
->setup
->configuration_file
;
7544 if (!file
|| file
->length
== 0)
7547 // Retrieve config file and remove the extension
7548 config_file_name
= mono_string_to_utf8_checked (file
, &error
);
7549 if (mono_error_set_pending_exception (&error
))
7551 config_file_path
= mono_portability_find_file (config_file_name
, TRUE
);
7552 if (!config_file_path
)
7553 config_file_path
= config_file_name
;
7555 config_file_path_length
= strlen (config_file_path
);
7556 config_ext_length
= strlen (".config");
7557 if (config_file_path_length
<= config_ext_length
)
7560 len
= config_file_path_length
- config_ext_length
;
7561 module
= (gchar
*)g_malloc0 (len
+ 1);
7562 memcpy (module
, config_file_path
, len
);
7563 // Get the config file from the module name
7564 app_config
= mono_config_string_for_assembly_file (module
);
7567 if (config_file_name
!= config_file_path
)
7568 g_free (config_file_name
);
7569 g_free (config_file_path
);
7574 return mono_string_new (mono_domain_get (), app_config
);
7578 get_bundled_machine_config (void)
7580 const gchar
*machine_config
;
7582 machine_config
= mono_get_machine_config ();
7584 if (!machine_config
)
7587 return mono_string_new (mono_domain_get (), machine_config
);
7590 ICALL_EXPORT MonoString
*
7591 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7596 path
= g_path_get_dirname (mono_get_config_dir ());
7598 #if defined (HOST_WIN32)
7599 /* Avoid mixing '/' and '\\' */
7602 for (i
= strlen (path
) - 1; i
>= 0; i
--)
7603 if (path
[i
] == '/')
7607 ipath
= mono_string_new (mono_domain_get (), path
);
7613 ICALL_EXPORT gboolean
7614 ves_icall_get_resources_ptr (MonoReflectionAssembly
*assembly
, gpointer
*result
, gint32
*size
)
7616 MonoPEResourceDataEntry
*entry
;
7619 if (!assembly
|| !result
|| !size
)
7624 image
= assembly
->assembly
->image
;
7625 entry
= (MonoPEResourceDataEntry
*)mono_image_lookup_resource (image
, MONO_PE_RESOURCE_ID_ASPNET_STRING
, 0, NULL
);
7629 *result
= mono_image_rva_map (image
, entry
->rde_data_offset
);
7634 *size
= entry
->rde_size
;
7639 ICALL_EXPORT MonoBoolean
7640 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7642 return mono_is_debugger_attached ();
7645 ICALL_EXPORT MonoBoolean
7646 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7648 if (mono_get_runtime_callbacks ()->debug_log_is_enabled
)
7649 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7655 ves_icall_System_Diagnostics_Debugger_Log (int level
, MonoString
*category
, MonoString
*message
)
7657 if (mono_get_runtime_callbacks ()->debug_log
)
7658 mono_get_runtime_callbacks ()->debug_log (level
, category
, message
);
7662 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString
*message
)
7664 #if defined (HOST_WIN32)
7665 OutputDebugString (mono_string_chars (message
));
7667 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7671 /* Only used for value types */
7672 ICALL_EXPORT MonoObject
*
7673 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType
*type
)
7680 domain
= mono_object_domain (type
);
7681 klass
= mono_class_from_mono_type (type
->type
);
7682 mono_class_init_checked (klass
, &error
);
7683 if (mono_error_set_pending_exception (&error
))
7686 if (mono_class_is_nullable (klass
))
7687 /* No arguments -> null */
7690 result
= mono_object_new_checked (domain
, klass
, &error
);
7691 mono_error_set_pending_exception (&error
);
7695 ICALL_EXPORT MonoReflectionMethod
*
7696 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod
*m
, gboolean definition
)
7698 MonoReflectionMethod
*ret
= NULL
;
7701 MonoClass
*klass
, *parent
;
7702 MonoGenericContext
*generic_inst
= NULL
;
7703 MonoMethod
*method
= m
->method
;
7704 MonoMethod
*result
= NULL
;
7707 if (method
->klass
== NULL
)
7710 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
7711 MONO_CLASS_IS_INTERFACE (method
->klass
) ||
7712 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
7715 slot
= mono_method_get_vtable_slot (method
);
7719 klass
= method
->klass
;
7720 if (klass
->generic_class
) {
7721 generic_inst
= mono_class_get_context (klass
);
7722 klass
= klass
->generic_class
->container_class
;
7726 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7727 for (parent
= klass
->parent
; parent
!= NULL
; parent
= parent
->parent
) {
7728 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7729 or klass is the generic container class and generic_inst is the instantiation.
7731 when we go to the parent, if the parent is an open constructed type, we need to
7732 replace the type parameters by the definitions from the generic_inst, and then take it
7733 apart again into the klass and the generic_inst.
7735 For cases like this:
7736 class C<T> : B<T, int> {
7737 public override void Foo () { ... }
7739 class B<U,V> : A<HashMap<U,V>> {
7740 public override void Foo () { ... }
7743 public virtual void Foo () { ... }
7746 if at each iteration the parent isn't open, we can skip inflating it. if at some
7747 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7750 MonoGenericContext
*parent_inst
= NULL
;
7751 if (mono_class_is_open_constructed_type (mono_class_get_type (parent
))) {
7752 parent
= mono_class_inflate_generic_class_checked (parent
, generic_inst
, &error
);
7753 if (!mono_error_ok (&error
)) {
7754 mono_error_set_pending_exception (&error
);
7758 if (parent
->generic_class
) {
7759 parent_inst
= mono_class_get_context (parent
);
7760 parent
= parent
->generic_class
->container_class
;
7763 mono_class_setup_vtable (parent
);
7764 if (parent
->vtable_size
<= slot
)
7767 generic_inst
= parent_inst
;
7770 klass
= klass
->parent
;
7773 if (mono_class_is_open_constructed_type (mono_class_get_type (klass
))) {
7774 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, &error
);
7775 if (!mono_error_ok (&error
)) {
7776 mono_error_set_pending_exception (&error
);
7780 generic_inst
= NULL
;
7782 if (klass
->generic_class
) {
7783 generic_inst
= mono_class_get_context (klass
);
7784 klass
= klass
->generic_class
->container_class
;
7790 klass
= mono_class_inflate_generic_class_checked (klass
, generic_inst
, &error
);
7791 if (!mono_error_ok (&error
)) {
7792 mono_error_set_pending_exception (&error
);
7797 if (klass
== method
->klass
)
7800 /*This is possible if definition == FALSE.
7801 * Do it here to be really sure we don't read invalid memory.
7803 if (slot
>= klass
->vtable_size
)
7806 mono_class_setup_vtable (klass
);
7808 result
= klass
->vtable
[slot
];
7809 if (result
== NULL
) {
7810 /* It is an abstract method */
7811 gpointer iter
= NULL
;
7812 while ((result
= mono_class_get_methods (klass
, &iter
)))
7813 if (result
->slot
== slot
)
7820 ret
= mono_method_get_object_checked (mono_domain_get (), result
, NULL
, &error
);
7821 mono_error_set_pending_exception (&error
);
7825 ICALL_EXPORT MonoString
*
7826 ves_icall_MonoMethod_get_name (MonoReflectionMethod
*m
)
7828 MonoMethod
*method
= m
->method
;
7830 MONO_OBJECT_SETREF (m
, name
, mono_string_new (mono_object_domain (m
), method
->name
));
7835 mono_ArgIterator_Setup (MonoArgIterator
*iter
, char* argsp
, char* start
)
7837 iter
->sig
= *(MonoMethodSignature
**)argsp
;
7839 g_assert (iter
->sig
->sentinelpos
<= iter
->sig
->param_count
);
7840 g_assert (iter
->sig
->call_convention
== MONO_CALL_VARARG
);
7843 /* FIXME: it's not documented what start is exactly... */
7847 iter
->args
= argsp
+ sizeof (gpointer
);
7849 iter
->num_args
= iter
->sig
->param_count
- iter
->sig
->sentinelpos
;
7851 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7854 ICALL_EXPORT MonoTypedRef
7855 mono_ArgIterator_IntGetNextArg (MonoArgIterator
*iter
)
7857 guint32 i
, arg_size
;
7861 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7863 g_assert (i
< iter
->sig
->param_count
);
7865 res
.type
= iter
->sig
->params
[i
];
7866 res
.klass
= mono_class_from_mono_type (res
.type
);
7867 arg_size
= mono_type_stack_size (res
.type
, &align
);
7868 #if defined(__arm__) || defined(__mips__)
7869 iter
->args
= (guint8
*)(((gsize
)iter
->args
+ (align
) - 1) & ~(align
- 1));
7871 res
.value
= iter
->args
;
7872 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7873 /* Values are stored as 8 byte register sized objects, but 'value'
7874 * is dereferenced as a pointer in other routines.
7876 res
.value
= (char*)res
.value
+ 4;
7878 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7879 if (arg_size
<= sizeof (gpointer
)) {
7881 int padding
= arg_size
- mono_type_size (res
.type
, &dummy
);
7882 res
.value
= (guint8
*)res
.value
+ padding
;
7885 iter
->args
= (char*)iter
->args
+ arg_size
;
7888 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7893 ICALL_EXPORT MonoTypedRef
7894 mono_ArgIterator_IntGetNextArgT (MonoArgIterator
*iter
, MonoType
*type
)
7896 guint32 i
, arg_size
;
7900 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7902 g_assert (i
< iter
->sig
->param_count
);
7904 while (i
< iter
->sig
->param_count
) {
7905 if (!mono_metadata_type_equal (type
, iter
->sig
->params
[i
]))
7907 res
.type
= iter
->sig
->params
[i
];
7908 res
.klass
= mono_class_from_mono_type (res
.type
);
7909 /* FIXME: endianess issue... */
7910 arg_size
= mono_type_stack_size (res
.type
, &align
);
7911 #if defined(__arm__) || defined(__mips__)
7912 iter
->args
= (guint8
*)(((gsize
)iter
->args
+ (align
) - 1) & ~(align
- 1));
7914 res
.value
= iter
->args
;
7915 iter
->args
= (char*)iter
->args
+ arg_size
;
7917 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7920 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7928 ICALL_EXPORT MonoType
*
7929 mono_ArgIterator_IntGetNextArgType (MonoArgIterator
*iter
)
7933 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7935 g_assert (i
< iter
->sig
->param_count
);
7937 return iter
->sig
->params
[i
];
7940 ICALL_EXPORT MonoObject
*
7941 mono_TypedReference_ToObject (MonoTypedRef
* tref
)
7944 MonoObject
*result
= NULL
;
7945 if (MONO_TYPE_IS_REFERENCE (tref
->type
)) {
7946 MonoObject
** objp
= (MonoObject
**)tref
->value
;
7950 result
= mono_value_box_checked (mono_domain_get (), tref
->klass
, tref
->value
, &error
);
7951 mono_error_set_pending_exception (&error
);
7955 ICALL_EXPORT MonoTypedRef
7956 mono_TypedReference_MakeTypedReferenceInternal (MonoObject
*target
, MonoArray
*fields
)
7959 MonoReflectionField
*f
;
7961 MonoType
*ftype
= NULL
;
7965 memset (&res
, 0, sizeof (res
));
7968 g_assert (mono_array_length (fields
) > 0);
7970 klass
= target
->vtable
->klass
;
7972 for (i
= 0; i
< mono_array_length (fields
); ++i
) {
7973 f
= mono_array_get (fields
, MonoReflectionField
*, i
);
7975 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7978 if (f
->field
->parent
!= klass
) {
7979 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7983 p
= (guint8
*)target
+ f
->field
->offset
;
7985 p
+= f
->field
->offset
- sizeof (MonoObject
);
7986 klass
= mono_class_from_mono_type (f
->field
->type
);
7987 ftype
= f
->field
->type
;
7991 res
.klass
= mono_class_from_mono_type (ftype
);
7998 prelink_method (MonoMethod
*method
, MonoError
*error
)
8000 const char *exc_class
, *exc_arg
;
8002 mono_error_init (error
);
8003 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
8005 mono_lookup_pinvoke_call (method
, &exc_class
, &exc_arg
);
8007 mono_error_set_exception_instance (error
,
8008 mono_exception_from_name_msg (mono_defaults
.corlib
, "System", exc_class
, exc_arg
));
8011 /* create the wrapper, too? */
8015 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod
*method
)
8019 prelink_method (method
->method
, &error
);
8020 mono_error_set_pending_exception (&error
);
8024 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType
*type
)
8027 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
8029 gpointer iter
= NULL
;
8031 mono_class_init_checked (klass
, &error
);
8032 if (mono_error_set_pending_exception (&error
))
8035 while ((m
= mono_class_get_methods (klass
, &iter
))) {
8036 prelink_method (m
, &error
);
8037 if (mono_error_set_pending_exception (&error
))
8042 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
8044 ves_icall_System_NumberFormatter_GetFormatterTables (guint64
const **mantissas
,
8045 gint32
const **exponents
,
8046 gunichar2
const **digitLowerTable
,
8047 gunichar2
const **digitUpperTable
,
8048 gint64
const **tenPowersList
,
8049 gint32
const **decHexDigits
)
8051 *mantissas
= Formatter_MantissaBitsTable
;
8052 *exponents
= Formatter_TensExponentTable
;
8053 *digitLowerTable
= Formatter_DigitLowerTable
;
8054 *digitUpperTable
= Formatter_DigitUpperTable
;
8055 *tenPowersList
= Formatter_TenPowersList
;
8056 *decHexDigits
= Formatter_DecHexDigits
;
8060 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
8061 * and avoid useless allocations.
8064 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
, MonoError
*error
)
8066 MonoReflectionType
*rt
;
8070 mono_error_init (error
);
8071 for (i
= 0; i
< type
->num_mods
; ++i
) {
8072 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
))
8077 res
= mono_array_new_checked (mono_domain_get (), mono_defaults
.systemtype_class
, count
, error
);
8078 return_val_if_nok (error
, NULL
);
8080 for (i
= 0; i
< type
->num_mods
; ++i
) {
8081 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
)) {
8082 MonoClass
*klass
= mono_class_get_checked (image
, type
->modifiers
[i
].token
, error
);
8083 return_val_if_nok (error
, NULL
);
8085 rt
= mono_type_get_object_checked (mono_domain_get (), &klass
->byval_arg
, error
);
8086 return_val_if_nok (error
, NULL
);
8088 mono_array_setref (res
, count
, rt
);
8095 ICALL_EXPORT MonoArray
*
8096 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter
*param
, MonoBoolean optional
)
8099 MonoType
*type
= param
->ClassImpl
->type
;
8100 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
8101 MonoMethod
*method
= NULL
;
8104 MonoMethodSignature
*sig
;
8107 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
8108 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
8109 method
= rmethod
->method
;
8110 } else if (member_class
->image
== mono_defaults
.corlib
&& !strcmp ("MonoProperty", member_class
->name
)) {
8111 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
8112 if (!(method
= prop
->property
->get
))
8113 method
= prop
->property
->set
;
8116 char *type_name
= mono_type_get_full_name (member_class
);
8117 char *msg
= g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name
);
8118 MonoException
*ex
= mono_get_exception_not_supported (msg
);
8121 mono_set_pending_exception (ex
);
8125 image
= method
->klass
->image
;
8126 pos
= param
->PositionImpl
;
8127 sig
= mono_method_signature (method
);
8131 type
= sig
->params
[pos
];
8133 res
= type_array_from_modifiers (image
, type
, optional
, &error
);
8134 mono_error_set_pending_exception (&error
);
8139 get_property_type (MonoProperty
*prop
)
8141 MonoMethodSignature
*sig
;
8143 sig
= mono_method_signature (prop
->get
);
8145 } else if (prop
->set
) {
8146 sig
= mono_method_signature (prop
->set
);
8147 return sig
->params
[sig
->param_count
- 1];
8152 ICALL_EXPORT MonoArray
*
8153 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty
*property
, MonoBoolean optional
)
8156 MonoType
*type
= get_property_type (property
->property
);
8157 MonoImage
*image
= property
->klass
->image
;
8162 res
= type_array_from_modifiers (image
, type
, optional
, &error
);
8163 mono_error_set_pending_exception (&error
);
8168 *Construct a MonoType suited to be used to decode a constant blob object.
8170 * @type is the target type which will be constructed
8171 * @blob_type is the blob type, for example, that comes from the constant table
8172 * @real_type is the expected constructed type.
8175 mono_type_from_blob_type (MonoType
*type
, MonoTypeEnum blob_type
, MonoType
*real_type
)
8177 type
->type
= blob_type
;
8178 type
->data
.klass
= NULL
;
8179 if (blob_type
== MONO_TYPE_CLASS
)
8180 type
->data
.klass
= mono_defaults
.object_class
;
8181 else if (real_type
->type
== MONO_TYPE_VALUETYPE
&& real_type
->data
.klass
->enumtype
) {
8182 /* For enums, we need to use the base type */
8183 type
->type
= MONO_TYPE_VALUETYPE
;
8184 type
->data
.klass
= mono_class_from_mono_type (real_type
);
8186 type
->data
.klass
= mono_class_from_mono_type (real_type
);
8189 ICALL_EXPORT MonoObject
*
8190 property_info_get_default_value (MonoReflectionProperty
*property
)
8194 MonoProperty
*prop
= property
->property
;
8195 MonoType
*type
= get_property_type (prop
);
8196 MonoDomain
*domain
= mono_object_domain (property
);
8197 MonoTypeEnum def_type
;
8198 const char *def_value
;
8201 mono_class_init (prop
->parent
);
8203 if (!(prop
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
)) {
8204 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL
));
8208 def_value
= mono_class_get_property_default_value (prop
, &def_type
);
8210 mono_type_from_blob_type (&blob_type
, def_type
, type
);
8211 o
= mono_get_object_from_blob (domain
, &blob_type
, def_value
, &error
);
8213 mono_error_set_pending_exception (&error
);
8217 ICALL_EXPORT MonoBoolean
8218 custom_attrs_defined_internal (MonoObject
*obj
, MonoReflectionType
*attr_type
)
8221 MonoClass
*attr_class
= mono_class_from_mono_type (attr_type
->type
);
8222 MonoCustomAttrInfo
*cinfo
;
8225 mono_class_init_checked (attr_class
, &error
);
8226 if (mono_error_set_pending_exception (&error
))
8229 cinfo
= mono_reflection_get_custom_attrs_info_checked (obj
, &error
);
8230 if (!is_ok (&error
)) {
8231 mono_error_set_pending_exception (&error
);
8236 found
= mono_custom_attrs_has_attr (cinfo
, attr_class
);
8238 mono_custom_attrs_free (cinfo
);
8242 ICALL_EXPORT MonoArray
*
8243 custom_attrs_get_by_type (MonoObject
*obj
, MonoReflectionType
*attr_type
)
8245 MonoClass
*attr_class
= attr_type
? mono_class_from_mono_type (attr_type
->type
) : NULL
;
8250 mono_class_init_checked (attr_class
, &error
);
8251 if (mono_error_set_pending_exception (&error
))
8255 res
= mono_reflection_get_custom_attrs_by_type (obj
, attr_class
, &error
);
8256 if (!mono_error_ok (&error
)) {
8257 mono_error_set_pending_exception (&error
);
8264 ICALL_EXPORT MonoArray
*
8265 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject
*obj
)
8269 result
= mono_reflection_get_custom_attrs_data_checked (obj
, &error
);
8270 mono_error_set_pending_exception (&error
);
8275 ICALL_EXPORT MonoString
*
8276 ves_icall_Mono_Runtime_GetDisplayName (void)
8279 MonoString
*display_name
;
8281 info
= mono_get_runtime_callbacks ()->get_runtime_build_info ();
8282 display_name
= mono_string_new (mono_domain_get (), info
);
8284 return display_name
;
8287 ICALL_EXPORT MonoString
*
8288 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code
)
8291 MonoString
*message
;
8295 ret
= FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
8296 FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, code
, 0,
8299 message
= mono_string_new (mono_domain_get (), "Error looking up error string");
8301 message
= mono_string_new_utf16_checked (mono_domain_get (), buf
, ret
, &error
);
8302 if (mono_error_set_pending_exception (&error
))
8309 ICALL_EXPORT gpointer
8310 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8312 return GetCurrentProcess ();
8315 ICALL_EXPORT MonoBoolean
8316 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle
, gint32
*exitcode
)
8318 return GetExitCodeProcess (handle
, (guint32
*) exitcode
);
8321 ICALL_EXPORT MonoBoolean
8322 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle
)
8324 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8325 return CloseHandle (handle
);
8327 return CloseProcess (handle
);
8331 ICALL_EXPORT MonoBoolean
8332 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle
, gint32 exitcode
)
8334 return TerminateProcess (handle
, exitcode
);
8338 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle
, gint32 milliseconds
)
8340 return WaitForInputIdle (handle
, milliseconds
);
8343 ICALL_EXPORT MonoBoolean
8344 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle
, gsize
*min
, gsize
*max
)
8346 return GetProcessWorkingSetSize (handle
, min
, max
);
8349 ICALL_EXPORT MonoBoolean
8350 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle
, gsize min
, gsize max
)
8352 return SetProcessWorkingSetSize (handle
, min
, max
);
8355 ICALL_EXPORT MonoBoolean
8356 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle
, gint64
*creationtime
, gint64
*exittime
, gint64
*kerneltime
, gint64
*usertime
)
8358 return GetProcessTimes (handle
, (LPFILETIME
) creationtime
, (LPFILETIME
) exittime
, (LPFILETIME
) kerneltime
, (LPFILETIME
) usertime
);
8362 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8364 return mono_process_current_pid ();
8368 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle
)
8370 return GetPriorityClass (handle
);
8373 ICALL_EXPORT MonoBoolean
8374 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle
, gint32 priorityClass
)
8376 return SetPriorityClass (handle
, priorityClass
);
8379 #ifndef DISABLE_ICALL_TABLES
8381 #define ICALL_TYPE(id,name,first)
8382 #define ICALL(id,name,func) Icall_ ## id,
8385 #include "metadata/icall-def.h"
8391 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8392 #define ICALL(id,name,func)
8394 #include "metadata/icall-def.h"
8400 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8401 #define ICALL(id,name,func)
8403 guint16 first_icall
;
8406 static const IcallTypeDesc
8407 icall_type_descs
[] = {
8408 #include "metadata/icall-def.h"
8412 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8415 #define ICALL_TYPE(id,name,first)
8418 #ifdef HAVE_ARRAY_ELEM_INIT
8419 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8420 #define MSGSTRFIELD1(line) str##line
8422 static const struct msgstrtn_t
{
8423 #define ICALL(id,name,func)
8425 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8426 #include "metadata/icall-def.h"
8428 } icall_type_names_str
= {
8429 #define ICALL_TYPE(id,name,first) (name),
8430 #include "metadata/icall-def.h"
8433 static const guint16 icall_type_names_idx
[] = {
8434 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8435 #include "metadata/icall-def.h"
8438 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8440 static const struct msgstr_t
{
8442 #define ICALL_TYPE(id,name,first)
8443 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8444 #include "metadata/icall-def.h"
8446 } icall_names_str
= {
8447 #define ICALL(id,name,func) (name),
8448 #include "metadata/icall-def.h"
8451 static const guint16 icall_names_idx
[] = {
8452 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8453 #include "metadata/icall-def.h"
8456 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8462 #define ICALL_TYPE(id,name,first) name,
8463 #define ICALL(id,name,func)
8464 static const char* const
8465 icall_type_names
[] = {
8466 #include "metadata/icall-def.h"
8470 #define icall_type_name_get(id) (icall_type_names [(id)])
8474 #define ICALL_TYPE(id,name,first)
8475 #define ICALL(id,name,func) name,
8476 static const char* const
8478 #include "metadata/icall-def.h"
8481 #define icall_name_get(id) icall_names [(id)]
8483 #endif /* !HAVE_ARRAY_ELEM_INIT */
8487 #define ICALL_TYPE(id,name,first)
8488 #define ICALL(id,name,func) func,
8489 static const gconstpointer
8490 icall_functions
[] = {
8491 #include "metadata/icall-def.h"
8495 #ifdef ENABLE_ICALL_SYMBOL_MAP
8498 #define ICALL_TYPE(id,name,first)
8499 #define ICALL(id,name,func) #func,
8500 static const gconstpointer
8501 icall_symbols
[] = {
8502 #include "metadata/icall-def.h"
8507 #endif /* DISABLE_ICALL_TABLES */
8509 static mono_mutex_t icall_mutex
;
8510 static GHashTable
*icall_hash
= NULL
;
8511 static GHashTable
*jit_icall_hash_name
= NULL
;
8512 static GHashTable
*jit_icall_hash_addr
= NULL
;
8515 mono_icall_init (void)
8517 #ifndef DISABLE_ICALL_TABLES
8520 /* check that tables are sorted: disable in release */
8523 const char *prev_class
= NULL
;
8524 const char *prev_method
;
8526 for (i
= 0; i
< Icall_type_num
; ++i
) {
8527 const IcallTypeDesc
*desc
;
8530 if (prev_class
&& strcmp (prev_class
, icall_type_name_get (i
)) >= 0)
8531 g_print ("class %s should come before class %s\n", icall_type_name_get (i
), prev_class
);
8532 prev_class
= icall_type_name_get (i
);
8533 desc
= &icall_type_descs
[i
];
8534 num_icalls
= icall_desc_num_icalls (desc
);
8535 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8536 for (j
= 0; j
< num_icalls
; ++j
) {
8537 const char *methodn
= icall_name_get (desc
->first_icall
+ j
);
8538 if (prev_method
&& strcmp (prev_method
, methodn
) >= 0)
8539 g_print ("method %s should come before method %s\n", methodn
, prev_method
);
8540 prev_method
= methodn
;
8546 icall_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
8547 mono_os_mutex_init (&icall_mutex
);
8551 mono_icall_lock (void)
8553 mono_locks_os_acquire (&icall_mutex
, IcallLock
);
8557 mono_icall_unlock (void)
8559 mono_locks_os_release (&icall_mutex
, IcallLock
);
8563 mono_icall_cleanup (void)
8565 g_hash_table_destroy (icall_hash
);
8566 g_hash_table_destroy (jit_icall_hash_name
);
8567 g_hash_table_destroy (jit_icall_hash_addr
);
8568 mono_os_mutex_destroy (&icall_mutex
);
8572 * mono_add_internal_call:
8573 * @name: method specification to surface to the managed world
8574 * @method: pointer to a C method to invoke when the method is called
8576 * This method surfaces the C function pointed by @method as a method
8577 * that has been surfaced in managed code with the method specified in
8578 * @name as an internal call.
8580 * Internal calls are surfaced to all app domains loaded and they are
8581 * accessibly by a type with the specified name.
8583 * You must provide a fully qualified type name, that is namespaces
8584 * and type name, followed by a colon and the method name, with an
8585 * optional signature to bind.
8587 * For example, the following are all valid declarations:
8589 * "MyApp.Services.ScriptService:Accelerate"
8590 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8592 * You use method parameters in cases where there might be more than
8593 * one surface method to managed code. That way you can register different
8594 * internal calls for different method overloads.
8596 * The internal calls are invoked with no marshalling. This means that .NET
8597 * types like System.String are exposed as `MonoString *` parameters. This is
8598 * different than the way that strings are surfaced in P/Invoke.
8600 * For more information on how the parameters are marshalled, see the
8601 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8604 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8605 * reference for more information on the format of method descriptions.
8608 mono_add_internal_call (const char *name
, gconstpointer method
)
8612 g_hash_table_insert (icall_hash
, g_strdup (name
), (gpointer
) method
);
8614 mono_icall_unlock ();
8617 #ifndef DISABLE_ICALL_TABLES
8619 #ifdef HAVE_ARRAY_ELEM_INIT
8621 compare_method_imap (const void *key
, const void *elem
)
8623 const char* method_name
= (const char*)&icall_names_str
+ (*(guint16
*)elem
);
8624 return strcmp (key
, method_name
);
8628 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
8630 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
);
8633 return (gpointer
)icall_functions
[(nameslot
- &icall_names_idx
[0])];
8637 compare_class_imap (const void *key
, const void *elem
)
8639 const char* class_name
= (const char*)&icall_type_names_str
+ (*(guint16
*)elem
);
8640 return strcmp (key
, class_name
);
8643 static const IcallTypeDesc
*
8644 find_class_icalls (const char *name
)
8646 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
);
8649 return &icall_type_descs
[nameslot
- &icall_type_names_idx
[0]];
8652 #else /* HAVE_ARRAY_ELEM_INIT */
8655 compare_method_imap (const void *key
, const void *elem
)
8657 const char** method_name
= (const char**)elem
;
8658 return strcmp (key
, *method_name
);
8662 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
8664 const char **nameslot
= mono_binary_search (name
, icall_names
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names
[0]), compare_method_imap
);
8667 return (gpointer
)icall_functions
[(nameslot
- icall_names
)];
8671 compare_class_imap (const void *key
, const void *elem
)
8673 const char** class_name
= (const char**)elem
;
8674 return strcmp (key
, *class_name
);
8677 static const IcallTypeDesc
*
8678 find_class_icalls (const char *name
)
8680 const char **nameslot
= mono_binary_search (name
, icall_type_names
, Icall_type_num
, sizeof (icall_type_names
[0]), compare_class_imap
);
8683 return &icall_type_descs
[nameslot
- icall_type_names
];
8686 #endif /* HAVE_ARRAY_ELEM_INIT */
8688 #endif /* DISABLE_ICALL_TABLES */
8691 * we should probably export this as an helper (handle nested types).
8692 * Returns the number of chars written in buf.
8695 concat_class_name (char *buf
, int bufsize
, MonoClass
*klass
)
8697 int nspacelen
, cnamelen
;
8698 nspacelen
= strlen (klass
->name_space
);
8699 cnamelen
= strlen (klass
->name
);
8700 if (nspacelen
+ cnamelen
+ 2 > bufsize
)
8703 memcpy (buf
, klass
->name_space
, nspacelen
);
8704 buf
[nspacelen
++] = '.';
8706 memcpy (buf
+ nspacelen
, klass
->name
, cnamelen
);
8707 buf
[nspacelen
+ cnamelen
] = 0;
8708 return nspacelen
+ cnamelen
;
8711 #ifdef DISABLE_ICALL_TABLES
8713 no_icall_table (void)
8715 g_assert_not_reached ();
8720 mono_lookup_internal_call (MonoMethod
*method
)
8725 int typelen
= 0, mlen
, siglen
;
8727 #ifndef DISABLE_ICALL_TABLES
8728 const IcallTypeDesc
*imap
= NULL
;
8731 g_assert (method
!= NULL
);
8733 if (method
->is_inflated
)
8734 method
= ((MonoMethodInflated
*) method
)->declaring
;
8736 if (method
->klass
->nested_in
) {
8737 int pos
= concat_class_name (mname
, sizeof (mname
)-2, method
->klass
->nested_in
);
8741 mname
[pos
++] = '/';
8744 typelen
= concat_class_name (mname
+pos
, sizeof (mname
)-pos
-1, method
->klass
);
8750 typelen
= concat_class_name (mname
, sizeof (mname
), method
->klass
);
8755 #ifndef DISABLE_ICALL_TABLES
8756 imap
= find_class_icalls (mname
);
8759 mname
[typelen
] = ':';
8760 mname
[typelen
+ 1] = ':';
8762 mlen
= strlen (method
->name
);
8763 memcpy (mname
+ typelen
+ 2, method
->name
, mlen
);
8764 sigstart
= mname
+ typelen
+ 2 + mlen
;
8767 tmpsig
= mono_signature_get_desc (mono_method_signature (method
), TRUE
);
8768 siglen
= strlen (tmpsig
);
8769 if (typelen
+ mlen
+ siglen
+ 6 > sizeof (mname
))
8772 memcpy (sigstart
+ 1, tmpsig
, siglen
);
8773 sigstart
[siglen
+ 1] = ')';
8774 sigstart
[siglen
+ 2] = 0;
8779 res
= g_hash_table_lookup (icall_hash
, mname
);
8781 mono_icall_unlock ();;
8784 /* try without signature */
8786 res
= g_hash_table_lookup (icall_hash
, mname
);
8788 mono_icall_unlock ();
8792 #ifdef DISABLE_ICALL_TABLES
8793 mono_icall_unlock ();
8794 /* Fail only when the result is actually used */
8795 /* mono_marshal_get_native_wrapper () depends on this */
8796 if (method
->klass
== mono_defaults
.string_class
&& !strcmp (method
->name
, ".ctor"))
8797 return ves_icall_System_String_ctor_RedirectToCreateString
;
8799 return no_icall_table
;
8801 /* it wasn't found in the static call tables */
8803 mono_icall_unlock ();
8806 res
= find_method_icall (imap
, sigstart
- mlen
);
8808 mono_icall_unlock ();
8811 /* try _with_ signature */
8813 res
= find_method_icall (imap
, sigstart
- mlen
);
8815 mono_icall_unlock ();
8819 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname
);
8820 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8821 g_print ("The out of sync library is: %s\n", method
->klass
->image
->name
);
8822 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8823 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");
8824 g_print ("If you see other errors or faults after this message they are probably related\n");
8825 g_print ("and you need to fix your mono install first.\n");
8827 mono_icall_unlock ();
8833 #ifdef ENABLE_ICALL_SYMBOL_MAP
8835 func_cmp (gconstpointer key
, gconstpointer p
)
8837 return (gsize
)key
- (gsize
)*(gsize
*)p
;
8842 * mono_lookup_icall_symbol:
8844 * Given the icall METHOD, returns its C symbol.
8847 mono_lookup_icall_symbol (MonoMethod
*m
)
8849 #ifdef DISABLE_ICALL_TABLES
8850 g_assert_not_reached ();
8853 #ifdef ENABLE_ICALL_SYMBOL_MAP
8857 static gconstpointer
*functions_sorted
;
8858 static const char**symbols_sorted
;
8859 static gboolean inited
;
8864 functions_sorted
= g_malloc (G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
8865 memcpy (functions_sorted
, icall_functions
, G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
8866 symbols_sorted
= g_malloc (G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
8867 memcpy (symbols_sorted
, icall_symbols
, G_N_ELEMENTS (icall_functions
) * sizeof (gpointer
));
8868 /* Bubble sort the two arrays */
8872 for (i
= 0; i
< G_N_ELEMENTS (icall_functions
) - 1; ++i
) {
8873 if (functions_sorted
[i
] > functions_sorted
[i
+ 1]) {
8876 tmp
= functions_sorted
[i
];
8877 functions_sorted
[i
] = functions_sorted
[i
+ 1];
8878 functions_sorted
[i
+ 1] = tmp
;
8879 tmp
= symbols_sorted
[i
];
8880 symbols_sorted
[i
] = symbols_sorted
[i
+ 1];
8881 symbols_sorted
[i
+ 1] = tmp
;
8888 func
= mono_lookup_internal_call (m
);
8891 slot
= mono_binary_search (func
, functions_sorted
, G_N_ELEMENTS (icall_functions
), sizeof (gpointer
), func_cmp
);
8895 return symbols_sorted
[(gpointer
*)slot
- (gpointer
*)functions_sorted
];
8897 fprintf (stderr
, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8898 g_assert_not_reached ();
8905 type_from_typename (char *type_name
)
8907 MonoClass
*klass
= NULL
; /* assignment to shut GCC warning up */
8909 if (!strcmp (type_name
, "int"))
8910 klass
= mono_defaults
.int_class
;
8911 else if (!strcmp (type_name
, "ptr"))
8912 klass
= mono_defaults
.int_class
;
8913 else if (!strcmp (type_name
, "void"))
8914 klass
= mono_defaults
.void_class
;
8915 else if (!strcmp (type_name
, "int32"))
8916 klass
= mono_defaults
.int32_class
;
8917 else if (!strcmp (type_name
, "uint32"))
8918 klass
= mono_defaults
.uint32_class
;
8919 else if (!strcmp (type_name
, "int8"))
8920 klass
= mono_defaults
.sbyte_class
;
8921 else if (!strcmp (type_name
, "uint8"))
8922 klass
= mono_defaults
.byte_class
;
8923 else if (!strcmp (type_name
, "int16"))
8924 klass
= mono_defaults
.int16_class
;
8925 else if (!strcmp (type_name
, "uint16"))
8926 klass
= mono_defaults
.uint16_class
;
8927 else if (!strcmp (type_name
, "long"))
8928 klass
= mono_defaults
.int64_class
;
8929 else if (!strcmp (type_name
, "ulong"))
8930 klass
= mono_defaults
.uint64_class
;
8931 else if (!strcmp (type_name
, "float"))
8932 klass
= mono_defaults
.single_class
;
8933 else if (!strcmp (type_name
, "double"))
8934 klass
= mono_defaults
.double_class
;
8935 else if (!strcmp (type_name
, "object"))
8936 klass
= mono_defaults
.object_class
;
8937 else if (!strcmp (type_name
, "obj"))
8938 klass
= mono_defaults
.object_class
;
8939 else if (!strcmp (type_name
, "string"))
8940 klass
= mono_defaults
.string_class
;
8941 else if (!strcmp (type_name
, "bool"))
8942 klass
= mono_defaults
.boolean_class
;
8943 else if (!strcmp (type_name
, "boolean"))
8944 klass
= mono_defaults
.boolean_class
;
8946 g_error ("%s", type_name
);
8947 g_assert_not_reached ();
8949 return &klass
->byval_arg
;
8953 * LOCKING: Take the corlib image lock.
8955 MonoMethodSignature
*
8956 mono_create_icall_signature (const char *sigstr
)
8961 MonoMethodSignature
*res
, *res2
;
8962 MonoImage
*corlib
= mono_defaults
.corlib
;
8964 mono_image_lock (corlib
);
8965 res
= (MonoMethodSignature
*)g_hash_table_lookup (corlib
->helper_signatures
, sigstr
);
8966 mono_image_unlock (corlib
);
8971 parts
= g_strsplit (sigstr
, " ", 256);
8980 res
= mono_metadata_signature_alloc (corlib
, len
- 1);
8985 * Under windows, the default pinvoke calling convention is STDCALL but
8988 res
->call_convention
= MONO_CALL_C
;
8991 res
->ret
= type_from_typename (parts
[0]);
8992 for (i
= 1; i
< len
; ++i
) {
8993 res
->params
[i
- 1] = type_from_typename (parts
[i
]);
8998 mono_image_lock (corlib
);
8999 res2
= (MonoMethodSignature
*)g_hash_table_lookup (corlib
->helper_signatures
, sigstr
);
9001 res
= res2
; /*Value is allocated in the image pool*/
9003 g_hash_table_insert (corlib
->helper_signatures
, (gpointer
)sigstr
, res
);
9004 mono_image_unlock (corlib
);
9010 mono_find_jit_icall_by_name (const char *name
)
9012 MonoJitICallInfo
*info
;
9013 g_assert (jit_icall_hash_name
);
9016 info
= (MonoJitICallInfo
*)g_hash_table_lookup (jit_icall_hash_name
, name
);
9017 mono_icall_unlock ();
9022 mono_find_jit_icall_by_addr (gconstpointer addr
)
9024 MonoJitICallInfo
*info
;
9025 g_assert (jit_icall_hash_addr
);
9028 info
= (MonoJitICallInfo
*)g_hash_table_lookup (jit_icall_hash_addr
, (gpointer
)addr
);
9029 mono_icall_unlock ();
9035 * mono_get_jit_icall_info:
9037 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
9038 * caller should access it while holding the icall lock.
9041 mono_get_jit_icall_info (void)
9043 return jit_icall_hash_name
;
9047 * mono_lookup_jit_icall_symbol:
9049 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
9052 mono_lookup_jit_icall_symbol (const char *name
)
9054 MonoJitICallInfo
*info
;
9055 const char *res
= NULL
;
9058 info
= (MonoJitICallInfo
*)g_hash_table_lookup (jit_icall_hash_name
, name
);
9060 res
= info
->c_symbol
;
9061 mono_icall_unlock ();
9066 mono_register_jit_icall_wrapper (MonoJitICallInfo
*info
, gconstpointer wrapper
)
9069 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)wrapper
, info
);
9070 mono_icall_unlock ();
9074 * 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
9075 * icalls without wrappers in some cases.
9078 mono_register_jit_icall_full (gconstpointer func
, const char *name
, MonoMethodSignature
*sig
, gboolean is_save
, gboolean no_raise
, const char *c_symbol
)
9080 MonoJitICallInfo
*info
;
9087 if (!jit_icall_hash_name
) {
9088 jit_icall_hash_name
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, g_free
);
9089 jit_icall_hash_addr
= g_hash_table_new (NULL
, NULL
);
9092 if (g_hash_table_lookup (jit_icall_hash_name
, name
)) {
9093 g_warning ("jit icall already defined \"%s\"\n", name
);
9094 g_assert_not_reached ();
9097 info
= g_new0 (MonoJitICallInfo
, 1);
9102 info
->c_symbol
= c_symbol
;
9103 info
->no_raise
= no_raise
;
9106 info
->wrapper
= func
;
9108 info
->wrapper
= NULL
;
9111 g_hash_table_insert (jit_icall_hash_name
, (gpointer
)info
->name
, info
);
9112 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)func
, info
);
9114 mono_icall_unlock ();
9119 mono_register_jit_icall (gconstpointer func
, const char *name
, MonoMethodSignature
*sig
, gboolean is_save
)
9121 return mono_register_jit_icall_full (func
, name
, sig
, is_save
, FALSE
, NULL
);