5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
21 #ifdef HAVE_SYS_TIME_H
27 #if defined (HOST_WIN32)
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/io-layer/io-layer.h>
71 #include <mono/utils/strtod.h>
72 #include <mono/utils/monobitset.h>
73 #include <mono/utils/mono-time.h>
74 #include <mono/utils/mono-proclib.h>
75 #include <mono/utils/mono-string.h>
76 #include <mono/utils/mono-error-internals.h>
77 #include <mono/utils/mono-mmap.h>
79 #if defined (HOST_WIN32)
85 extern MonoString
* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL
;
87 static MonoReflectionAssembly
* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
90 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
);
92 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
93 * It works by allocating an initial small array on stack and only going to malloc'd memory if needed.
101 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
103 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\
105 (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
106 (ARRAY).data = INITIAL_SIZE > MONO_PTR_ARRAY_MAX_ON_STACK ? mono_gc_alloc_fixed (sizeof (void*) * INITIAL_SIZE, NULL) : g_newa (void*, MONO_PTR_ARRAY_MAX_ON_STACK); \
109 #define mono_ptr_array_destroy(ARRAY) do {\
110 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
111 mono_gc_free_fixed ((ARRAY).data); \
114 #define mono_ptr_array_append(ARRAY, VALUE) do { \
115 if ((ARRAY).size >= (ARRAY).capacity) {\
116 void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \
117 memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
118 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
119 mono_gc_free_fixed ((ARRAY).data); \
120 (ARRAY).data = __tmp; \
121 (ARRAY).capacity *= 2;\
123 ((ARRAY).data [(ARRAY).size++] = VALUE); \
126 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
127 ((ARRAY).data [(IDX)] = VALUE); \
130 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
132 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
135 static inline MonoBoolean
136 is_generic_parameter (MonoType
*type
)
138 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
142 * We expect a pointer to a char, not a string
145 mono_double_ParseImpl (char *ptr
, double *result
)
147 gchar
*endptr
= NULL
;
154 *result
= strtod (ptr
, &endptr
);
158 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
159 EnterCriticalSection (&mono_strtod_mutex
);
160 *result
= mono_strtod (ptr
, &endptr
);
161 LeaveCriticalSection (&mono_strtod_mutex
);
163 *result
= mono_strtod (ptr
, &endptr
);
168 if (!*ptr
|| (endptr
&& *endptr
))
175 ves_icall_System_Array_GetValueImpl (MonoObject
*this, guint32 pos
)
184 ao
= (MonoArray
*)this;
185 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
187 esize
= mono_array_element_size (ac
);
188 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
190 if (ac
->element_class
->valuetype
)
191 return mono_value_box (this->vtable
->domain
, ac
->element_class
, ea
);
197 ves_icall_System_Array_GetValue (MonoObject
*this, MonoObject
*idxs
)
205 MONO_CHECK_ARG_NULL (idxs
);
207 io
= (MonoArray
*)idxs
;
208 ic
= (MonoClass
*)io
->obj
.vtable
->klass
;
210 ao
= (MonoArray
*)this;
211 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
213 g_assert (ic
->rank
== 1);
214 if (io
->bounds
!= NULL
|| io
->max_length
!= ac
->rank
)
215 mono_raise_exception (mono_get_exception_argument (NULL
, NULL
));
217 ind
= (gint32
*)io
->vector
;
219 if (ao
->bounds
== NULL
) {
220 if (*ind
< 0 || *ind
>= ao
->max_length
)
221 mono_raise_exception (mono_get_exception_index_out_of_range ());
223 return ves_icall_System_Array_GetValueImpl (this, *ind
);
226 for (i
= 0; i
< ac
->rank
; i
++)
227 if ((ind
[i
] < ao
->bounds
[i
].lower_bound
) ||
228 (ind
[i
] >= (mono_array_lower_bound_t
)ao
->bounds
[i
].length
+ ao
->bounds
[i
].lower_bound
))
229 mono_raise_exception (mono_get_exception_index_out_of_range ());
231 pos
= ind
[0] - ao
->bounds
[0].lower_bound
;
232 for (i
= 1; i
< ac
->rank
; i
++)
233 pos
= pos
*ao
->bounds
[i
].length
+ ind
[i
] -
234 ao
->bounds
[i
].lower_bound
;
236 return ves_icall_System_Array_GetValueImpl (this, pos
);
240 ves_icall_System_Array_SetValueImpl (MonoArray
*this, MonoObject
*value
, guint32 pos
)
242 MonoClass
*ac
, *vc
, *ec
;
254 vc
= value
->vtable
->klass
;
258 ac
= this->obj
.vtable
->klass
;
259 ec
= ac
->element_class
;
261 esize
= mono_array_element_size (ac
);
262 ea
= (gpointer
*)((char*)this->vector
+ (pos
* esize
));
263 va
= (gpointer
*)((char*)value
+ sizeof (MonoObject
));
265 if (mono_class_is_nullable (ec
)) {
266 mono_nullable_init ((guint8
*)ea
, value
, ec
);
271 memset (ea
, 0, esize
);
275 #define NO_WIDENING_CONVERSION G_STMT_START{\
276 mono_raise_exception (mono_get_exception_argument ( \
277 "value", "not a widening conversion")); \
280 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
281 if (esize < vsize + (extra)) \
282 mono_raise_exception (mono_get_exception_argument ( \
283 "value", "not a widening conversion")); \
286 #define INVALID_CAST G_STMT_START{\
287 mono_raise_exception (mono_get_exception_invalid_cast ()); \
290 /* Check element (destination) type. */
291 switch (ec
->byval_arg
.type
) {
292 case MONO_TYPE_STRING
:
293 switch (vc
->byval_arg
.type
) {
294 case MONO_TYPE_STRING
:
300 case MONO_TYPE_BOOLEAN
:
301 switch (vc
->byval_arg
.type
) {
302 case MONO_TYPE_BOOLEAN
:
315 NO_WIDENING_CONVERSION
;
322 if (!ec
->valuetype
) {
323 if (!mono_object_isinst (value
, ec
))
325 mono_gc_wbarrier_set_arrayref (this, ea
, (MonoObject
*)value
);
329 if (mono_object_isinst (value
, ec
)) {
330 if (ec
->has_references
)
331 mono_value_copy (ea
, (char*)value
+ sizeof (MonoObject
), ec
);
333 memcpy (ea
, (char *)value
+ sizeof (MonoObject
), esize
);
340 vsize
= mono_class_instance_size (vc
) - sizeof (MonoObject
);
342 et
= ec
->byval_arg
.type
;
343 if (et
== MONO_TYPE_VALUETYPE
&& ec
->byval_arg
.data
.klass
->enumtype
)
344 et
= mono_class_enum_basetype (ec
->byval_arg
.data
.klass
)->type
;
346 vt
= vc
->byval_arg
.type
;
347 if (vt
== MONO_TYPE_VALUETYPE
&& vc
->byval_arg
.data
.klass
->enumtype
)
348 vt
= mono_class_enum_basetype (vc
->byval_arg
.data
.klass
)->type
;
350 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
356 case MONO_TYPE_CHAR: \
357 CHECK_WIDENING_CONVERSION(0); \
358 *(etype *) ea = (etype) u64; \
360 /* You can't assign a signed value to an unsigned array. */ \
365 /* You can't assign a floating point number to an integer array. */ \
368 NO_WIDENING_CONVERSION; \
372 #define ASSIGN_SIGNED(etype) G_STMT_START{\
378 CHECK_WIDENING_CONVERSION(0); \
379 *(etype *) ea = (etype) i64; \
381 /* You can assign an unsigned value to a signed array if the array's */ \
382 /* element size is larger than the value size. */ \
387 case MONO_TYPE_CHAR: \
388 CHECK_WIDENING_CONVERSION(1); \
389 *(etype *) ea = (etype) u64; \
391 /* You can't assign a floating point number to an integer array. */ \
394 NO_WIDENING_CONVERSION; \
398 #define ASSIGN_REAL(etype) G_STMT_START{\
402 CHECK_WIDENING_CONVERSION(0); \
403 *(etype *) ea = (etype) r64; \
405 /* All integer values fit into a floating point array, so we don't */ \
406 /* need to CHECK_WIDENING_CONVERSION here. */ \
411 *(etype *) ea = (etype) i64; \
417 case MONO_TYPE_CHAR: \
418 *(etype *) ea = (etype) u64; \
425 u64
= *(guint8
*) va
;
428 u64
= *(guint16
*) va
;
431 u64
= *(guint32
*) va
;
434 u64
= *(guint64
*) va
;
440 i64
= *(gint16
*) va
;
443 i64
= *(gint32
*) va
;
446 i64
= *(gint64
*) va
;
449 r64
= *(gfloat
*) va
;
452 r64
= *(gdouble
*) va
;
455 u64
= *(guint16
*) va
;
457 case MONO_TYPE_BOOLEAN
:
458 /* Boolean is only compatible with itself. */
471 NO_WIDENING_CONVERSION
;
478 /* If we can't do a direct copy, let's try a widening conversion. */
481 ASSIGN_UNSIGNED (guint16
);
483 ASSIGN_UNSIGNED (guint8
);
485 ASSIGN_UNSIGNED (guint16
);
487 ASSIGN_UNSIGNED (guint32
);
489 ASSIGN_UNSIGNED (guint64
);
491 ASSIGN_SIGNED (gint8
);
493 ASSIGN_SIGNED (gint16
);
495 ASSIGN_SIGNED (gint32
);
497 ASSIGN_SIGNED (gint64
);
499 ASSIGN_REAL (gfloat
);
501 ASSIGN_REAL (gdouble
);
505 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
509 #undef NO_WIDENING_CONVERSION
510 #undef CHECK_WIDENING_CONVERSION
511 #undef ASSIGN_UNSIGNED
517 ves_icall_System_Array_SetValue (MonoArray
*this, MonoObject
*value
,
525 MONO_CHECK_ARG_NULL (idxs
);
527 ic
= idxs
->obj
.vtable
->klass
;
528 ac
= this->obj
.vtable
->klass
;
530 g_assert (ic
->rank
== 1);
531 if (idxs
->bounds
!= NULL
|| idxs
->max_length
!= ac
->rank
)
532 mono_raise_exception (mono_get_exception_argument (NULL
, NULL
));
534 ind
= (gint32
*)idxs
->vector
;
536 if (this->bounds
== NULL
) {
537 if (*ind
< 0 || *ind
>= this->max_length
)
538 mono_raise_exception (mono_get_exception_index_out_of_range ());
540 ves_icall_System_Array_SetValueImpl (this, value
, *ind
);
544 for (i
= 0; i
< ac
->rank
; i
++)
545 if ((ind
[i
] < this->bounds
[i
].lower_bound
) ||
546 (ind
[i
] >= (mono_array_lower_bound_t
)this->bounds
[i
].length
+ this->bounds
[i
].lower_bound
))
547 mono_raise_exception (mono_get_exception_index_out_of_range ());
549 pos
= ind
[0] - this->bounds
[0].lower_bound
;
550 for (i
= 1; i
< ac
->rank
; i
++)
551 pos
= pos
* this->bounds
[i
].length
+ ind
[i
] -
552 this->bounds
[i
].lower_bound
;
554 ves_icall_System_Array_SetValueImpl (this, value
, pos
);
558 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType
*type
, MonoArray
*lengths
, MonoArray
*bounds
)
562 mono_array_size_t
*sizes
, i
;
563 gboolean bounded
= FALSE
;
567 MONO_CHECK_ARG_NULL (type
);
568 MONO_CHECK_ARG_NULL (lengths
);
570 MONO_CHECK_ARG (lengths
, mono_array_length (lengths
) > 0);
572 MONO_CHECK_ARG (bounds
, mono_array_length (lengths
) == mono_array_length (bounds
));
574 for (i
= 0; i
< mono_array_length (lengths
); i
++)
575 if (mono_array_get (lengths
, gint32
, i
) < 0)
576 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL
));
578 if (bounds
&& (mono_array_length (bounds
) == 1) && (mono_array_get (bounds
, gint32
, 0) != 0))
579 /* vectors are not the same as one dimensional arrays with no-zero bounds */
584 aklass
= mono_bounded_array_class_get (mono_class_from_mono_type (type
->type
), mono_array_length (lengths
), bounded
);
586 sizes
= alloca (aklass
->rank
* sizeof(mono_array_size_t
) * 2);
587 for (i
= 0; i
< aklass
->rank
; ++i
) {
588 sizes
[i
] = mono_array_get (lengths
, guint32
, i
);
590 sizes
[i
+ aklass
->rank
] = mono_array_get (bounds
, guint32
, i
);
592 sizes
[i
+ aklass
->rank
] = 0;
595 array
= mono_array_new_full (mono_object_domain (type
), aklass
, sizes
, sizes
+ aklass
->rank
);
601 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType
*type
, MonoArray
*lengths
, MonoArray
*bounds
)
605 mono_array_size_t
*sizes
, i
;
606 gboolean bounded
= FALSE
;
610 MONO_CHECK_ARG_NULL (type
);
611 MONO_CHECK_ARG_NULL (lengths
);
613 MONO_CHECK_ARG (lengths
, mono_array_length (lengths
) > 0);
615 MONO_CHECK_ARG (bounds
, mono_array_length (lengths
) == mono_array_length (bounds
));
617 for (i
= 0; i
< mono_array_length (lengths
); i
++)
618 if ((mono_array_get (lengths
, gint64
, i
) < 0) ||
619 (mono_array_get (lengths
, gint64
, i
) > MONO_ARRAY_MAX_INDEX
))
620 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL
));
622 if (bounds
&& (mono_array_length (bounds
) == 1) && (mono_array_get (bounds
, gint64
, 0) != 0))
623 /* vectors are not the same as one dimensional arrays with no-zero bounds */
628 aklass
= mono_bounded_array_class_get (mono_class_from_mono_type (type
->type
), mono_array_length (lengths
), bounded
);
630 sizes
= alloca (aklass
->rank
* sizeof(mono_array_size_t
) * 2);
631 for (i
= 0; i
< aklass
->rank
; ++i
) {
632 sizes
[i
] = mono_array_get (lengths
, guint64
, i
);
634 sizes
[i
+ aklass
->rank
] = (mono_array_size_t
) mono_array_get (bounds
, guint64
, i
);
636 sizes
[i
+ aklass
->rank
] = 0;
639 array
= mono_array_new_full (mono_object_domain (type
), aklass
, sizes
, sizes
+ aklass
->rank
);
645 ves_icall_System_Array_GetRank (MonoObject
*this)
649 return this->vtable
->klass
->rank
;
653 ves_icall_System_Array_GetLength (MonoArray
*this, gint32 dimension
)
655 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
656 mono_array_size_t length
;
660 if ((dimension
< 0) || (dimension
>= rank
))
661 mono_raise_exception (mono_get_exception_index_out_of_range ());
663 if (this->bounds
== NULL
)
664 length
= this->max_length
;
666 length
= this->bounds
[dimension
].length
;
668 #ifdef MONO_BIG_ARRAYS
669 if (length
> G_MAXINT32
)
670 mono_raise_exception (mono_get_exception_overflow ());
676 ves_icall_System_Array_GetLongLength (MonoArray
*this, gint32 dimension
)
678 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
682 if ((dimension
< 0) || (dimension
>= rank
))
683 mono_raise_exception (mono_get_exception_index_out_of_range ());
685 if (this->bounds
== NULL
)
686 return this->max_length
;
688 return this->bounds
[dimension
].length
;
692 ves_icall_System_Array_GetLowerBound (MonoArray
*this, gint32 dimension
)
694 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
698 if ((dimension
< 0) || (dimension
>= rank
))
699 mono_raise_exception (mono_get_exception_index_out_of_range ());
701 if (this->bounds
== NULL
)
704 return this->bounds
[dimension
].lower_bound
;
708 ves_icall_System_Array_ClearInternal (MonoArray
*arr
, int idx
, int length
)
710 int sz
= mono_array_element_size (mono_object_class (arr
));
711 memset (mono_array_addr_with_size (arr
, sz
, idx
), 0, length
* sz
);
715 ves_icall_System_Array_FastCopy (MonoArray
*source
, int source_idx
, MonoArray
* dest
, int dest_idx
, int length
)
720 MonoClass
*src_class
;
721 MonoClass
*dest_class
;
726 if (source
->obj
.vtable
->klass
->rank
!= dest
->obj
.vtable
->klass
->rank
)
729 if (source
->bounds
|| dest
->bounds
)
732 /* there's no integer overflow since mono_array_length returns an unsigned integer */
733 if ((dest_idx
+ length
> mono_array_length (dest
)) ||
734 (source_idx
+ length
> mono_array_length (source
)))
737 src_class
= source
->obj
.vtable
->klass
->element_class
;
738 dest_class
= dest
->obj
.vtable
->klass
->element_class
;
741 * Handle common cases.
744 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
745 if (src_class
== mono_defaults
.object_class
&& dest_class
->valuetype
) {
746 int has_refs
= dest_class
->has_references
;
747 for (i
= source_idx
; i
< source_idx
+ length
; ++i
) {
748 MonoObject
*elem
= mono_array_get (source
, MonoObject
*, i
);
749 if (elem
&& !mono_object_isinst (elem
, dest_class
))
753 element_size
= mono_array_element_size (dest
->obj
.vtable
->klass
);
754 memset (mono_array_addr_with_size (dest
, element_size
, dest_idx
), 0, element_size
* length
);
755 for (i
= 0; i
< length
; ++i
) {
756 MonoObject
*elem
= mono_array_get (source
, MonoObject
*, source_idx
+ i
);
757 void *addr
= mono_array_addr_with_size (dest
, element_size
, dest_idx
+ i
);
761 mono_value_copy (addr
, (char *)elem
+ sizeof (MonoObject
), dest_class
);
763 memcpy (addr
, (char *)elem
+ sizeof (MonoObject
), element_size
);
768 /* Check if we're copying a char[] <==> (u)short[] */
769 if (src_class
!= dest_class
) {
770 if (dest_class
->valuetype
|| dest_class
->enumtype
|| src_class
->valuetype
|| src_class
->enumtype
)
773 if (mono_class_is_subclass_of (src_class
, dest_class
, FALSE
))
775 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
776 else if (mono_class_is_subclass_of (dest_class
, src_class
, FALSE
))
777 for (i
= source_idx
; i
< source_idx
+ length
; ++i
) {
778 MonoObject
*elem
= mono_array_get (source
, MonoObject
*, i
);
779 if (elem
&& !mono_object_isinst (elem
, dest_class
))
786 if (dest_class
->valuetype
) {
787 element_size
= mono_array_element_size (source
->obj
.vtable
->klass
);
788 source_addr
= mono_array_addr_with_size (source
, element_size
, source_idx
);
789 if (dest_class
->has_references
) {
790 mono_value_copy_array (dest
, dest_idx
, source_addr
, length
);
792 dest_addr
= mono_array_addr_with_size (dest
, element_size
, dest_idx
);
793 memmove (dest_addr
, source_addr
, element_size
* length
);
796 mono_array_memcpy_refs (dest
, dest_idx
, source
, source_idx
, length
);
803 ves_icall_System_Array_GetGenericValueImpl (MonoObject
*this, guint32 pos
, gpointer value
)
812 ao
= (MonoArray
*)this;
813 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
815 esize
= mono_array_element_size (ac
);
816 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
818 memcpy (value
, ea
, esize
);
822 ves_icall_System_Array_SetGenericValueImpl (MonoObject
*this, guint32 pos
, gpointer value
)
831 ao
= (MonoArray
*)this;
832 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
833 ec
= ac
->element_class
;
835 esize
= mono_array_element_size (ac
);
836 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
838 if (MONO_TYPE_IS_REFERENCE (&ec
->byval_arg
)) {
839 g_assert (esize
== sizeof (gpointer
));
840 mono_gc_wbarrier_generic_store (ea
, *(gpointer
*)value
);
842 g_assert (ec
->inited
);
843 g_assert (esize
== mono_class_value_size (ec
, NULL
));
844 if (ec
->has_references
)
845 mono_gc_wbarrier_value_copy (ea
, value
, 1, ec
);
847 memcpy (ea
, value
, esize
);
852 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray
*array
, MonoClassField
*field_handle
)
854 MonoClass
*klass
= array
->obj
.vtable
->klass
;
855 guint32 size
= mono_array_element_size (klass
);
856 MonoType
*type
= mono_type_get_underlying_type (&klass
->element_class
->byval_arg
);
858 const char *field_data
;
860 if (MONO_TYPE_IS_REFERENCE (type
) ||
861 (type
->type
== MONO_TYPE_VALUETYPE
&&
862 (!mono_type_get_class (type
) ||
863 mono_type_get_class (type
)->has_references
))) {
864 MonoException
*exc
= mono_get_exception_argument("array",
865 "Cannot initialize array containing references");
866 mono_raise_exception (exc
);
869 if (!(field_handle
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
)) {
870 MonoException
*exc
= mono_get_exception_argument("field_handle",
871 "Field doesn't have an RVA");
872 mono_raise_exception (exc
);
875 size
*= array
->max_length
;
876 field_data
= mono_field_get_data (field_handle
);
878 if (size
> mono_type_size (field_handle
->type
, &align
)) {
879 MonoException
*exc
= mono_get_exception_argument("field_handle",
880 "Field not large enough to fill array");
881 mono_raise_exception (exc
);
884 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
886 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
887 guint ## n *src = (guint ## n *) field_data; \
888 guint ## n *end = (guint ## n *)((char*)src + size); \
890 for (; src < end; data++, src++) { \
891 *data = read ## n (src); \
895 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
897 switch (type
->type
) {
914 memcpy (mono_array_addr (array
, char, 0), field_data
, size
);
918 memcpy (mono_array_addr (array
, char, 0), field_data
, size
);
920 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_R8
) {
923 double *data
= (double*)mono_array_addr (array
, double, 0);
925 for (i
= 0; i
< size
; i
++, data
++) {
935 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
939 return offsetof (MonoString
, chars
);
943 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject
*obj
)
947 if ((obj
== NULL
) || (! (obj
->vtable
->klass
->valuetype
)))
950 return mono_object_clone (obj
);
954 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType
*handle
)
959 MONO_CHECK_ARG_NULL (handle
);
961 klass
= mono_class_from_mono_type (handle
);
962 MONO_CHECK_ARG (handle
, klass
);
964 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, TRUE
);
966 /* This will call the type constructor */
967 mono_runtime_class_init (vtable
);
971 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage
*image
)
975 mono_image_check_for_module_cctor (image
);
976 if (image
->has_module_cctor
) {
977 MonoClass
*module_klass
= mono_class_get (image
, MONO_TOKEN_TYPE_DEF
| 1);
978 /*It's fine to raise the exception here*/
979 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass
, TRUE
));
984 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
989 /* later make this configurable and per-arch */
990 int min_size
= 4096 * 4 * sizeof (void*);
991 mono_thread_get_stack_bounds (&stack_addr
, &stack_size
);
992 /* if we have no info we are optimistic and assume there is enough room */
995 current
= (guint8
*)&stack_addr
;
996 if (current
> stack_addr
) {
997 if ((current
- stack_addr
) < min_size
)
1000 if (current
- (stack_addr
- stack_size
) < min_size
)
1007 ves_icall_System_Object_MemberwiseClone (MonoObject
*this)
1009 MONO_ARCH_SAVE_REGS
;
1011 return mono_object_clone (this);
1015 ves_icall_System_ValueType_InternalGetHashCode (MonoObject
*this, MonoArray
**fields
)
1018 MonoObject
**values
= NULL
;
1022 MonoClassField
* field
;
1025 MONO_ARCH_SAVE_REGS
;
1027 klass
= mono_object_class (this);
1029 if (mono_class_num_fields (klass
) == 0)
1030 return mono_object_hash (this);
1033 * Compute the starting value of the hashcode for fields of primitive
1034 * types, and return the remaining fields in an array to the managed side.
1035 * This way, we can avoid costly reflection operations in managed code.
1038 while ((field
= mono_class_get_fields (klass
, &iter
))) {
1039 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1041 if (mono_field_is_deleted (field
))
1043 /* FIXME: Add more types */
1044 switch (field
->type
->type
) {
1046 result
^= *(gint32
*)((guint8
*)this + field
->offset
);
1048 case MONO_TYPE_STRING
: {
1050 s
= *(MonoString
**)((guint8
*)this + field
->offset
);
1052 result
^= mono_string_hash (s
);
1057 values
= g_newa (MonoObject
*, mono_class_num_fields (klass
));
1058 o
= mono_field_get_value_object (mono_object_domain (this), field
, this);
1059 values
[count
++] = o
;
1065 mono_gc_wbarrier_generic_store (fields
, (MonoObject
*) mono_array_new (mono_domain_get (), mono_defaults
.object_class
, count
));
1066 for (i
= 0; i
< count
; ++i
)
1067 mono_array_setref (*fields
, i
, values
[i
]);
1075 ves_icall_System_ValueType_Equals (MonoObject
*this, MonoObject
*that
, MonoArray
**fields
)
1078 MonoObject
**values
= NULL
;
1080 MonoClassField
* field
;
1084 MONO_ARCH_SAVE_REGS
;
1086 MONO_CHECK_ARG_NULL (that
);
1088 if (this->vtable
!= that
->vtable
)
1091 klass
= mono_object_class (this);
1093 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) && mono_class_enum_basetype (klass
)->type
== MONO_TYPE_I4
)
1094 return (*(gint32
*)((guint8
*)this + 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 + field
->offset
) != *((guint8
*)that
+ field
->offset
))
1119 case MONO_TYPE_CHAR
:
1120 if (*(gint16
*)((guint8
*)this + field
->offset
) != *(gint16
*)((guint8
*)that
+ field
->offset
))
1125 if (*(gint32
*)((guint8
*)this + field
->offset
) != *(gint32
*)((guint8
*)that
+ field
->offset
))
1130 if (*(gint64
*)((guint8
*)this + field
->offset
) != *(gint64
*)((guint8
*)that
+ field
->offset
))
1134 if (*(float*)((guint8
*)this + field
->offset
) != *(float*)((guint8
*)that
+ field
->offset
))
1138 if (*(double*)((guint8
*)this + 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 + 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 (mono_object_domain (this), field
, this);
1165 values
[count
++] = o
;
1166 o
= mono_field_get_value_object (mono_object_domain (this), field
, that
);
1167 values
[count
++] = o
;
1170 if (klass
->enumtype
)
1171 /* enums only have one non-static field */
1177 mono_gc_wbarrier_generic_store (fields
, (MonoObject
*) mono_array_new (mono_domain_get (), mono_defaults
.object_class
, count
));
1178 for (i
= 0; i
< count
; ++i
)
1179 mono_array_setref (*fields
, i
, values
[i
]);
1186 static MonoReflectionType
*
1187 ves_icall_System_Object_GetType (MonoObject
*obj
)
1189 MONO_ARCH_SAVE_REGS
;
1191 if (obj
->vtable
->klass
!= mono_defaults
.transparent_proxy_class
)
1192 return mono_type_get_object (mono_object_domain (obj
), &obj
->vtable
->klass
->byval_arg
);
1194 return mono_type_get_object (mono_object_domain (obj
), &((MonoTransparentProxy
*)obj
)->remote_class
->proxy_class
->byval_arg
);
1198 mono_type_type_from_obj (MonoReflectionType
*mtype
, MonoObject
*obj
)
1200 MONO_ARCH_SAVE_REGS
;
1202 mtype
->type
= &obj
->vtable
->klass
->byval_arg
;
1203 g_assert (mtype
->type
->type
);
1207 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder
*mb
, MonoObject
*obj
)
1209 MONO_ARCH_SAVE_REGS
;
1211 MONO_CHECK_ARG_NULL (obj
);
1213 return mono_image_create_token (mb
->dynamic_image
, obj
, TRUE
, TRUE
);
1217 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder
*mb
,
1218 MonoReflectionMethod
*method
,
1219 MonoArray
*opt_param_types
)
1221 MONO_ARCH_SAVE_REGS
;
1223 MONO_CHECK_ARG_NULL (method
);
1225 return mono_image_create_method_token (
1226 mb
->dynamic_image
, (MonoObject
*) method
, opt_param_types
);
1230 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
1232 MONO_ARCH_SAVE_REGS
;
1234 mono_image_create_pefile (mb
, file
);
1238 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder
*mb
)
1240 MONO_ARCH_SAVE_REGS
;
1242 mono_image_build_metadata (mb
);
1246 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder
*mb
, MonoObject
*obj
, guint32 token
)
1248 MONO_ARCH_SAVE_REGS
;
1250 mono_image_register_token (mb
->dynamic_image
, token
, obj
);
1254 get_caller (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1256 MonoMethod
**dest
= data
;
1258 /* skip unmanaged frames */
1274 get_executing (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1276 MonoMethod
**dest
= data
;
1278 /* skip unmanaged frames */
1283 if (!strcmp (m
->klass
->name_space
, "System.Reflection"))
1292 get_caller_no_reflection (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1294 MonoMethod
**dest
= data
;
1296 /* skip unmanaged frames */
1300 if (m
->wrapper_type
!= MONO_WRAPPER_NONE
)
1303 if (m
->klass
->image
== mono_defaults
.corlib
&& !strcmp (m
->klass
->name_space
, "System.Reflection"))
1317 static MonoReflectionType
*
1318 type_from_name (const char *str
, MonoBoolean ignoreCase
)
1320 MonoType
*type
= NULL
;
1321 MonoAssembly
*assembly
= NULL
;
1322 MonoTypeNameParse info
;
1323 char *temp_str
= g_strdup (str
);
1324 gboolean type_resolve
= FALSE
;
1326 MONO_ARCH_SAVE_REGS
;
1328 /* mono_reflection_parse_type() mangles the string */
1329 if (!mono_reflection_parse_type (temp_str
, &info
)) {
1330 mono_reflection_free_type_info (&info
);
1335 if (info
.assembly
.name
) {
1336 assembly
= mono_assembly_load (&info
.assembly
, NULL
, NULL
);
1338 MonoMethod
*m
= mono_method_get_last_managed ();
1339 MonoMethod
*dest
= m
;
1341 mono_stack_walk_no_il (get_caller_no_reflection
, &dest
);
1346 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1347 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1348 * to crash. This only seems to happen in some strange remoting
1349 * scenarios and I was unable to figure out what's happening there.
1350 * Dec 10, 2005 - Martin.
1354 assembly
= dest
->klass
->image
->assembly
;
1355 type_resolve
= TRUE
;
1357 g_warning (G_STRLOC
);
1362 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1363 type
= mono_reflection_get_type (assembly
->image
, &info
, ignoreCase
, &type_resolve
);
1366 if (!info
.assembly
.name
&& !type
) /* try mscorlib */
1367 type
= mono_reflection_get_type (NULL
, &info
, ignoreCase
, &type_resolve
);
1369 if (assembly
&& !type
&& type_resolve
) {
1370 type_resolve
= FALSE
; /* This will invoke TypeResolve if not done in the first 'if' */
1371 type
= mono_reflection_get_type (assembly
->image
, &info
, ignoreCase
, &type_resolve
);
1374 mono_reflection_free_type_info (&info
);
1380 return mono_type_get_object (mono_domain_get (), type
);
1384 MonoReflectionType
*
1385 mono_type_get (const char *str
)
1387 char *copy
= g_strdup (str
);
1388 MonoReflectionType
*type
= type_from_name (copy
, FALSE
);
1395 static MonoReflectionType
*
1396 ves_icall_type_from_name (MonoString
*name
,
1397 MonoBoolean throwOnError
,
1398 MonoBoolean ignoreCase
)
1400 char *str
= mono_string_to_utf8 (name
);
1401 MonoReflectionType
*type
;
1403 type
= type_from_name (str
, ignoreCase
);
1406 MonoException
*e
= NULL
;
1409 e
= mono_get_exception_type_load (name
, NULL
);
1411 mono_loader_clear_error ();
1413 mono_raise_exception (e
);
1420 static MonoReflectionType
*
1421 ves_icall_type_from_handle (MonoType
*handle
)
1423 MonoDomain
*domain
= mono_domain_get ();
1424 MonoClass
*klass
= mono_class_from_mono_type (handle
);
1426 MONO_ARCH_SAVE_REGS
;
1428 mono_class_init (klass
);
1429 return mono_type_get_object (domain
, handle
);
1433 ves_icall_System_Type_EqualsInternal (MonoReflectionType
*type
, MonoReflectionType
*c
)
1435 MONO_ARCH_SAVE_REGS
;
1437 if (c
&& type
->type
&& c
->type
)
1438 return mono_metadata_type_equal (type
->type
, c
->type
);
1440 return (type
== c
) ? TRUE
: FALSE
;
1443 /* System.TypeCode */
1462 TYPECODE_STRING
= 18
1466 ves_icall_type_GetTypeCodeInternal (MonoReflectionType
*type
)
1468 int t
= type
->type
->type
;
1470 MONO_ARCH_SAVE_REGS
;
1472 if (type
->type
->byref
)
1473 return TYPECODE_OBJECT
;
1477 case MONO_TYPE_VOID
:
1478 return TYPECODE_OBJECT
;
1479 case MONO_TYPE_BOOLEAN
:
1480 return TYPECODE_BOOLEAN
;
1482 return TYPECODE_BYTE
;
1484 return TYPECODE_SBYTE
;
1486 return TYPECODE_UINT16
;
1488 return TYPECODE_INT16
;
1489 case MONO_TYPE_CHAR
:
1490 return TYPECODE_CHAR
;
1494 return TYPECODE_OBJECT
;
1496 return TYPECODE_UINT32
;
1498 return TYPECODE_INT32
;
1500 return TYPECODE_UINT64
;
1502 return TYPECODE_INT64
;
1504 return TYPECODE_SINGLE
;
1506 return TYPECODE_DOUBLE
;
1507 case MONO_TYPE_VALUETYPE
:
1508 if (type
->type
->data
.klass
->enumtype
) {
1509 t
= mono_class_enum_basetype (type
->type
->data
.klass
)->type
;
1512 MonoClass
*k
= type
->type
->data
.klass
;
1513 if (strcmp (k
->name_space
, "System") == 0) {
1514 if (strcmp (k
->name
, "Decimal") == 0)
1515 return TYPECODE_DECIMAL
;
1516 else if (strcmp (k
->name
, "DateTime") == 0)
1517 return TYPECODE_DATETIME
;
1520 return TYPECODE_OBJECT
;
1521 case MONO_TYPE_STRING
:
1522 return TYPECODE_STRING
;
1523 case MONO_TYPE_SZARRAY
:
1524 case MONO_TYPE_ARRAY
:
1525 case MONO_TYPE_OBJECT
:
1527 case MONO_TYPE_MVAR
:
1528 case MONO_TYPE_TYPEDBYREF
:
1529 return TYPECODE_OBJECT
;
1530 case MONO_TYPE_CLASS
:
1532 MonoClass
*k
= type
->type
->data
.klass
;
1533 if (strcmp (k
->name_space
, "System") == 0) {
1534 if (strcmp (k
->name
, "DBNull") == 0)
1535 return TYPECODE_DBNULL
;
1538 return TYPECODE_OBJECT
;
1539 case MONO_TYPE_GENERICINST
:
1540 return TYPECODE_OBJECT
;
1542 g_error ("type 0x%02x not handled in GetTypeCode()", t
);
1548 ves_icall_type_is_subtype_of (MonoReflectionType
*type
, MonoReflectionType
*c
, MonoBoolean check_interfaces
)
1554 MONO_ARCH_SAVE_REGS
;
1556 g_assert (type
!= NULL
);
1558 domain
= ((MonoObject
*)type
)->vtable
->domain
;
1560 if (!c
) /* FIXME: dont know what do do here */
1563 klass
= mono_class_from_mono_type (type
->type
);
1564 klassc
= mono_class_from_mono_type (c
->type
);
1566 if (type
->type
->byref
)
1567 return klassc
== mono_defaults
.object_class
;
1569 return mono_class_is_subclass_of (klass
, klassc
, check_interfaces
);
1573 ves_icall_type_is_assignable_from (MonoReflectionType
*type
, MonoReflectionType
*c
)
1579 MONO_ARCH_SAVE_REGS
;
1581 g_assert (type
!= NULL
);
1583 domain
= ((MonoObject
*)type
)->vtable
->domain
;
1585 klass
= mono_class_from_mono_type (type
->type
);
1586 klassc
= mono_class_from_mono_type (c
->type
);
1588 if (type
->type
->byref
&& !c
->type
->byref
)
1591 return mono_class_is_assignable_from (klass
, klassc
);
1595 ves_icall_type_IsInstanceOfType (MonoReflectionType
*type
, MonoObject
*obj
)
1597 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1598 return mono_object_isinst (obj
, klass
) != NULL
;
1602 ves_icall_get_attributes (MonoReflectionType
*type
)
1604 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1606 MONO_ARCH_SAVE_REGS
;
1608 return klass
->flags
;
1611 static MonoReflectionMarshal
*
1612 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField
*field
)
1614 MonoClass
*klass
= field
->field
->parent
;
1615 MonoMarshalType
*info
;
1618 if (klass
->generic_container
||
1619 (klass
->generic_class
&& klass
->generic_class
->context
.class_inst
->is_open
))
1622 info
= mono_marshal_load_type_info (klass
);
1624 for (i
= 0; i
< info
->num_fields
; ++i
) {
1625 if (info
->fields
[i
].field
== field
->field
) {
1626 if (!info
->fields
[i
].mspec
)
1629 return mono_reflection_marshal_from_marshal_spec (field
->object
.vtable
->domain
, klass
, info
->fields
[i
].mspec
);
1636 static MonoReflectionField
*
1637 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField
*handle
, MonoType
*type
)
1639 gboolean found
= FALSE
;
1646 klass
= handle
->parent
;
1648 klass
= mono_class_from_mono_type (type
);
1650 /* Check that the field belongs to the class */
1651 for (k
= klass
; k
; k
= k
->parent
) {
1652 if (k
== handle
->parent
) {
1659 /* The managed code will throw the exception */
1663 return mono_field_get_object (mono_domain_get (), klass
, handle
);
1667 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField
*field
, MonoBoolean optional
)
1669 MonoType
*type
= field
->field
->type
;
1671 return type_array_from_modifiers (field
->field
->parent
->image
, type
, optional
);
1675 ves_icall_get_method_info (MonoMethod
*method
, MonoMethodInfo
*info
)
1677 MonoDomain
*domain
= mono_domain_get ();
1678 MonoMethodSignature
* sig
;
1679 MONO_ARCH_SAVE_REGS
;
1681 sig
= mono_method_signature (method
);
1683 g_assert (mono_loader_get_last_error ());
1684 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1687 MONO_STRUCT_SETREF (info
, parent
, mono_type_get_object (domain
, &method
->klass
->byval_arg
));
1688 MONO_STRUCT_SETREF (info
, ret
, mono_type_get_object (domain
, sig
->ret
));
1689 info
->attrs
= method
->flags
;
1690 info
->implattrs
= method
->iflags
;
1691 if (sig
->call_convention
== MONO_CALL_DEFAULT
)
1692 info
->callconv
= sig
->sentinelpos
>= 0 ? 2 : 1;
1694 if (sig
->call_convention
== MONO_CALL_VARARG
|| sig
->sentinelpos
>= 0)
1699 info
->callconv
|= (sig
->hasthis
<< 5) | (sig
->explicit_this
<< 6);
1703 ves_icall_get_parameter_info (MonoMethod
*method
, MonoReflectionMethod
*member
)
1705 MonoDomain
*domain
= mono_domain_get ();
1707 return mono_param_get_objects_internal (domain
, method
, member
->reftype
? mono_class_from_mono_type (member
->reftype
->type
) : NULL
);
1710 static MonoReflectionMarshal
*
1711 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod
*method
)
1713 MonoDomain
*domain
= mono_domain_get ();
1714 MonoReflectionMarshal
* res
= NULL
;
1715 MonoMarshalSpec
**mspecs
;
1718 mspecs
= g_new (MonoMarshalSpec
*, mono_method_signature (method
)->param_count
+ 1);
1719 mono_method_get_marshal_info (method
, mspecs
);
1722 res
= mono_reflection_marshal_from_marshal_spec (domain
, method
->klass
, mspecs
[0]);
1724 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
1726 mono_metadata_free_marshal_spec (mspecs
[i
]);
1733 ves_icall_MonoField_GetFieldOffset (MonoReflectionField
*field
)
1735 return field
->field
->offset
- sizeof (MonoObject
);
1738 static MonoReflectionType
*
1739 ves_icall_MonoField_GetParentType (MonoReflectionField
*field
, MonoBoolean declaring
)
1742 MONO_ARCH_SAVE_REGS
;
1744 parent
= declaring
? field
->field
->parent
: field
->klass
;
1746 return mono_type_get_object (mono_object_domain (field
), &parent
->byval_arg
);
1750 ves_icall_MonoField_GetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
)
1753 MonoClassField
*cf
= field
->field
;
1757 MonoDomain
*domain
= mono_object_domain (field
);
1759 gboolean is_static
= FALSE
;
1760 gboolean is_ref
= FALSE
;
1762 MONO_ARCH_SAVE_REGS
;
1764 if (field
->klass
->image
->assembly
->ref_only
)
1765 mono_raise_exception (mono_get_exception_invalid_operation (
1766 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1768 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
1769 mono_security_core_clr_ensure_reflection_access_field (cf
);
1771 mono_class_init (field
->klass
);
1773 if (cf
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1776 if (obj
&& !is_static
) {
1777 /* Check that the field belongs to the object */
1778 gboolean found
= FALSE
;
1781 for (k
= obj
->vtable
->klass
; k
; k
= k
->parent
) {
1782 if (k
== cf
->parent
) {
1789 char *msg
= g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", mono_field_get_name (cf
), cf
->parent
->name
, obj
->vtable
->klass
->name
);
1790 MonoException
*ex
= mono_get_exception_argument (NULL
, msg
);
1792 mono_raise_exception (ex
);
1796 t
= mono_type_get_underlying_type (cf
->type
);
1798 case MONO_TYPE_STRING
:
1799 case MONO_TYPE_OBJECT
:
1800 case MONO_TYPE_CLASS
:
1801 case MONO_TYPE_ARRAY
:
1802 case MONO_TYPE_SZARRAY
:
1807 case MONO_TYPE_BOOLEAN
:
1810 case MONO_TYPE_CHAR
:
1819 case MONO_TYPE_VALUETYPE
:
1822 case MONO_TYPE_GENERICINST
:
1823 if (mono_type_generic_inst_is_valuetype (t
)) {
1830 g_error ("type 0x%x not handled in "
1831 "ves_icall_Monofield_GetValue", t
->type
);
1837 vtable
= mono_class_vtable_full (domain
, cf
->parent
, TRUE
);
1838 if (!vtable
->initialized
&& !(cf
->type
->attrs
& FIELD_ATTRIBUTE_LITERAL
))
1839 mono_runtime_class_init (vtable
);
1844 mono_field_static_get_value (vtable
, cf
, &o
);
1846 mono_field_get_value (obj
, cf
, &o
);
1851 if (mono_class_is_nullable (mono_class_from_mono_type (cf
->type
))) {
1852 MonoClass
*nklass
= mono_class_from_mono_type (cf
->type
);
1855 /* Convert the Nullable structure into a boxed vtype */
1857 buf
= (guint8
*)vtable
->data
+ cf
->offset
;
1859 buf
= (guint8
*)obj
+ cf
->offset
;
1861 return mono_nullable_box (buf
, nklass
);
1864 /* boxed value type */
1865 klass
= mono_class_from_mono_type (cf
->type
);
1866 o
= mono_object_new (domain
, klass
);
1867 v
= ((gchar
*) o
) + sizeof (MonoObject
);
1869 mono_field_static_get_value (vtable
, cf
, v
);
1871 mono_field_get_value (obj
, cf
, v
);
1878 ves_icall_MonoField_SetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
, MonoObject
*value
)
1880 MonoClassField
*cf
= field
->field
;
1883 MONO_ARCH_SAVE_REGS
;
1885 if (field
->klass
->image
->assembly
->ref_only
)
1886 mono_raise_exception (mono_get_exception_invalid_operation (
1887 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1889 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
1890 mono_security_core_clr_ensure_reflection_access_field (cf
);
1892 v
= (gchar
*) value
;
1893 if (!cf
->type
->byref
) {
1894 switch (cf
->type
->type
) {
1897 case MONO_TYPE_BOOLEAN
:
1900 case MONO_TYPE_CHAR
:
1909 case MONO_TYPE_VALUETYPE
:
1911 v
+= sizeof (MonoObject
);
1913 case MONO_TYPE_STRING
:
1914 case MONO_TYPE_OBJECT
:
1915 case MONO_TYPE_CLASS
:
1916 case MONO_TYPE_ARRAY
:
1917 case MONO_TYPE_SZARRAY
:
1920 case MONO_TYPE_GENERICINST
: {
1921 MonoGenericClass
*gclass
= cf
->type
->data
.generic_class
;
1922 g_assert (!gclass
->context
.class_inst
->is_open
);
1924 if (mono_class_is_nullable (mono_class_from_mono_type (cf
->type
))) {
1925 MonoClass
*nklass
= mono_class_from_mono_type (cf
->type
);
1926 MonoObject
*nullable
;
1929 * Convert the boxed vtype into a Nullable structure.
1930 * This is complicated by the fact that Nullables have
1931 * a variable structure.
1933 nullable
= mono_object_new (mono_domain_get (), nklass
);
1935 mono_nullable_init (mono_object_unbox (nullable
), value
, nklass
);
1937 v
= mono_object_unbox (nullable
);
1940 if (gclass
->container_class
->valuetype
&& (v
!= NULL
))
1941 v
+= sizeof (MonoObject
);
1945 g_error ("type 0x%x not handled in "
1946 "ves_icall_FieldInfo_SetValueInternal", cf
->type
->type
);
1951 if (cf
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
1952 MonoVTable
*vtable
= mono_class_vtable_full (mono_object_domain (field
), cf
->parent
, TRUE
);
1953 if (!vtable
->initialized
)
1954 mono_runtime_class_init (vtable
);
1955 mono_field_static_set_value (vtable
, cf
, v
);
1957 mono_field_set_value (obj
, cf
, v
);
1962 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField
*this)
1964 MonoObject
*o
= NULL
;
1965 MonoClassField
*field
= this->field
;
1967 MonoDomain
*domain
= mono_object_domain (this);
1969 MonoTypeEnum def_type
;
1970 const char *def_value
;
1972 MONO_ARCH_SAVE_REGS
;
1974 mono_class_init (field
->parent
);
1976 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
))
1977 mono_raise_exception (mono_get_exception_invalid_operation (NULL
));
1979 if (field
->parent
->image
->dynamic
) {
1981 g_assert_not_reached ();
1984 def_value
= mono_class_get_field_default_value (field
, &def_type
);
1986 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1990 case MONO_TYPE_BOOLEAN
:
1993 case MONO_TYPE_CHAR
:
2001 case MONO_TYPE_R8
: {
2004 /* boxed value type */
2005 t
= g_new0 (MonoType
, 1);
2007 klass
= mono_class_from_mono_type (t
);
2009 o
= mono_object_new (domain
, klass
);
2010 v
= ((gchar
*) o
) + sizeof (MonoObject
);
2011 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, v
);
2014 case MONO_TYPE_STRING
:
2015 case MONO_TYPE_CLASS
:
2016 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, &o
);
2019 g_assert_not_reached ();
2025 static MonoReflectionType
*
2026 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod
*rmethod
)
2028 MonoMethod
*method
= rmethod
->method
.method
;
2030 return mono_type_get_object (mono_object_domain (rmethod
), &method
->klass
->byval_arg
);
2033 /* From MonoProperty.cs */
2035 PInfo_Attributes
= 1,
2036 PInfo_GetMethod
= 1 << 1,
2037 PInfo_SetMethod
= 1 << 2,
2038 PInfo_ReflectedType
= 1 << 3,
2039 PInfo_DeclaringType
= 1 << 4,
2044 ves_icall_get_property_info (MonoReflectionProperty
*property
, MonoPropertyInfo
*info
, PInfo req_info
)
2046 MonoDomain
*domain
= mono_object_domain (property
);
2048 MONO_ARCH_SAVE_REGS
;
2050 if ((req_info
& PInfo_ReflectedType
) != 0)
2051 MONO_STRUCT_SETREF (info
, parent
, mono_type_get_object (domain
, &property
->klass
->byval_arg
));
2052 else if ((req_info
& PInfo_DeclaringType
) != 0)
2053 MONO_STRUCT_SETREF (info
, parent
, mono_type_get_object (domain
, &property
->property
->parent
->byval_arg
));
2055 if ((req_info
& PInfo_Name
) != 0)
2056 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, property
->property
->name
));
2058 if ((req_info
& PInfo_Attributes
) != 0)
2059 info
->attrs
= property
->property
->attrs
;
2061 if ((req_info
& PInfo_GetMethod
) != 0)
2062 MONO_STRUCT_SETREF (info
, get
, property
->property
->get
?
2063 mono_method_get_object (domain
, property
->property
->get
, property
->klass
): NULL
);
2065 if ((req_info
& PInfo_SetMethod
) != 0)
2066 MONO_STRUCT_SETREF (info
, set
, property
->property
->set
?
2067 mono_method_get_object (domain
, property
->property
->set
, property
->klass
): NULL
);
2069 * There may be other methods defined for properties, though, it seems they are not exposed
2070 * in the reflection API
2075 ves_icall_get_event_info (MonoReflectionMonoEvent
*event
, MonoEventInfo
*info
)
2077 MonoDomain
*domain
= mono_object_domain (event
);
2079 MONO_ARCH_SAVE_REGS
;
2081 MONO_STRUCT_SETREF (info
, reflected_type
, mono_type_get_object (domain
, &event
->klass
->byval_arg
));
2082 MONO_STRUCT_SETREF (info
, declaring_type
, mono_type_get_object (domain
, &event
->event
->parent
->byval_arg
));
2084 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, event
->event
->name
));
2085 info
->attrs
= event
->event
->attrs
;
2086 MONO_STRUCT_SETREF (info
, add_method
, event
->event
->add
? mono_method_get_object (domain
, event
->event
->add
, NULL
): NULL
);
2087 MONO_STRUCT_SETREF (info
, remove_method
, event
->event
->remove
? mono_method_get_object (domain
, event
->event
->remove
, NULL
): NULL
);
2088 MONO_STRUCT_SETREF (info
, raise_method
, event
->event
->raise
? mono_method_get_object (domain
, event
->event
->raise
, NULL
): NULL
);
2090 if (event
->event
->other
) {
2092 while (event
->event
->other
[n
])
2094 MONO_STRUCT_SETREF (info
, other_methods
, mono_array_new (domain
, mono_defaults
.method_info_class
, n
));
2096 for (i
= 0; i
< n
; i
++)
2097 mono_array_setref (info
->other_methods
, i
, mono_method_get_object (domain
, event
->event
->other
[i
], NULL
));
2102 ves_icall_Type_GetInterfaces (MonoReflectionType
* type
)
2105 MonoDomain
*domain
= mono_object_domain (type
);
2107 GPtrArray
*ifaces
= NULL
;
2109 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2112 MonoGenericContext
*context
= NULL
;
2114 MONO_ARCH_SAVE_REGS
;
2116 if (class->generic_class
&& class->generic_class
->context
.class_inst
->is_open
) {
2117 context
= mono_class_get_context (class);
2118 class = class->generic_class
->container_class
;
2121 mono_class_setup_vtable (class);
2123 slots
= mono_bitset_new (class->max_interface_id
+ 1, 0);
2125 for (parent
= class; parent
; parent
= parent
->parent
) {
2126 GPtrArray
*tmp_ifaces
= mono_class_get_implemented_interfaces (parent
, &error
);
2127 if (!mono_error_ok (&error
)) {
2128 mono_bitset_free (slots
);
2129 mono_error_raise_exception (&error
);
2131 } else if (tmp_ifaces
) {
2132 for (i
= 0; i
< tmp_ifaces
->len
; ++i
) {
2133 MonoClass
*ic
= g_ptr_array_index (tmp_ifaces
, i
);
2135 if (mono_bitset_test (slots
, ic
->interface_id
))
2138 mono_bitset_set (slots
, ic
->interface_id
);
2140 ifaces
= g_ptr_array_new ();
2141 g_ptr_array_add (ifaces
, ic
);
2143 g_ptr_array_free (tmp_ifaces
, TRUE
);
2146 mono_bitset_free (slots
);
2149 return mono_array_new_cached (domain
, mono_defaults
.monotype_class
, 0);
2151 intf
= mono_array_new_cached (domain
, mono_defaults
.monotype_class
, ifaces
->len
);
2152 for (i
= 0; i
< ifaces
->len
; ++i
) {
2153 MonoClass
*ic
= g_ptr_array_index (ifaces
, i
);
2154 MonoType
*ret
= &ic
->byval_arg
, *inflated
= NULL
;
2155 if (context
&& ic
->generic_class
&& ic
->generic_class
->context
.class_inst
->is_open
)
2156 inflated
= ret
= mono_class_inflate_generic_type (ret
, context
);
2158 mono_array_setref (intf
, i
, mono_type_get_object (domain
, ret
));
2160 mono_metadata_free_type (inflated
);
2162 g_ptr_array_free (ifaces
, TRUE
);
2168 ves_icall_Type_GetInterfaceMapData (MonoReflectionType
*type
, MonoReflectionType
*iface
, MonoArray
**targets
, MonoArray
**methods
)
2170 gboolean variance_used
;
2171 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2172 MonoClass
*iclass
= mono_class_from_mono_type (iface
->type
);
2173 MonoReflectionMethod
*member
;
2176 int i
= 0, len
, ioffset
;
2179 MONO_ARCH_SAVE_REGS
;
2181 mono_class_setup_vtable (class);
2183 ioffset
= mono_class_interface_offset_with_variance (class, iclass
, &variance_used
);
2187 len
= mono_class_num_methods (iclass
);
2188 domain
= mono_object_domain (type
);
2189 mono_gc_wbarrier_generic_store (targets
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.method_info_class
, len
));
2190 mono_gc_wbarrier_generic_store (methods
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.method_info_class
, len
));
2192 while ((method
= mono_class_get_methods (iclass
, &iter
))) {
2193 member
= mono_method_get_object (domain
, method
, iclass
);
2194 mono_array_setref (*methods
, i
, member
);
2195 member
= mono_method_get_object (domain
, class->vtable
[i
+ ioffset
], class);
2196 mono_array_setref (*targets
, i
, member
);
2203 ves_icall_Type_GetPacking (MonoReflectionType
*type
, guint32
*packing
, guint32
*size
)
2205 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2207 if (klass
->image
->dynamic
) {
2208 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)type
;
2209 *packing
= tb
->packing_size
;
2210 *size
= tb
->class_size
;
2212 mono_metadata_packing_from_typedef (klass
->image
, klass
->type_token
, packing
, size
);
2216 static MonoReflectionType
*
2217 ves_icall_MonoType_GetElementType (MonoReflectionType
*type
)
2221 MONO_ARCH_SAVE_REGS
;
2223 if (!type
->type
->byref
&& type
->type
->type
== MONO_TYPE_SZARRAY
)
2224 return mono_type_get_object (mono_object_domain (type
), &type
->type
->data
.klass
->byval_arg
);
2226 class = mono_class_from_mono_type (type
->type
);
2228 // GetElementType should only return a type for:
2229 // Array Pointer PassedByRef
2230 if (type
->type
->byref
)
2231 return mono_type_get_object (mono_object_domain (type
), &class->byval_arg
);
2232 else if (class->element_class
&& MONO_CLASS_IS_ARRAY (class))
2233 return mono_type_get_object (mono_object_domain (type
), &class->element_class
->byval_arg
);
2234 else if (class->element_class
&& type
->type
->type
== MONO_TYPE_PTR
)
2235 return mono_type_get_object (mono_object_domain (type
), &class->element_class
->byval_arg
);
2240 static MonoReflectionType
*
2241 ves_icall_get_type_parent (MonoReflectionType
*type
)
2243 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2245 MONO_ARCH_SAVE_REGS
;
2247 return class->parent
? mono_type_get_object (mono_object_domain (type
), &class->parent
->byval_arg
): NULL
;
2251 ves_icall_type_ispointer (MonoReflectionType
*type
)
2253 MONO_ARCH_SAVE_REGS
;
2255 return type
->type
->type
== MONO_TYPE_PTR
;
2259 ves_icall_type_isprimitive (MonoReflectionType
*type
)
2261 MONO_ARCH_SAVE_REGS
;
2263 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
)));
2267 ves_icall_type_isbyref (MonoReflectionType
*type
)
2269 MONO_ARCH_SAVE_REGS
;
2271 return type
->type
->byref
;
2275 ves_icall_type_iscomobject (MonoReflectionType
*type
)
2277 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2278 MONO_ARCH_SAVE_REGS
;
2280 return (klass
&& klass
->is_com_object
);
2283 static MonoReflectionModule
*
2284 ves_icall_MonoType_get_Module (MonoReflectionType
*type
)
2286 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2288 MONO_ARCH_SAVE_REGS
;
2290 return mono_module_get_object (mono_object_domain (type
), class->image
);
2293 static MonoReflectionAssembly
*
2294 ves_icall_MonoType_get_Assembly (MonoReflectionType
*type
)
2296 MonoDomain
*domain
= mono_domain_get ();
2297 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2299 MONO_ARCH_SAVE_REGS
;
2301 return mono_assembly_get_object (domain
, class->image
->assembly
);
2304 static MonoReflectionType
*
2305 ves_icall_MonoType_get_DeclaringType (MonoReflectionType
*type
)
2307 MonoDomain
*domain
= mono_domain_get ();
2310 MONO_ARCH_SAVE_REGS
;
2312 if (type
->type
->byref
)
2314 if (type
->type
->type
== MONO_TYPE_VAR
)
2315 class = mono_type_get_generic_param_owner (type
->type
)->owner
.klass
;
2316 else if (type
->type
->type
== MONO_TYPE_MVAR
)
2317 class = mono_type_get_generic_param_owner (type
->type
)->owner
.method
->klass
;
2319 class = mono_class_from_mono_type (type
->type
)->nested_in
;
2321 return class ? mono_type_get_object (domain
, &class->byval_arg
) : NULL
;
2324 static MonoReflectionType
*
2325 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType
*type
)
2327 MonoDomain
*domain
= mono_domain_get ();
2328 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2330 MONO_ARCH_SAVE_REGS
;
2332 if (class->enumtype
&& mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2333 return mono_type_get_object (domain
, mono_class_enum_basetype (class));
2334 else if (class->element_class
)
2335 return mono_type_get_object (domain
, &class->element_class
->byval_arg
);
2341 ves_icall_MonoType_get_Name (MonoReflectionType
*type
)
2343 MonoDomain
*domain
= mono_domain_get ();
2344 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2346 MONO_ARCH_SAVE_REGS
;
2348 if (type
->type
->byref
) {
2349 char *n
= g_strdup_printf ("%s&", class->name
);
2350 MonoString
*res
= mono_string_new (domain
, n
);
2356 return mono_string_new (domain
, class->name
);
2361 ves_icall_MonoType_get_Namespace (MonoReflectionType
*type
)
2363 MonoDomain
*domain
= mono_domain_get ();
2364 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2366 MONO_ARCH_SAVE_REGS
;
2368 while (class->nested_in
)
2369 class = class->nested_in
;
2371 if (class->name_space
[0] == '\0')
2374 return mono_string_new (domain
, class->name_space
);
2378 ves_icall_MonoType_GetArrayRank (MonoReflectionType
*type
)
2382 if (type
->type
->type
!= MONO_TYPE_ARRAY
&& type
->type
->type
!= MONO_TYPE_SZARRAY
)
2383 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2385 class = mono_class_from_mono_type (type
->type
);
2390 ves_icall_MonoType_GetGenericArguments (MonoReflectionType
*type
)
2393 MonoClass
*klass
, *pklass
;
2394 MonoDomain
*domain
= mono_object_domain (type
);
2395 MonoVTable
*array_vtable
= mono_class_vtable_full (domain
, mono_array_class_get_cached (mono_defaults
.systemtype_class
, 1), TRUE
);
2397 MONO_ARCH_SAVE_REGS
;
2399 klass
= mono_class_from_mono_type (type
->type
);
2401 if (klass
->generic_container
) {
2402 MonoGenericContainer
*container
= klass
->generic_container
;
2403 res
= mono_array_new_specific (array_vtable
, container
->type_argc
);
2404 for (i
= 0; i
< container
->type_argc
; ++i
) {
2405 pklass
= mono_class_from_generic_parameter (mono_generic_container_get_param (container
, i
), klass
->image
, FALSE
);
2406 mono_array_setref (res
, i
, mono_type_get_object (domain
, &pklass
->byval_arg
));
2408 } else if (klass
->generic_class
) {
2409 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
2410 res
= mono_array_new_specific (array_vtable
, inst
->type_argc
);
2411 for (i
= 0; i
< inst
->type_argc
; ++i
)
2412 mono_array_setref (res
, i
, mono_type_get_object (domain
, inst
->type_argv
[i
]));
2414 res
= mono_array_new_specific (array_vtable
, 0);
2420 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType
*type
)
2423 MONO_ARCH_SAVE_REGS
;
2425 if (!IS_MONOTYPE (type
))
2428 if (type
->type
->byref
)
2431 klass
= mono_class_from_mono_type (type
->type
);
2433 return klass
->generic_container
!= NULL
;
2436 static MonoReflectionType
*
2437 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType
*type
)
2440 MONO_ARCH_SAVE_REGS
;
2442 if (type
->type
->byref
)
2445 klass
= mono_class_from_mono_type (type
->type
);
2446 if (klass
->generic_container
) {
2447 return type
; /* check this one */
2449 if (klass
->generic_class
) {
2450 MonoClass
*generic_class
= klass
->generic_class
->container_class
;
2453 tb
= mono_class_get_ref_info (generic_class
);
2455 if (generic_class
->wastypebuilder
&& tb
)
2458 return mono_type_get_object (mono_object_domain (type
), &generic_class
->byval_arg
);
2463 static MonoReflectionType
*
2464 ves_icall_Type_MakeGenericType (MonoReflectionType
*type
, MonoArray
*type_array
)
2466 MonoType
*geninst
, **types
;
2469 MONO_ARCH_SAVE_REGS
;
2471 count
= mono_array_length (type_array
);
2472 types
= g_new0 (MonoType
*, count
);
2474 for (i
= 0; i
< count
; i
++) {
2475 MonoReflectionType
*t
= mono_array_get (type_array
, gpointer
, i
);
2476 types
[i
] = t
->type
;
2479 geninst
= mono_reflection_bind_generic_parameters (type
, count
, types
);
2484 return mono_type_get_object (mono_object_domain (type
), geninst
);
2488 ves_icall_Type_get_IsGenericInstance (MonoReflectionType
*type
)
2491 MONO_ARCH_SAVE_REGS
;
2493 if (type
->type
->byref
)
2496 klass
= mono_class_from_mono_type (type
->type
);
2497 return klass
->generic_class
!= NULL
;
2501 ves_icall_Type_get_IsGenericType (MonoReflectionType
*type
)
2504 MONO_ARCH_SAVE_REGS
;
2506 if (!IS_MONOTYPE (type
))
2509 if (type
->type
->byref
)
2512 klass
= mono_class_from_mono_type (type
->type
);
2513 return klass
->generic_class
!= NULL
|| klass
->generic_container
!= NULL
;
2517 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType
*type
)
2519 MONO_ARCH_SAVE_REGS
;
2521 if (!IS_MONOTYPE (type
))
2524 if (is_generic_parameter (type
->type
))
2525 return mono_type_get_generic_param_num (type
->type
);
2529 static GenericParameterAttributes
2530 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType
*type
)
2532 MONO_ARCH_SAVE_REGS
;
2534 g_assert (IS_MONOTYPE (type
));
2535 g_assert (is_generic_parameter (type
->type
));
2536 return mono_generic_param_info (type
->type
->data
.generic_param
)->flags
;
2540 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType
*type
)
2542 MonoGenericParamInfo
*param_info
;
2548 MONO_ARCH_SAVE_REGS
;
2550 g_assert (IS_MONOTYPE (type
));
2552 domain
= mono_object_domain (type
);
2553 param_info
= mono_generic_param_info (type
->type
->data
.generic_param
);
2554 for (count
= 0, ptr
= param_info
->constraints
; ptr
&& *ptr
; ptr
++, count
++)
2557 res
= mono_array_new (domain
, mono_defaults
.monotype_class
, count
);
2558 for (i
= 0; i
< count
; i
++)
2559 mono_array_setref (res
, i
, mono_type_get_object (domain
, ¶m_info
->constraints
[i
]->byval_arg
));
2566 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType
*type
)
2568 MONO_ARCH_SAVE_REGS
;
2569 return is_generic_parameter (type
->type
);
2573 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder
*tb
)
2575 MONO_ARCH_SAVE_REGS
;
2576 return is_generic_parameter (tb
->type
.type
);
2580 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType
*enumtype
,
2581 MonoReflectionType
*t
)
2583 enumtype
->type
= t
->type
;
2586 static MonoReflectionMethod
*
2587 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType
*type
,
2588 MonoReflectionMethod
* generic
)
2595 MONO_ARCH_SAVE_REGS
;
2597 domain
= ((MonoObject
*)type
)->vtable
->domain
;
2599 klass
= mono_class_from_mono_type (type
->type
);
2602 while ((method
= mono_class_get_methods (klass
, &iter
))) {
2603 if (method
->token
== generic
->method
->token
)
2604 return mono_method_get_object (domain
, method
, klass
);
2612 static MonoReflectionMethod
*
2613 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType
*ref_type
)
2616 MonoType
*type
= ref_type
->type
;
2618 MONO_ARCH_SAVE_REGS
;
2620 if (type
->byref
|| (type
->type
!= MONO_TYPE_MVAR
&& type
->type
!= MONO_TYPE_VAR
))
2621 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2622 if (type
->type
== MONO_TYPE_VAR
)
2625 method
= mono_type_get_generic_param_owner (type
)->owner
.method
;
2627 return mono_method_get_object (mono_object_domain (ref_type
), method
, method
->klass
);
2630 static MonoReflectionDllImportAttribute
*
2631 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod
*method
)
2633 static MonoClass
*DllImportAttributeClass
= NULL
;
2634 MonoDomain
*domain
= mono_domain_get ();
2635 MonoReflectionDllImportAttribute
*attr
;
2636 MonoImage
*image
= method
->klass
->image
;
2637 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)method
;
2638 MonoTableInfo
*tables
= image
->tables
;
2639 MonoTableInfo
*im
= &tables
[MONO_TABLE_IMPLMAP
];
2640 MonoTableInfo
*mr
= &tables
[MONO_TABLE_MODULEREF
];
2641 guint32 im_cols
[MONO_IMPLMAP_SIZE
];
2642 guint32 scope_token
;
2643 const char *import
= NULL
;
2644 const char *scope
= NULL
;
2647 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
2650 if (!DllImportAttributeClass
) {
2651 DllImportAttributeClass
=
2652 mono_class_from_name (mono_defaults
.corlib
,
2653 "System.Runtime.InteropServices", "DllImportAttribute");
2654 g_assert (DllImportAttributeClass
);
2657 if (method
->klass
->image
->dynamic
) {
2658 MonoReflectionMethodAux
*method_aux
=
2659 g_hash_table_lookup (
2660 ((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
2662 import
= method_aux
->dllentry
;
2663 scope
= method_aux
->dll
;
2666 if (!import
|| !scope
) {
2667 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2672 if (piinfo
->implmap_idx
) {
2673 mono_metadata_decode_row (im
, piinfo
->implmap_idx
- 1, im_cols
, MONO_IMPLMAP_SIZE
);
2675 piinfo
->piflags
= im_cols
[MONO_IMPLMAP_FLAGS
];
2676 import
= mono_metadata_string_heap (image
, im_cols
[MONO_IMPLMAP_NAME
]);
2677 scope_token
= mono_metadata_decode_row_col (mr
, im_cols
[MONO_IMPLMAP_SCOPE
] - 1, MONO_MODULEREF_NAME
);
2678 scope
= mono_metadata_string_heap (image
, scope_token
);
2681 flags
= piinfo
->piflags
;
2683 attr
= (MonoReflectionDllImportAttribute
*)mono_object_new (domain
, DllImportAttributeClass
);
2685 MONO_OBJECT_SETREF (attr
, dll
, mono_string_new (domain
, scope
));
2686 MONO_OBJECT_SETREF (attr
, entry_point
, mono_string_new (domain
, import
));
2687 attr
->call_conv
= (flags
& 0x700) >> 8;
2688 attr
->charset
= ((flags
& 0x6) >> 1) + 1;
2689 if (attr
->charset
== 1)
2691 attr
->exact_spelling
= (flags
& 0x1) != 0;
2692 attr
->set_last_error
= (flags
& 0x40) != 0;
2693 attr
->best_fit_mapping
= (flags
& 0x30) == 0x10;
2694 attr
->throw_on_unmappable
= (flags
& 0x3000) == 0x1000;
2695 attr
->preserve_sig
= FALSE
;
2700 static MonoReflectionMethod
*
2701 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod
*method
)
2703 MonoMethodInflated
*imethod
;
2706 MONO_ARCH_SAVE_REGS
;
2708 if (method
->method
->is_generic
)
2711 if (!method
->method
->is_inflated
)
2714 imethod
= (MonoMethodInflated
*) method
->method
;
2716 result
= imethod
->declaring
;
2717 /* Not a generic method. */
2718 if (!result
->is_generic
)
2721 if (method
->method
->klass
->image
->dynamic
) {
2722 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->method
->klass
->image
;
2723 MonoReflectionMethod
*res
;
2726 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2727 * the dynamic case as well ?
2729 mono_loader_lock ();
2730 res
= mono_g_hash_table_lookup (image
->generic_def_objects
, imethod
);
2731 mono_loader_unlock ();
2737 if (imethod
->context
.class_inst
) {
2738 MonoClass
*klass
= ((MonoMethod
*) imethod
)->klass
;
2739 /*Generic methods gets the context of the GTD.*/
2740 if (mono_class_get_context (klass
))
2741 result
= mono_class_inflate_generic_method_full (result
, klass
, mono_class_get_context (klass
));
2744 return mono_method_get_object (mono_object_domain (method
), result
, NULL
);
2748 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod
*method
)
2750 MONO_ARCH_SAVE_REGS
;
2752 return mono_method_signature (method
->method
)->generic_param_count
!= 0;
2756 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod
*method
)
2758 MONO_ARCH_SAVE_REGS
;
2760 return method
->method
->is_generic
;
2764 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod
*method
)
2769 MONO_ARCH_SAVE_REGS
;
2771 domain
= mono_object_domain (method
);
2773 if (method
->method
->is_inflated
) {
2774 MonoGenericInst
*inst
= mono_method_get_context (method
->method
)->method_inst
;
2777 count
= inst
->type_argc
;
2778 res
= mono_array_new (domain
, mono_defaults
.systemtype_class
, count
);
2780 for (i
= 0; i
< count
; i
++)
2781 mono_array_setref (res
, i
, mono_type_get_object (domain
, inst
->type_argv
[i
]));
2787 count
= mono_method_signature (method
->method
)->generic_param_count
;
2788 res
= mono_array_new (domain
, mono_defaults
.systemtype_class
, count
);
2790 for (i
= 0; i
< count
; i
++) {
2791 MonoGenericContainer
*container
= mono_method_get_generic_container (method
->method
);
2792 MonoGenericParam
*param
= mono_generic_container_get_param (container
, i
);
2793 MonoClass
*pklass
= mono_class_from_generic_parameter (
2794 param
, method
->method
->klass
->image
, TRUE
);
2795 mono_array_setref (res
, i
,
2796 mono_type_get_object (domain
, &pklass
->byval_arg
));
2803 ves_icall_InternalInvoke (MonoReflectionMethod
*method
, MonoObject
*this, MonoArray
*params
, MonoException
**exc
)
2806 * Invoke from reflection is supposed to always be a virtual call (the API
2807 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2808 * greater flexibility.
2810 MonoMethod
*m
= method
->method
;
2814 MONO_ARCH_SAVE_REGS
;
2818 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
2819 mono_security_core_clr_ensure_reflection_access_method (m
);
2821 if (!(m
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
2823 if (!mono_object_isinst (this, m
->klass
)) {
2824 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Object does not match target type."));
2827 m
= mono_object_get_virtual_method (this, m
);
2828 /* must pass the pointer to the value for valuetype methods */
2829 if (m
->klass
->valuetype
)
2830 obj
= mono_object_unbox (this);
2831 } else if (strcmp (m
->name
, ".ctor") && !m
->wrapper_type
) {
2832 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Non-static method requires a target."));
2837 pcount
= params
? mono_array_length (params
): 0;
2838 if (pcount
!= mono_method_signature (m
)->param_count
) {
2839 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name (mono_defaults
.corlib
, "System.Reflection", "TargetParameterCountException"));
2843 if ((m
->klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
) && !strcmp (m
->name
, ".ctor") && !this) {
2844 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."));
2848 if (m
->klass
->image
->assembly
->ref_only
) {
2849 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."));
2853 if (m
->klass
->rank
&& !strcmp (m
->name
, ".ctor")) {
2855 mono_array_size_t
*lengths
;
2856 mono_array_size_t
*lower_bounds
;
2857 pcount
= mono_array_length (params
);
2858 lengths
= alloca (sizeof (mono_array_size_t
) * pcount
);
2859 for (i
= 0; i
< pcount
; ++i
)
2860 lengths
[i
] = *(mono_array_size_t
*) ((char*)mono_array_get (params
, gpointer
, i
) + sizeof (MonoObject
));
2862 if (m
->klass
->rank
== pcount
) {
2863 /* Only lengths provided. */
2864 lower_bounds
= NULL
;
2866 g_assert (pcount
== (m
->klass
->rank
* 2));
2867 /* lower bounds are first. */
2868 lower_bounds
= lengths
;
2869 lengths
+= m
->klass
->rank
;
2872 return (MonoObject
*)mono_array_new_full (mono_object_domain (params
), m
->klass
, lengths
, lower_bounds
);
2874 return mono_runtime_invoke_array (m
, obj
, params
, NULL
);
2878 ves_icall_InternalExecute (MonoReflectionMethod
*method
, MonoObject
*this, MonoArray
*params
, MonoArray
**outArgs
)
2880 MonoDomain
*domain
= mono_object_domain (method
);
2881 MonoMethod
*m
= method
->method
;
2882 MonoMethodSignature
*sig
= mono_method_signature (m
);
2883 MonoArray
*out_args
;
2885 int i
, j
, outarg_count
= 0;
2887 MONO_ARCH_SAVE_REGS
;
2889 if (m
->klass
== mono_defaults
.object_class
) {
2891 if (!strcmp (m
->name
, "FieldGetter")) {
2892 MonoClass
*k
= this->vtable
->klass
;
2896 /* If this is a proxy, then it must be a CBO */
2897 if (k
== mono_defaults
.transparent_proxy_class
) {
2898 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
2899 this = tp
->rp
->unwrapped_server
;
2901 k
= this->vtable
->klass
;
2904 name
= mono_array_get (params
, MonoString
*, 1);
2905 str
= mono_string_to_utf8 (name
);
2908 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
2910 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2911 if (field_klass
->valuetype
)
2912 result
= mono_value_box (domain
, field_klass
, (char *)this + field
->offset
);
2914 result
= *((gpointer
*)((char *)this + field
->offset
));
2916 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 1);
2917 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2918 mono_array_setref (out_args
, 0, result
);
2926 g_assert_not_reached ();
2928 } else if (!strcmp (m
->name
, "FieldSetter")) {
2929 MonoClass
*k
= this->vtable
->klass
;
2935 /* If this is a proxy, then it must be a CBO */
2936 if (k
== mono_defaults
.transparent_proxy_class
) {
2937 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
2938 this = tp
->rp
->unwrapped_server
;
2940 k
= this->vtable
->klass
;
2943 name
= mono_array_get (params
, MonoString
*, 1);
2944 str
= mono_string_to_utf8 (name
);
2947 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
2949 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2950 MonoObject
*val
= mono_array_get (params
, gpointer
, 2);
2952 if (field_klass
->valuetype
) {
2953 size
= mono_type_size (field
->type
, &align
);
2954 g_assert (size
== mono_class_value_size (field_klass
, NULL
));
2955 mono_gc_wbarrier_value_copy ((char *)this + field
->offset
, (char*)val
+ sizeof (MonoObject
), 1, field_klass
);
2957 mono_gc_wbarrier_set_field (this, (char*)this + field
->offset
, val
);
2960 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 0);
2961 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2971 g_assert_not_reached ();
2976 for (i
= 0; i
< mono_array_length (params
); i
++) {
2977 if (sig
->params
[i
]->byref
)
2981 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, outarg_count
);
2983 /* handle constructors only for objects already allocated */
2984 if (!strcmp (method
->method
->name
, ".ctor"))
2987 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2988 g_assert (!method
->method
->klass
->valuetype
);
2989 result
= mono_runtime_invoke_array (method
->method
, this, params
, NULL
);
2991 for (i
= 0, j
= 0; i
< mono_array_length (params
); i
++) {
2992 if (sig
->params
[i
]->byref
) {
2994 arg
= mono_array_get (params
, gpointer
, i
);
2995 mono_array_setref (out_args
, j
, arg
);
3000 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
3006 read_enum_value (char *mem
, int type
)
3010 return *(guint8
*)mem
;
3012 return *(gint8
*)mem
;
3014 return *(guint16
*)mem
;
3016 return *(gint16
*)mem
;
3018 return *(guint32
*)mem
;
3020 return *(gint32
*)mem
;
3022 return *(guint64
*)mem
;
3024 return *(gint64
*)mem
;
3026 g_assert_not_reached ();
3032 write_enum_value (char *mem
, int type
, guint64 value
)
3036 case MONO_TYPE_I1
: {
3037 guint8
*p
= (guint8
*)mem
;
3042 case MONO_TYPE_I2
: {
3043 guint16
*p
= (void*)mem
;
3048 case MONO_TYPE_I4
: {
3049 guint32
*p
= (void*)mem
;
3054 case MONO_TYPE_I8
: {
3055 guint64
*p
= (void*)mem
;
3060 g_assert_not_reached ();
3066 ves_icall_System_Enum_ToObject (MonoReflectionType
*enumType
, MonoObject
*value
)
3069 MonoClass
*enumc
, *objc
;
3073 MONO_ARCH_SAVE_REGS
;
3075 MONO_CHECK_ARG_NULL (enumType
);
3076 MONO_CHECK_ARG_NULL (value
);
3078 domain
= mono_object_domain (enumType
);
3079 enumc
= mono_class_from_mono_type (enumType
->type
);
3080 objc
= value
->vtable
->klass
;
3082 if (!enumc
->enumtype
)
3083 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3084 if (!((objc
->enumtype
) || (objc
->byval_arg
.type
>= MONO_TYPE_I1
&& objc
->byval_arg
.type
<= MONO_TYPE_U8
)))
3085 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
3087 res
= mono_object_new (domain
, enumc
);
3088 val
= read_enum_value ((char *)value
+ sizeof (MonoObject
), objc
->enumtype
? mono_class_enum_basetype (objc
)->type
: objc
->byval_arg
.type
);
3089 write_enum_value ((char *)res
+ sizeof (MonoObject
), mono_class_enum_basetype (enumc
)->type
, val
);
3095 ves_icall_System_Enum_get_value (MonoObject
*this)
3103 MONO_ARCH_SAVE_REGS
;
3108 g_assert (this->vtable
->klass
->enumtype
);
3110 enumc
= mono_class_from_mono_type (mono_class_enum_basetype (this->vtable
->klass
));
3111 res
= mono_object_new (mono_object_domain (this), enumc
);
3112 dst
= (char *)res
+ sizeof (MonoObject
);
3113 src
= (char *)this + sizeof (MonoObject
);
3114 size
= mono_class_value_size (enumc
, NULL
);
3116 memcpy (dst
, src
, size
);
3121 static MonoReflectionType
*
3122 ves_icall_System_Enum_get_underlying_type (MonoReflectionType
*type
)
3124 MONO_ARCH_SAVE_REGS
;
3126 return mono_type_get_object (mono_object_domain (type
), mono_class_enum_basetype (mono_class_from_mono_type (type
->type
)));
3130 ves_icall_System_Enum_compare_value_to (MonoObject
*this, MonoObject
*other
)
3132 gpointer tdata
= (char *)this + sizeof (MonoObject
);
3133 gpointer odata
= (char *)other
+ sizeof (MonoObject
);
3134 MonoType
*basetype
= mono_class_enum_basetype (this->vtable
->klass
);
3135 g_assert (basetype
);
3137 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3138 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3139 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3142 return me > other ? 1 : -1; \
3145 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3146 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3147 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3150 return me - other; \
3153 switch (basetype
->type
) {
3155 COMPARE_ENUM_VALUES (guint8
);
3157 COMPARE_ENUM_VALUES (gint8
);
3158 case MONO_TYPE_CHAR
:
3160 COMPARE_ENUM_VALUES_RANGE (guint16
);
3162 COMPARE_ENUM_VALUES (gint16
);
3164 COMPARE_ENUM_VALUES (guint32
);
3166 COMPARE_ENUM_VALUES (gint32
);
3168 COMPARE_ENUM_VALUES (guint64
);
3170 COMPARE_ENUM_VALUES (gint64
);
3172 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3174 #undef COMPARE_ENUM_VALUES_RANGE
3175 #undef COMPARE_ENUM_VALUES
3180 ves_icall_System_Enum_get_hashcode (MonoObject
*this)
3182 gpointer data
= (char *)this + sizeof (MonoObject
);
3183 MonoType
*basetype
= mono_class_enum_basetype (this->vtable
->klass
);
3184 g_assert (basetype
);
3186 switch (basetype
->type
) {
3188 return *((gint8
*)data
);
3190 return *((guint8
*)data
);
3191 case MONO_TYPE_CHAR
:
3193 return *((guint16
*)data
);
3196 return *((gint16
*)data
);
3198 return *((guint32
*)data
);
3200 return *((gint32
*)data
);
3202 case MONO_TYPE_I8
: {
3203 gint64 value
= *((gint64
*)data
);
3204 return (gint
)(value
& 0xffffffff) ^ (int)(value
>> 32);
3207 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3213 ves_icall_get_enum_info (MonoReflectionType
*type
, MonoEnumInfo
*info
)
3215 MonoDomain
*domain
= mono_object_domain (type
);
3216 MonoClass
*enumc
= mono_class_from_mono_type (type
->type
);
3217 guint j
= 0, nvalues
, crow
;
3219 MonoClassField
*field
;
3221 MONO_ARCH_SAVE_REGS
;
3223 MONO_STRUCT_SETREF (info
, utype
, mono_type_get_object (domain
, mono_class_enum_basetype (enumc
)));
3224 nvalues
= mono_class_num_fields (enumc
) ? mono_class_num_fields (enumc
) - 1 : 0;
3225 MONO_STRUCT_SETREF (info
, names
, mono_array_new (domain
, mono_defaults
.string_class
, nvalues
));
3226 MONO_STRUCT_SETREF (info
, values
, mono_array_new (domain
, enumc
, nvalues
));
3230 while ((field
= mono_class_get_fields (enumc
, &iter
))) {
3233 MonoTypeEnum def_type
;
3235 if (strcmp ("value__", mono_field_get_name (field
)) == 0)
3237 if (mono_field_is_deleted (field
))
3239 mono_array_setref (info
->names
, j
, mono_string_new (domain
, mono_field_get_name (field
)));
3241 p
= mono_class_get_field_default_value (field
, &def_type
);
3242 len
= mono_metadata_decode_blob_size (p
, &p
);
3243 switch (mono_class_enum_basetype (enumc
)->type
) {
3246 mono_array_set (info
->values
, gchar
, j
, *p
);
3248 case MONO_TYPE_CHAR
:
3251 mono_array_set (info
->values
, gint16
, j
, read16 (p
));
3255 mono_array_set (info
->values
, gint32
, j
, read32 (p
));
3259 mono_array_set (info
->values
, gint64
, j
, read64 (p
));
3262 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc
)->type
);
3269 BFLAGS_IgnoreCase
= 1,
3270 BFLAGS_DeclaredOnly
= 2,
3271 BFLAGS_Instance
= 4,
3273 BFLAGS_Public
= 0x10,
3274 BFLAGS_NonPublic
= 0x20,
3275 BFLAGS_FlattenHierarchy
= 0x40,
3276 BFLAGS_InvokeMethod
= 0x100,
3277 BFLAGS_CreateInstance
= 0x200,
3278 BFLAGS_GetField
= 0x400,
3279 BFLAGS_SetField
= 0x800,
3280 BFLAGS_GetProperty
= 0x1000,
3281 BFLAGS_SetProperty
= 0x2000,
3282 BFLAGS_ExactBinding
= 0x10000,
3283 BFLAGS_SuppressChangeType
= 0x20000,
3284 BFLAGS_OptionalParamBinding
= 0x40000
3287 static MonoReflectionField
*
3288 ves_icall_Type_GetField (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3291 MonoClass
*startklass
, *klass
;
3293 MonoClassField
*field
;
3296 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3297 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3298 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3300 MONO_ARCH_SAVE_REGS
;
3303 mono_raise_exception (mono_get_exception_argument_null ("name"));
3304 if (type
->type
->byref
)
3307 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
3310 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3311 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3314 while ((field
= mono_class_get_fields (klass
, &iter
))) {
3317 if (field
->type
== NULL
)
3319 if (mono_field_is_deleted (field
))
3321 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3322 if (bflags
& BFLAGS_Public
)
3324 } else if ((klass
== startklass
) || (field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3325 if (bflags
& BFLAGS_NonPublic
) {
3332 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
3333 if (bflags
& BFLAGS_Static
)
3334 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3337 if (bflags
& BFLAGS_Instance
)
3344 utf8_name
= mono_string_to_utf8 (name
);
3346 if (compare_func (mono_field_get_name (field
), utf8_name
)) {
3352 return mono_field_get_object (domain
, klass
, field
);
3354 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3361 ves_icall_Type_GetFields_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3364 MonoClass
*startklass
, *klass
, *refklass
;
3369 MonoClassField
*field
;
3370 MonoPtrArray tmp_array
;
3372 MONO_ARCH_SAVE_REGS
;
3374 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3375 if (type
->type
->byref
)
3376 return mono_array_new (domain
, mono_defaults
.field_info_class
, 0);
3377 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3378 refklass
= mono_class_from_mono_type (reftype
->type
);
3380 mono_ptr_array_init (tmp_array
, 2);
3383 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3384 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3387 while ((field
= mono_class_get_fields (klass
, &iter
))) {
3389 if (mono_field_is_deleted (field
))
3391 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3392 if (bflags
& BFLAGS_Public
)
3394 } else if ((klass
== startklass
) || (field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3395 if (bflags
& BFLAGS_NonPublic
) {
3402 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
3403 if (bflags
& BFLAGS_Static
)
3404 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3407 if (bflags
& BFLAGS_Instance
)
3413 member
= (MonoObject
*)mono_field_get_object (domain
, refklass
, field
);
3414 mono_ptr_array_append (tmp_array
, member
);
3416 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3419 res
= mono_array_new_cached (domain
, mono_defaults
.field_info_class
, mono_ptr_array_size (tmp_array
));
3421 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3422 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3424 mono_ptr_array_destroy (tmp_array
);
3430 method_nonpublic (MonoMethod
* method
, gboolean start_klass
)
3432 switch (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) {
3433 case METHOD_ATTRIBUTE_ASSEM
:
3434 return (start_klass
|| mono_defaults
.generic_ilist_class
);
3435 case METHOD_ATTRIBUTE_PRIVATE
:
3437 case METHOD_ATTRIBUTE_PUBLIC
:
3445 ves_icall_Type_GetMethodsByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3447 static MonoClass
*MethodInfo_array
;
3449 MonoClass
*startklass
, *klass
, *refklass
;
3454 int i
, len
, match
, nslots
;
3455 /*FIXME, use MonoBitSet*/
3456 guint32 method_slots_default
[8];
3457 guint32
*method_slots
= NULL
;
3458 gchar
*mname
= NULL
;
3459 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3460 MonoVTable
*array_vtable
;
3462 MonoPtrArray tmp_array
;
3464 MONO_ARCH_SAVE_REGS
;
3466 mono_ptr_array_init (tmp_array
, 4);
3468 if (!MethodInfo_array
) {
3469 MonoClass
*klass
= mono_array_class_get (mono_defaults
.method_info_class
, 1);
3470 mono_memory_barrier ();
3471 MethodInfo_array
= klass
;
3474 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3475 array_vtable
= mono_class_vtable_full (domain
, MethodInfo_array
, TRUE
);
3476 if (type
->type
->byref
)
3477 return mono_array_new_specific (array_vtable
, 0);
3478 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3479 refklass
= mono_class_from_mono_type (reftype
->type
);
3482 mname
= mono_string_to_utf8 (name
);
3483 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3486 /* An optimization for calls made from Delegate:CreateDelegate () */
3487 if (klass
->delegate
&& mname
&& !strcmp (mname
, "Invoke") && (bflags
== (BFLAGS_Public
| BFLAGS_Static
| BFLAGS_Instance
))) {
3488 method
= mono_get_delegate_invoke (klass
);
3489 if (mono_loader_get_last_error ())
3492 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3494 res
= mono_array_new_specific (array_vtable
, 1);
3495 mono_array_setref (res
, 0, member
);
3500 mono_class_setup_vtable (klass
);
3501 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3504 if (is_generic_parameter (type
->type
))
3505 nslots
= mono_class_get_vtable_size (klass
->parent
);
3507 nslots
= MONO_CLASS_IS_INTERFACE (klass
) ? mono_class_num_methods (klass
) : mono_class_get_vtable_size (klass
);
3508 if (nslots
>= sizeof (method_slots_default
) * 8) {
3509 method_slots
= g_new0 (guint32
, nslots
/ 32 + 1);
3511 method_slots
= method_slots_default
;
3512 memset (method_slots
, 0, sizeof (method_slots_default
));
3515 mono_class_setup_vtable (klass
);
3516 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3520 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3522 if (method
->slot
!= -1) {
3523 g_assert (method
->slot
< nslots
);
3524 if (method_slots
[method
->slot
>> 5] & (1 << (method
->slot
& 0x1f)))
3526 if (!(method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
))
3527 method_slots
[method
->slot
>> 5] |= 1 << (method
->slot
& 0x1f);
3530 if (method
->name
[0] == '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0))
3532 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3533 if (bflags
& BFLAGS_Public
)
3535 } else if ((bflags
& BFLAGS_NonPublic
) && method_nonpublic (method
, (klass
== startklass
))) {
3541 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3542 if (bflags
& BFLAGS_Static
)
3543 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3546 if (bflags
& BFLAGS_Instance
)
3554 if (compare_func (mname
, method
->name
))
3560 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3562 mono_ptr_array_append (tmp_array
, member
);
3564 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3568 if (method_slots
!= method_slots_default
)
3569 g_free (method_slots
);
3571 res
= mono_array_new_specific (array_vtable
, mono_ptr_array_size (tmp_array
));
3573 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3574 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3576 mono_ptr_array_destroy (tmp_array
);
3581 if (method_slots
!= method_slots_default
)
3582 g_free (method_slots
);
3583 mono_ptr_array_destroy (tmp_array
);
3584 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3585 ex
= mono_class_get_exception_for_failure (klass
);
3587 ex
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3588 mono_loader_clear_error ();
3590 mono_raise_exception (ex
);
3595 ves_icall_Type_GetConstructors_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3598 static MonoClass
*System_Reflection_ConstructorInfo
;
3599 MonoClass
*startklass
, *klass
, *refklass
;
3604 gpointer iter
= NULL
;
3605 MonoPtrArray tmp_array
;
3607 MONO_ARCH_SAVE_REGS
;
3609 mono_ptr_array_init (tmp_array
, 4); /*FIXME, guestimating*/
3611 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3612 if (type
->type
->byref
)
3613 return mono_array_new_cached (domain
, mono_defaults
.method_info_class
, 0);
3614 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3615 refklass
= mono_class_from_mono_type (reftype
->type
);
3617 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3618 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3620 if (!System_Reflection_ConstructorInfo
)
3621 System_Reflection_ConstructorInfo
= mono_class_from_name (
3622 mono_defaults
.corlib
, "System.Reflection", "ConstructorInfo");
3625 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3627 if (strcmp (method
->name
, ".ctor") && strcmp (method
->name
, ".cctor"))
3629 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3630 if (bflags
& BFLAGS_Public
)
3633 if (bflags
& BFLAGS_NonPublic
)
3639 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3640 if (bflags
& BFLAGS_Static
)
3641 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3644 if (bflags
& BFLAGS_Instance
)
3650 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3652 mono_ptr_array_append (tmp_array
, member
);
3655 res
= mono_array_new_cached (domain
, System_Reflection_ConstructorInfo
, mono_ptr_array_size (tmp_array
));
3657 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3658 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3660 mono_ptr_array_destroy (tmp_array
);
3666 property_hash (gconstpointer data
)
3668 MonoProperty
*prop
= (MonoProperty
*)data
;
3670 return g_str_hash (prop
->name
);
3674 property_equal (MonoProperty
*prop1
, MonoProperty
*prop2
)
3676 // Properties are hide-by-name-and-signature
3677 if (!g_str_equal (prop1
->name
, prop2
->name
))
3680 if (prop1
->get
&& prop2
->get
&& !mono_metadata_signature_equal (mono_method_signature (prop1
->get
), mono_method_signature (prop2
->get
)))
3682 if (prop1
->set
&& prop2
->set
&& !mono_metadata_signature_equal (mono_method_signature (prop1
->set
), mono_method_signature (prop2
->set
)))
3688 property_accessor_nonpublic (MonoMethod
* accessor
, gboolean start_klass
)
3693 return method_nonpublic (accessor
, start_klass
);
3697 ves_icall_Type_GetPropertiesByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3700 static MonoClass
*System_Reflection_PropertyInfo
;
3701 MonoClass
*startklass
, *klass
;
3707 gchar
*propname
= NULL
;
3708 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3710 GHashTable
*properties
;
3711 MonoPtrArray tmp_array
;
3713 MONO_ARCH_SAVE_REGS
;
3715 mono_ptr_array_init (tmp_array
, 8); /*This the average for ASP.NET types*/
3717 if (!System_Reflection_PropertyInfo
)
3718 System_Reflection_PropertyInfo
= mono_class_from_name (
3719 mono_defaults
.corlib
, "System.Reflection", "PropertyInfo");
3721 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3722 if (type
->type
->byref
)
3723 return mono_array_new_cached (domain
, System_Reflection_PropertyInfo
, 0);
3724 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3726 propname
= mono_string_to_utf8 (name
);
3727 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3730 mono_class_setup_vtable (klass
);
3732 properties
= g_hash_table_new (property_hash
, (GEqualFunc
)property_equal
);
3734 mono_class_setup_vtable (klass
);
3735 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3736 g_hash_table_destroy (properties
);
3739 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3743 while ((prop
= mono_class_get_properties (klass
, &iter
))) {
3749 flags
= method
->flags
;
3752 if ((prop
->get
&& ((prop
->get
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
)) ||
3753 (prop
->set
&& ((prop
->set
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
))) {
3754 if (bflags
& BFLAGS_Public
)
3756 } else if (bflags
& BFLAGS_NonPublic
) {
3757 if (property_accessor_nonpublic(prop
->get
, startklass
== klass
) ||
3758 property_accessor_nonpublic(prop
->set
, startklass
== klass
)) {
3765 if (flags
& METHOD_ATTRIBUTE_STATIC
) {
3766 if (bflags
& BFLAGS_Static
)
3767 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3770 if (bflags
& BFLAGS_Instance
)
3779 if (compare_func (propname
, prop
->name
))
3783 if (g_hash_table_lookup (properties
, prop
))
3786 mono_ptr_array_append (tmp_array
, mono_property_get_object (domain
, startklass
, prop
));
3788 g_hash_table_insert (properties
, prop
, prop
);
3790 if ((!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
)))
3793 g_hash_table_destroy (properties
);
3796 res
= mono_array_new_cached (domain
, System_Reflection_PropertyInfo
, mono_ptr_array_size (tmp_array
));
3797 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3798 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3800 mono_ptr_array_destroy (tmp_array
);
3805 static MonoReflectionEvent
*
3806 ves_icall_MonoType_GetEvent (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3809 MonoClass
*klass
, *startklass
;
3815 MONO_ARCH_SAVE_REGS
;
3817 event_name
= mono_string_to_utf8 (name
);
3818 if (type
->type
->byref
)
3820 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3821 domain
= mono_object_domain (type
);
3824 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3825 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3828 while ((event
= mono_class_get_events (klass
, &iter
))) {
3829 if (strcmp (event
->name
, event_name
))
3832 method
= event
->add
;
3834 method
= event
->remove
;
3836 method
= event
->raise
;
3838 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3839 if (!(bflags
& BFLAGS_Public
))
3842 if (!(bflags
& BFLAGS_NonPublic
))
3844 if ((klass
!= startklass
) && (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PRIVATE
)
3848 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3849 if (!(bflags
& BFLAGS_Static
))
3851 if (!(bflags
& BFLAGS_FlattenHierarchy
) && (klass
!= startklass
))
3854 if (!(bflags
& BFLAGS_Instance
))
3858 if (!(bflags
& BFLAGS_NonPublic
))
3861 g_free (event_name
);
3862 return mono_event_get_object (domain
, startklass
, event
);
3865 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3868 g_free (event_name
);
3873 ves_icall_Type_GetEvents_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3876 static MonoClass
*System_Reflection_EventInfo
;
3877 MonoClass
*startklass
, *klass
;
3884 MonoPtrArray tmp_array
;
3886 MONO_ARCH_SAVE_REGS
;
3888 mono_ptr_array_init (tmp_array
, 4);
3890 if (!System_Reflection_EventInfo
)
3891 System_Reflection_EventInfo
= mono_class_from_name (
3892 mono_defaults
.corlib
, "System.Reflection", "EventInfo");
3894 domain
= mono_object_domain (type
);
3895 if (type
->type
->byref
)
3896 return mono_array_new_cached (domain
, System_Reflection_EventInfo
, 0);
3897 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3900 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3901 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3904 while ((event
= mono_class_get_events (klass
, &iter
))) {
3906 method
= event
->add
;
3908 method
= event
->remove
;
3910 method
= event
->raise
;
3912 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3913 if (bflags
& BFLAGS_Public
)
3915 } else if ((klass
== startklass
) || (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) {
3916 if (bflags
& BFLAGS_NonPublic
)
3921 if (bflags
& BFLAGS_NonPublic
)
3927 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3928 if (bflags
& BFLAGS_Static
)
3929 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3932 if (bflags
& BFLAGS_Instance
)
3937 if (bflags
& BFLAGS_Instance
)
3941 mono_ptr_array_append (tmp_array
, mono_event_get_object (domain
, startklass
, event
));
3943 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3946 res
= mono_array_new_cached (domain
, System_Reflection_EventInfo
, mono_ptr_array_size (tmp_array
));
3948 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3949 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3951 mono_ptr_array_destroy (tmp_array
);
3956 static MonoReflectionType
*
3957 ves_icall_Type_GetNestedType (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3965 MONO_ARCH_SAVE_REGS
;
3968 mono_raise_exception (mono_get_exception_argument_null ("name"));
3970 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3971 if (type
->type
->byref
)
3973 klass
= mono_class_from_mono_type (type
->type
);
3974 str
= mono_string_to_utf8 (name
);
3977 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3978 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3981 * If a nested type is generic, return its generic type definition.
3982 * Note that this means that the return value is essentially a
3983 * nested type of the generic type definition of @klass.
3985 * A note in MSDN claims that a generic type definition can have
3986 * nested types that aren't generic. In any case, the container of that
3987 * nested type would be the generic type definition.
3989 if (klass
->generic_class
)
3990 klass
= klass
->generic_class
->container_class
;
3993 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
3995 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
3996 if (bflags
& BFLAGS_Public
)
3999 if (bflags
& BFLAGS_NonPublic
)
4004 if (strcmp (nested
->name
, str
) == 0){
4006 return mono_type_get_object (domain
, &nested
->byval_arg
);
4009 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
4016 ves_icall_Type_GetNestedTypes (MonoReflectionType
*type
, guint32 bflags
)
4025 MonoPtrArray tmp_array
;
4027 MONO_ARCH_SAVE_REGS
;
4029 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4030 if (type
->type
->byref
)
4031 return mono_array_new (domain
, mono_defaults
.monotype_class
, 0);
4032 klass
= mono_class_from_mono_type (type
->type
);
4033 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
4034 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
4037 * If a nested type is generic, return its generic type definition.
4038 * Note that this means that the return value is essentially the set
4039 * of nested types of the generic type definition of @klass.
4041 * A note in MSDN claims that a generic type definition can have
4042 * nested types that aren't generic. In any case, the container of that
4043 * nested type would be the generic type definition.
4045 if (klass
->generic_class
)
4046 klass
= klass
->generic_class
->container_class
;
4048 mono_ptr_array_init (tmp_array
, 1);
4050 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
4052 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
4053 if (bflags
& BFLAGS_Public
)
4056 if (bflags
& BFLAGS_NonPublic
)
4061 member
= (MonoObject
*)mono_type_get_object (domain
, &nested
->byval_arg
);
4062 mono_ptr_array_append (tmp_array
, member
);
4065 res
= mono_array_new_cached (domain
, mono_defaults
.monotype_class
, mono_ptr_array_size (tmp_array
));
4067 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4068 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4070 mono_ptr_array_destroy (tmp_array
);
4075 static MonoReflectionType
*
4076 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly
*assembly
, MonoReflectionModule
*module
, MonoString
*name
, MonoBoolean throwOnError
, MonoBoolean ignoreCase
)
4079 MonoType
*type
= NULL
;
4080 MonoTypeNameParse info
;
4081 gboolean type_resolve
;
4083 MONO_ARCH_SAVE_REGS
;
4085 /* On MS.NET, this does not fire a TypeResolve event */
4086 type_resolve
= TRUE
;
4087 str
= mono_string_to_utf8 (name
);
4088 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4089 if (!mono_reflection_parse_type (str
, &info
)) {
4091 mono_reflection_free_type_info (&info
);
4092 if (throwOnError
) /* uhm: this is a parse error, though... */
4093 mono_raise_exception (mono_get_exception_type_load (name
, NULL
));
4094 /*g_print ("failed parse\n");*/
4098 if (info
.assembly
.name
) {
4100 mono_reflection_free_type_info (&info
);
4102 /* 1.0 and 2.0 throw different exceptions */
4103 if (mono_defaults
.generic_ilist_class
)
4104 mono_raise_exception (mono_get_exception_argument (NULL
, "Type names passed to Assembly.GetType() must not specify an assembly."));
4106 mono_raise_exception (mono_get_exception_type_load (name
, NULL
));
4111 if (module
!= NULL
) {
4113 type
= mono_reflection_get_type (module
->image
, &info
, ignoreCase
, &type_resolve
);
4118 if (assembly
->assembly
->dynamic
) {
4119 /* Enumerate all modules */
4120 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)assembly
;
4124 if (abuilder
->modules
) {
4125 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
4126 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
4127 type
= mono_reflection_get_type (&mb
->dynamic_image
->image
, &info
, ignoreCase
, &type_resolve
);
4133 if (!type
&& abuilder
->loaded_modules
) {
4134 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
4135 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
4136 type
= mono_reflection_get_type (mod
->image
, &info
, ignoreCase
, &type_resolve
);
4143 type
= mono_reflection_get_type (assembly
->assembly
->image
, &info
, ignoreCase
, &type_resolve
);
4145 mono_reflection_free_type_info (&info
);
4147 MonoException
*e
= NULL
;
4150 e
= mono_get_exception_type_load (name
, NULL
);
4152 if (mono_loader_get_last_error () && mono_defaults
.generic_ilist_class
)
4153 e
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4155 mono_loader_clear_error ();
4158 mono_raise_exception (e
);
4163 if (type
->type
== MONO_TYPE_CLASS
) {
4164 MonoClass
*klass
= mono_type_get_class (type
);
4166 if (mono_is_security_manager_active () && !klass
->exception_type
)
4167 /* Some security problems are detected during generic vtable construction */
4168 mono_class_setup_vtable (klass
);
4169 /* need to report exceptions ? */
4170 if (throwOnError
&& klass
->exception_type
) {
4171 /* report SecurityException (or others) that occured when loading the assembly */
4172 MonoException
*exc
= mono_class_get_exception_for_failure (klass
);
4173 mono_loader_clear_error ();
4174 mono_raise_exception (exc
);
4175 } else if (klass
->exception_type
== MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND
) {
4180 /* g_print ("got it\n"); */
4181 return mono_type_get_object (mono_object_domain (assembly
), type
);
4185 replace_shadow_path (MonoDomain
*domain
, gchar
*dirname
, gchar
**filename
)
4188 gchar
*shadow_ini_file
;
4191 /* Check for shadow-copied assembly */
4192 if (mono_is_shadow_copy_enabled (domain
, dirname
)) {
4193 shadow_ini_file
= g_build_filename (dirname
, "__AssemblyInfo__.ini", NULL
);
4195 if (!g_file_get_contents (shadow_ini_file
, &content
, &len
, NULL
) ||
4196 !g_file_test (content
, G_FILE_TEST_IS_REGULAR
)) {
4202 g_free (shadow_ini_file
);
4203 if (content
!= NULL
) {
4206 *filename
= content
;
4214 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly
*assembly
, MonoBoolean escaped
)
4216 MonoDomain
*domain
= mono_object_domain (assembly
);
4217 MonoAssembly
*mass
= assembly
->assembly
;
4218 MonoString
*res
= NULL
;
4223 MONO_ARCH_SAVE_REGS
;
4225 if (g_path_is_absolute (mass
->image
->name
)) {
4226 absolute
= g_strdup (mass
->image
->name
);
4227 dirname
= g_path_get_dirname (absolute
);
4229 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
4230 dirname
= g_strdup (mass
->basedir
);
4233 replace_shadow_path (domain
, dirname
, &absolute
);
4238 for (i
= strlen (absolute
) - 1; i
>= 0; i
--)
4239 if (absolute
[i
] == '\\')
4244 uri
= g_filename_to_uri (absolute
, NULL
, NULL
);
4246 const char *prepend
= "file://";
4248 if (*absolute
== '/' && *(absolute
+ 1) == '/') {
4251 prepend
= "file:///";
4254 uri
= g_strconcat (prepend
, absolute
, NULL
);
4258 res
= mono_string_new (domain
, uri
);
4266 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly
*assembly
)
4268 MonoAssembly
*mass
= assembly
->assembly
;
4270 MONO_ARCH_SAVE_REGS
;
4272 return mass
->in_gac
;
4275 static MonoReflectionAssembly
*
4276 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString
*mname
, MonoObject
*evidence
)
4280 MonoImageOpenStatus status
;
4282 MONO_ARCH_SAVE_REGS
;
4284 name
= mono_string_to_utf8 (mname
);
4285 res
= mono_assembly_load_with_partial_name (name
, &status
);
4291 return mono_assembly_get_object (mono_domain_get (), res
);
4295 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly
*assembly
)
4297 MonoDomain
*domain
= mono_object_domain (assembly
);
4300 MONO_ARCH_SAVE_REGS
;
4302 res
= mono_string_new (domain
, mono_image_get_filename (assembly
->assembly
->image
));
4308 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly
*assembly
)
4310 MONO_ARCH_SAVE_REGS
;
4312 return assembly
->assembly
->ref_only
;
4316 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly
*assembly
)
4318 MonoDomain
*domain
= mono_object_domain (assembly
);
4320 MONO_ARCH_SAVE_REGS
;
4322 return mono_string_new (domain
, assembly
->assembly
->image
->version
);
4325 static MonoReflectionMethod
*
4326 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly
*assembly
)
4328 guint32 token
= mono_image_get_entry_point (assembly
->assembly
->image
);
4330 MONO_ARCH_SAVE_REGS
;
4334 return mono_method_get_object (mono_object_domain (assembly
), mono_get_method (assembly
->assembly
->image
, token
, NULL
), NULL
);
4337 static MonoReflectionModule
*
4338 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly
*assembly
)
4340 return mono_module_get_object (mono_object_domain (assembly
), assembly
->assembly
->image
);
4344 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly
*assembly
)
4346 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4347 MonoArray
*result
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, table
->rows
);
4351 MONO_ARCH_SAVE_REGS
;
4353 for (i
= 0; i
< table
->rows
; ++i
) {
4354 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_MANIFEST_NAME
));
4355 mono_array_setref (result
, i
, mono_string_new (mono_object_domain (assembly
), val
));
4361 create_version (MonoDomain
*domain
, guint32 major
, guint32 minor
, guint32 build
, guint32 revision
)
4363 static MonoClass
*System_Version
= NULL
;
4364 static MonoMethod
*create_version
= NULL
;
4368 if (!System_Version
) {
4369 System_Version
= mono_class_from_name (mono_defaults
.corlib
, "System", "Version");
4370 g_assert (System_Version
);
4373 if (!create_version
) {
4374 MonoMethodDesc
*desc
= mono_method_desc_new (":.ctor(int,int,int,int)", FALSE
);
4375 create_version
= mono_method_desc_search_in_class (desc
, System_Version
);
4376 g_assert (create_version
);
4377 mono_method_desc_free (desc
);
4383 args
[3] = &revision
;
4384 result
= mono_object_new (domain
, System_Version
);
4385 mono_runtime_invoke (create_version
, result
, args
, NULL
);
4391 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly
*assembly
)
4393 static MonoClass
*System_Reflection_AssemblyName
;
4395 MonoDomain
*domain
= mono_object_domain (assembly
);
4397 static MonoMethod
*create_culture
= NULL
;
4398 MonoImage
*image
= assembly
->assembly
->image
;
4401 MONO_ARCH_SAVE_REGS
;
4403 if (!System_Reflection_AssemblyName
)
4404 System_Reflection_AssemblyName
= mono_class_from_name (
4405 mono_defaults
.corlib
, "System.Reflection", "AssemblyName");
4407 t
= &assembly
->assembly
->image
->tables
[MONO_TABLE_ASSEMBLYREF
];
4410 result
= mono_array_new (domain
, System_Reflection_AssemblyName
, count
);
4412 if (count
> 0 && !create_culture
) {
4413 MonoMethodDesc
*desc
= mono_method_desc_new (
4414 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4415 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4416 g_assert (create_culture
);
4417 mono_method_desc_free (desc
);
4420 for (i
= 0; i
< count
; i
++) {
4421 MonoReflectionAssemblyName
*aname
;
4422 guint32 cols
[MONO_ASSEMBLYREF_SIZE
];
4424 mono_metadata_decode_row (t
, i
, cols
, MONO_ASSEMBLYREF_SIZE
);
4426 aname
= (MonoReflectionAssemblyName
*) mono_object_new (
4427 domain
, System_Reflection_AssemblyName
);
4429 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_NAME
])));
4431 aname
->major
= cols
[MONO_ASSEMBLYREF_MAJOR_VERSION
];
4432 aname
->minor
= cols
[MONO_ASSEMBLYREF_MINOR_VERSION
];
4433 aname
->build
= cols
[MONO_ASSEMBLYREF_BUILD_NUMBER
];
4434 aname
->revision
= cols
[MONO_ASSEMBLYREF_REV_NUMBER
];
4435 aname
->flags
= cols
[MONO_ASSEMBLYREF_FLAGS
];
4436 aname
->versioncompat
= 1; /* SameMachine (default) */
4437 aname
->hashalg
= ASSEMBLY_HASH_SHA1
; /* SHA1 (default) */
4438 MONO_OBJECT_SETREF (aname
, version
, create_version (domain
, aname
->major
, aname
->minor
, aname
->build
, aname
->revision
));
4440 if (create_culture
) {
4442 MonoBoolean assembly_ref
= 1;
4443 args
[0] = mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_CULTURE
]));
4444 args
[1] = &assembly_ref
;
4445 MONO_OBJECT_SETREF (aname
, cultureInfo
, mono_runtime_invoke (create_culture
, NULL
, args
, NULL
));
4448 if (cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]) {
4449 const gchar
*pkey_ptr
= mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]);
4450 guint32 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
4452 if ((cols
[MONO_ASSEMBLYREF_FLAGS
] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
)) {
4453 /* public key token isn't copied - the class library will
4454 automatically generate it from the public key if required */
4455 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4456 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
4458 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4459 memcpy (mono_array_addr (aname
->keyToken
, guint8
, 0), pkey_ptr
, pkey_len
);
4462 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
4465 /* note: this function doesn't return the codebase on purpose (i.e. it can
4466 be used under partial trust as path information isn't present). */
4468 mono_array_setref (result
, i
, aname
);
4479 foreach_namespace (const char* key
, gconstpointer val
, NameSpaceInfo
*info
)
4481 MonoString
*name
= mono_string_new (mono_object_domain (info
->res
), key
);
4483 mono_array_setref (info
->res
, info
->idx
, name
);
4488 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly
*assembly
)
4490 MonoImage
*img
= assembly
->assembly
->image
;
4495 MONO_ARCH_SAVE_REGS
;
4497 mono_image_lock (img
);
4498 mono_image_init_name_cache (img
);
4501 len
= g_hash_table_size (img
->name_cache
);
4502 mono_image_unlock (img
);
4504 /*we can't create objects holding the image lock */
4505 res
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, len
);
4507 mono_image_lock (img
);
4508 /*len might have changed, create a new array*/
4509 if (len
!= g_hash_table_size (img
->name_cache
))
4514 g_hash_table_foreach (img
->name_cache
, (GHFunc
)foreach_namespace
, &info
);
4515 mono_image_unlock (img
);
4520 /* move this in some file in mono/util/ */
4522 g_concat_dir_and_file (const char *dir
, const char *file
)
4524 g_return_val_if_fail (dir
!= NULL
, NULL
);
4525 g_return_val_if_fail (file
!= NULL
, NULL
);
4528 * If the directory name doesn't have a / on the end, we need
4529 * to add one so we get a proper path to the file
4531 if (dir
[strlen(dir
) - 1] != G_DIR_SEPARATOR
)
4532 return g_strconcat (dir
, G_DIR_SEPARATOR_S
, file
, NULL
);
4534 return g_strconcat (dir
, file
, NULL
);
4538 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, gint32
*size
, MonoReflectionModule
**ref_module
)
4540 char *n
= mono_string_to_utf8 (name
);
4541 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4543 guint32 cols
[MONO_MANIFEST_SIZE
];
4544 guint32 impl
, file_idx
;
4548 MONO_ARCH_SAVE_REGS
;
4550 for (i
= 0; i
< table
->rows
; ++i
) {
4551 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
4552 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
4553 if (strcmp (val
, n
) == 0)
4557 if (i
== table
->rows
)
4560 impl
= cols
[MONO_MANIFEST_IMPLEMENTATION
];
4563 * this code should only be called after obtaining the
4564 * ResourceInfo and handling the other cases.
4566 g_assert ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
);
4567 file_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
4569 module
= mono_image_load_file_for_image (assembly
->assembly
->image
, file_idx
);
4574 module
= assembly
->assembly
->image
;
4576 mono_gc_wbarrier_generic_store (ref_module
, (MonoObject
*) mono_module_get_object (mono_domain_get (), module
));
4578 return (void*)mono_image_get_resource (module
, cols
[MONO_MANIFEST_OFFSET
], (guint32
*)size
);
4582 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoManifestResourceInfo
*info
)
4584 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4586 guint32 cols
[MONO_MANIFEST_SIZE
];
4587 guint32 file_cols
[MONO_FILE_SIZE
];
4591 MONO_ARCH_SAVE_REGS
;
4593 n
= mono_string_to_utf8 (name
);
4594 for (i
= 0; i
< table
->rows
; ++i
) {
4595 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
4596 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
4597 if (strcmp (val
, n
) == 0)
4601 if (i
== table
->rows
)
4604 if (!cols
[MONO_MANIFEST_IMPLEMENTATION
]) {
4605 info
->location
= RESOURCE_LOCATION_EMBEDDED
| RESOURCE_LOCATION_IN_MANIFEST
;
4608 switch (cols
[MONO_MANIFEST_IMPLEMENTATION
] & MONO_IMPLEMENTATION_MASK
) {
4609 case MONO_IMPLEMENTATION_FILE
:
4610 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
4611 table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
4612 mono_metadata_decode_row (table
, i
- 1, file_cols
, MONO_FILE_SIZE
);
4613 val
= mono_metadata_string_heap (assembly
->assembly
->image
, file_cols
[MONO_FILE_NAME
]);
4614 MONO_OBJECT_SETREF (info
, filename
, mono_string_new (mono_object_domain (assembly
), val
));
4615 if (file_cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
4618 info
->location
= RESOURCE_LOCATION_EMBEDDED
;
4621 case MONO_IMPLEMENTATION_ASSEMBLYREF
:
4622 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
4623 mono_assembly_load_reference (assembly
->assembly
->image
, i
- 1);
4624 if (assembly
->assembly
->image
->references
[i
- 1] == (gpointer
)-1) {
4625 char *msg
= g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i
- 1, assembly
->assembly
->image
->name
);
4626 MonoException
*ex
= mono_get_exception_file_not_found2 (msg
, NULL
);
4628 mono_raise_exception (ex
);
4630 MONO_OBJECT_SETREF (info
, assembly
, mono_assembly_get_object (mono_domain_get (), assembly
->assembly
->image
->references
[i
- 1]));
4632 /* Obtain info recursively */
4633 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info
->assembly
, name
, info
);
4634 info
->location
|= RESOURCE_LOCATION_ANOTHER_ASSEMBLY
;
4637 case MONO_IMPLEMENTATION_EXP_TYPE
:
4638 g_assert_not_reached ();
4647 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoBoolean resource_modules
)
4649 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
4650 MonoArray
*result
= NULL
;
4655 MONO_ARCH_SAVE_REGS
;
4657 /* check hash if needed */
4659 n
= mono_string_to_utf8 (name
);
4660 for (i
= 0; i
< table
->rows
; ++i
) {
4661 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
4662 if (strcmp (val
, n
) == 0) {
4665 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
4666 fn
= mono_string_new (mono_object_domain (assembly
), n
);
4668 return (MonoObject
*)fn
;
4676 for (i
= 0; i
< table
->rows
; ++i
) {
4677 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
))
4681 result
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, count
);
4684 for (i
= 0; i
< table
->rows
; ++i
) {
4685 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
4686 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
4687 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
4688 mono_array_setref (result
, count
, mono_string_new (mono_object_domain (assembly
), n
));
4693 return (MonoObject
*)result
;
4697 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly
*assembly
)
4699 MonoDomain
*domain
= mono_domain_get();
4702 int i
, j
, file_count
= 0;
4703 MonoImage
**modules
;
4704 guint32 module_count
, real_module_count
;
4705 MonoTableInfo
*table
;
4706 guint32 cols
[MONO_FILE_SIZE
];
4707 MonoImage
*image
= assembly
->assembly
->image
;
4709 g_assert (image
!= NULL
);
4710 g_assert (!assembly
->assembly
->dynamic
);
4712 table
= &image
->tables
[MONO_TABLE_FILE
];
4713 file_count
= table
->rows
;
4715 modules
= image
->modules
;
4716 module_count
= image
->module_count
;
4718 real_module_count
= 0;
4719 for (i
= 0; i
< module_count
; ++i
)
4721 real_module_count
++;
4723 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Module");
4724 res
= mono_array_new (domain
, klass
, 1 + real_module_count
+ file_count
);
4726 mono_array_setref (res
, 0, mono_module_get_object (domain
, image
));
4728 for (i
= 0; i
< module_count
; ++i
)
4730 mono_array_setref (res
, j
, mono_module_get_object (domain
, modules
[i
]));
4734 for (i
= 0; i
< file_count
; ++i
, ++j
) {
4735 mono_metadata_decode_row (table
, i
, cols
, MONO_FILE_SIZE
);
4736 if (cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
4737 mono_array_setref (res
, j
, mono_module_file_get_object (domain
, image
, i
));
4739 MonoImage
*m
= mono_image_load_file_for_image (image
, i
+ 1);
4741 MonoString
*fname
= mono_string_new (mono_domain_get (), mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]));
4742 mono_raise_exception (mono_get_exception_file_not_found2 (NULL
, fname
));
4744 mono_array_setref (res
, j
, mono_module_get_object (domain
, m
));
4751 static MonoReflectionMethod
*
4752 ves_icall_GetCurrentMethod (void)
4754 MonoMethod
*m
= mono_method_get_last_managed ();
4756 while (m
->is_inflated
)
4757 m
= ((MonoMethodInflated
*)m
)->declaring
;
4759 return mono_method_get_object (mono_domain_get (), m
, NULL
);
4764 mono_method_get_equivalent_method (MonoMethod
*method
, MonoClass
*klass
)
4767 if (method
->is_inflated
&& ((MonoMethodInflated
*)method
)->context
.method_inst
) {
4768 MonoMethodInflated
*inflated
= (MonoMethodInflated
*)method
;
4769 //method is inflated, we should inflate it on the other class
4770 MonoGenericContext ctx
;
4771 ctx
.method_inst
= inflated
->context
.method_inst
;
4772 ctx
.class_inst
= inflated
->context
.class_inst
;
4773 if (klass
->generic_class
)
4774 ctx
.class_inst
= klass
->generic_class
->context
.class_inst
;
4775 else if (klass
->generic_container
)
4776 ctx
.class_inst
= klass
->generic_container
->context
.class_inst
;
4777 return mono_class_inflate_generic_method_full (inflated
->declaring
, klass
, &ctx
);
4780 mono_class_setup_methods (method
->klass
);
4781 if (method
->klass
->exception_type
)
4783 for (i
= 0; i
< method
->klass
->method
.count
; ++i
) {
4784 if (method
->klass
->methods
[i
] == method
) {
4789 mono_class_setup_methods (klass
);
4790 if (klass
->exception_type
)
4792 g_assert (offset
>= 0 && offset
< klass
->method
.count
);
4793 return klass
->methods
[offset
];
4796 static MonoReflectionMethod
*
4797 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod
*method
, MonoType
*type
)
4801 klass
= mono_class_from_mono_type (type
);
4802 if (mono_class_get_generic_type_definition (method
->klass
) != mono_class_get_generic_type_definition (klass
))
4804 if (method
->klass
!= klass
) {
4805 method
= mono_method_get_equivalent_method (method
, klass
);
4810 klass
= method
->klass
;
4811 return mono_method_get_object (mono_domain_get (), method
, klass
);
4814 static MonoReflectionMethod
*
4815 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod
*method
)
4817 return mono_method_get_object (mono_domain_get (), method
, NULL
);
4820 static MonoReflectionMethodBody
*
4821 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod
*method
)
4823 return mono_method_body_get_object (mono_domain_get (), method
);
4826 static MonoReflectionAssembly
*
4827 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4829 MonoMethod
*dest
= NULL
;
4831 MONO_ARCH_SAVE_REGS
;
4833 mono_stack_walk_no_il (get_executing
, &dest
);
4834 return mono_assembly_get_object (mono_domain_get (), dest
->klass
->image
->assembly
);
4838 static MonoReflectionAssembly
*
4839 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4841 MonoDomain
* domain
= mono_domain_get ();
4843 MONO_ARCH_SAVE_REGS
;
4845 if (!domain
->entry_assembly
)
4848 return mono_assembly_get_object (domain
, domain
->entry_assembly
);
4851 static MonoReflectionAssembly
*
4852 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4857 MONO_ARCH_SAVE_REGS
;
4860 mono_stack_walk_no_il (get_executing
, &dest
);
4862 mono_stack_walk_no_il (get_caller
, &dest
);
4865 return mono_assembly_get_object (mono_domain_get (), dest
->klass
->image
->assembly
);
4869 ves_icall_System_MonoType_getFullName (MonoReflectionType
*object
, gboolean full_name
,
4870 gboolean assembly_qualified
)
4872 MonoDomain
*domain
= mono_object_domain (object
);
4873 MonoTypeNameFormat format
;
4877 MONO_ARCH_SAVE_REGS
;
4879 format
= assembly_qualified
?
4880 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
:
4881 MONO_TYPE_NAME_FORMAT_FULL_NAME
;
4883 format
= MONO_TYPE_NAME_FORMAT_REFLECTION
;
4885 name
= mono_type_get_name_full (object
->type
, format
);
4889 if (full_name
&& (object
->type
->type
== MONO_TYPE_VAR
|| object
->type
->type
== MONO_TYPE_MVAR
)) {
4894 res
= mono_string_new (domain
, name
);
4901 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType
*this)
4903 MonoClass
*klass
= mono_class_from_mono_type (this->type
);
4904 return mono_security_core_clr_class_level (klass
);
4908 fill_reflection_assembly_name (MonoDomain
*domain
, MonoReflectionAssemblyName
*aname
, MonoAssemblyName
*name
, const char *absolute
, gboolean by_default_version
, gboolean default_publickey
, gboolean default_token
)
4910 static MonoMethod
*create_culture
= NULL
;
4913 const char *pkey_ptr
;
4915 MonoBoolean assembly_ref
= 0;
4917 MONO_ARCH_SAVE_REGS
;
4919 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, name
->name
));
4920 aname
->major
= name
->major
;
4921 aname
->minor
= name
->minor
;
4922 aname
->build
= name
->build
;
4923 aname
->flags
= name
->flags
;
4924 aname
->revision
= name
->revision
;
4925 aname
->hashalg
= name
->hash_alg
;
4926 aname
->versioncompat
= 1; /* SameMachine (default) */
4928 if (by_default_version
)
4929 MONO_OBJECT_SETREF (aname
, version
, create_version (domain
, name
->major
, name
->minor
, name
->build
, name
->revision
));
4932 if (absolute
!= NULL
&& *absolute
!= '\0') {
4933 const gchar
*prepend
= "file://";
4936 codebase
= g_strdup (absolute
);
4941 for (i
= strlen (codebase
) - 1; i
>= 0; i
--)
4942 if (codebase
[i
] == '\\')
4945 if (*codebase
== '/' && *(codebase
+ 1) == '/') {
4948 prepend
= "file:///";
4952 result
= g_strconcat (prepend
, codebase
, NULL
);
4958 MONO_OBJECT_SETREF (aname
, codebase
, mono_string_new (domain
, codebase
));
4962 if (!create_culture
) {
4963 MonoMethodDesc
*desc
= mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4964 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4965 g_assert (create_culture
);
4966 mono_method_desc_free (desc
);
4969 if (name
->culture
) {
4970 args
[0] = mono_string_new (domain
, name
->culture
);
4971 args
[1] = &assembly_ref
;
4972 MONO_OBJECT_SETREF (aname
, cultureInfo
, mono_runtime_invoke (create_culture
, NULL
, args
, NULL
));
4975 if (name
->public_key
) {
4976 pkey_ptr
= (char*)name
->public_key
;
4977 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
4979 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4980 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
4981 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
4982 } else if (default_publickey
) {
4983 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
4984 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
4987 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4988 if (name
->public_key_token
[0]) {
4992 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 8));
4993 p
= mono_array_addr (aname
->keyToken
, char, 0);
4995 for (i
= 0, j
= 0; i
< 8; i
++) {
4996 *p
= g_ascii_xdigit_value (name
->public_key_token
[j
++]) << 4;
4997 *p
|= g_ascii_xdigit_value (name
->public_key_token
[j
++]);
5000 } else if (default_token
) {
5001 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
5006 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly
*assembly
)
5008 MonoDomain
*domain
= mono_object_domain (assembly
);
5009 MonoAssembly
*mass
= assembly
->assembly
;
5013 name
= g_strdup_printf (
5014 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5016 mass
->aname
.major
, mass
->aname
.minor
, mass
->aname
.build
, mass
->aname
.revision
,
5017 mass
->aname
.culture
&& *mass
->aname
.culture
? mass
->aname
.culture
: "neutral",
5018 mass
->aname
.public_key_token
[0] ? (char *)mass
->aname
.public_key_token
: "null",
5019 (mass
->aname
.flags
& ASSEMBLYREF_RETARGETABLE_FLAG
) ? ", Retargetable=Yes" : "");
5021 res
= mono_string_new (domain
, name
);
5028 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly
*assembly
, MonoReflectionAssemblyName
*aname
)
5031 MonoAssembly
*mass
= assembly
->assembly
;
5033 MONO_ARCH_SAVE_REGS
;
5035 if (g_path_is_absolute (mass
->image
->name
)) {
5036 fill_reflection_assembly_name (mono_object_domain (assembly
),
5037 aname
, &mass
->aname
, mass
->image
->name
, TRUE
,
5041 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
5043 fill_reflection_assembly_name (mono_object_domain (assembly
),
5044 aname
, &mass
->aname
, absolute
, TRUE
, TRUE
,
5051 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString
*fname
, MonoReflectionAssemblyName
*aname
)
5054 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
5057 MonoAssemblyName name
;
5060 MONO_ARCH_SAVE_REGS
;
5062 filename
= mono_string_to_utf8 (fname
);
5064 dirname
= g_path_get_dirname (filename
);
5065 replace_shadow_path (mono_domain_get (), dirname
, &filename
);
5068 image
= mono_image_open (filename
, &status
);
5074 if (status
== MONO_IMAGE_IMAGE_INVALID
)
5075 exc
= mono_get_exception_bad_image_format2 (NULL
, fname
);
5077 exc
= mono_get_exception_file_not_found2 (NULL
, fname
);
5078 mono_raise_exception (exc
);
5081 res
= mono_assembly_fill_assembly_name (image
, &name
);
5083 mono_image_close (image
);
5085 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5088 fill_reflection_assembly_name (mono_domain_get (), aname
, &name
, filename
,
5092 mono_image_close (image
);
5096 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly
*assembly
,
5097 char **minimum
, guint32
*minLength
, char **optional
, guint32
*optLength
, char **refused
, guint32
*refLength
)
5099 MonoBoolean result
= FALSE
;
5100 MonoDeclSecurityEntry entry
;
5102 /* SecurityAction.RequestMinimum */
5103 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQMIN
, &entry
)) {
5104 *minimum
= entry
.blob
;
5105 *minLength
= entry
.size
;
5108 /* SecurityAction.RequestOptional */
5109 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQOPT
, &entry
)) {
5110 *optional
= entry
.blob
;
5111 *optLength
= entry
.size
;
5114 /* SecurityAction.RequestRefuse */
5115 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQREFUSE
, &entry
)) {
5116 *refused
= entry
.blob
;
5117 *refLength
= entry
.size
;
5125 mono_module_get_types (MonoDomain
*domain
, MonoImage
*image
, MonoArray
**exceptions
, MonoBoolean exportedOnly
)
5129 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_TYPEDEF
];
5131 guint32 attrs
, visibility
;
5133 /* we start the count from 1 because we skip the special type <Module> */
5136 for (i
= 1; i
< tdef
->rows
; ++i
) {
5137 attrs
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEDEF_FLAGS
);
5138 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5139 if (visibility
== TYPE_ATTRIBUTE_PUBLIC
|| visibility
== TYPE_ATTRIBUTE_NESTED_PUBLIC
)
5143 count
= tdef
->rows
- 1;
5145 res
= mono_array_new (domain
, mono_defaults
.monotype_class
, count
);
5146 *exceptions
= mono_array_new (domain
, mono_defaults
.exception_class
, count
);
5148 for (i
= 1; i
< tdef
->rows
; ++i
) {
5149 attrs
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEDEF_FLAGS
);
5150 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5151 if (!exportedOnly
|| (visibility
== TYPE_ATTRIBUTE_PUBLIC
|| visibility
== TYPE_ATTRIBUTE_NESTED_PUBLIC
)) {
5152 klass
= mono_class_get (image
, (i
+ 1) | MONO_TOKEN_TYPE_DEF
);
5154 mono_array_setref (res
, count
, mono_type_get_object (domain
, &klass
->byval_arg
));
5156 MonoLoaderError
*error
;
5159 error
= mono_loader_get_last_error ();
5160 g_assert (error
!= NULL
);
5162 ex
= mono_loader_error_prepare_exception (error
);
5163 mono_array_setref (*exceptions
, count
, ex
);
5165 if (mono_loader_get_last_error ())
5166 mono_loader_clear_error ();
5175 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly
*assembly
, MonoBoolean exportedOnly
)
5177 MonoArray
*res
= NULL
;
5178 MonoArray
*exceptions
= NULL
;
5179 MonoImage
*image
= NULL
;
5180 MonoTableInfo
*table
= NULL
;
5183 int i
, len
, ex_count
;
5185 MONO_ARCH_SAVE_REGS
;
5187 domain
= mono_object_domain (assembly
);
5189 g_assert (!assembly
->assembly
->dynamic
);
5190 image
= assembly
->assembly
->image
;
5191 table
= &image
->tables
[MONO_TABLE_FILE
];
5192 res
= mono_module_get_types (domain
, image
, &exceptions
, exportedOnly
);
5194 /* Append data from all modules in the assembly */
5195 for (i
= 0; i
< table
->rows
; ++i
) {
5196 if (!(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
5197 MonoImage
*loaded_image
= mono_assembly_load_module (image
->assembly
, i
+ 1);
5200 MonoArray
*res2
= mono_module_get_types (domain
, loaded_image
, &ex2
, exportedOnly
);
5201 /* Append the new types to the end of the array */
5202 if (mono_array_length (res2
) > 0) {
5204 MonoArray
*res3
, *ex3
;
5206 len1
= mono_array_length (res
);
5207 len2
= mono_array_length (res2
);
5209 res3
= mono_array_new (domain
, mono_defaults
.monotype_class
, len1
+ len2
);
5210 mono_array_memcpy_refs (res3
, 0, res
, 0, len1
);
5211 mono_array_memcpy_refs (res3
, len1
, res2
, 0, len2
);
5214 ex3
= mono_array_new (domain
, mono_defaults
.monotype_class
, len1
+ len2
);
5215 mono_array_memcpy_refs (ex3
, 0, exceptions
, 0, len1
);
5216 mono_array_memcpy_refs (ex3
, len1
, ex2
, 0, len2
);
5223 /* the ReflectionTypeLoadException must have all the types (Types property),
5224 * NULL replacing types which throws an exception. The LoaderException must
5225 * contain all exceptions for NULL items.
5228 len
= mono_array_length (res
);
5231 for (i
= 0; i
< len
; i
++) {
5232 MonoReflectionType
*t
= mono_array_get (res
, gpointer
, i
);
5236 klass
= mono_type_get_class (t
->type
);
5237 if ((klass
!= NULL
) && klass
->exception_type
) {
5238 /* keep the class in the list */
5239 list
= g_list_append (list
, klass
);
5240 /* and replace Type with NULL */
5241 mono_array_setref (res
, i
, NULL
);
5248 if (list
|| ex_count
) {
5250 MonoException
*exc
= NULL
;
5251 MonoArray
*exl
= NULL
;
5252 int j
, length
= g_list_length (list
) + ex_count
;
5254 mono_loader_clear_error ();
5256 exl
= mono_array_new (domain
, mono_defaults
.exception_class
, length
);
5257 /* Types for which mono_class_get () succeeded */
5258 for (i
= 0, tmp
= list
; tmp
; i
++, tmp
= tmp
->next
) {
5259 MonoException
*exc
= mono_class_get_exception_for_failure (tmp
->data
);
5260 mono_array_setref (exl
, i
, exc
);
5262 /* Types for which it don't */
5263 for (j
= 0; j
< mono_array_length (exceptions
); ++j
) {
5264 MonoException
*exc
= mono_array_get (exceptions
, MonoException
*, j
);
5266 g_assert (i
< length
);
5267 mono_array_setref (exl
, i
, exc
);
5274 exc
= mono_get_exception_reflection_type_load (res
, exl
);
5275 mono_loader_clear_error ();
5276 mono_raise_exception (exc
);
5283 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName
*name
, MonoString
*assname
)
5285 MonoAssemblyName aname
;
5286 MonoDomain
*domain
= mono_object_domain (name
);
5288 gboolean is_version_defined
;
5289 gboolean is_token_defined
;
5291 aname
.public_key
= NULL
;
5292 val
= mono_string_to_utf8 (assname
);
5293 if (!mono_assembly_name_parse_full (val
, &aname
, TRUE
, &is_version_defined
, &is_token_defined
)) {
5294 g_free ((guint8
*) aname
.public_key
);
5299 fill_reflection_assembly_name (domain
, name
, &aname
, "", is_version_defined
,
5300 FALSE
, is_token_defined
);
5302 mono_assembly_name_free (&aname
);
5303 g_free ((guint8
*) aname
.public_key
);
5309 static MonoReflectionType
*
5310 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule
*module
)
5312 MonoDomain
*domain
= mono_object_domain (module
);
5315 MONO_ARCH_SAVE_REGS
;
5317 g_assert (module
->image
);
5319 if (module
->image
->dynamic
&& ((MonoDynamicImage
*)(module
->image
))->initial_image
)
5320 /* These images do not have a global type */
5323 klass
= mono_class_get (module
->image
, 1 | MONO_TOKEN_TYPE_DEF
);
5324 return mono_type_get_object (domain
, &klass
->byval_arg
);
5328 ves_icall_System_Reflection_Module_Close (MonoReflectionModule
*module
)
5330 /*if (module->image)
5331 mono_image_close (module->image);*/
5335 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule
*module
)
5337 MonoDomain
*domain
= mono_object_domain (module
);
5339 MONO_ARCH_SAVE_REGS
;
5341 g_assert (module
->image
);
5342 return mono_string_new (domain
, module
->image
->guid
);
5346 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule
*module
)
5349 if (module
->image
&& module
->image
->is_module_handle
)
5350 return module
->image
->raw_data
;
5353 return (gpointer
) (-1);
5357 ves_icall_System_Reflection_Module_GetPEKind (MonoImage
*image
, gint32
*pe_kind
, gint32
*machine
)
5359 if (image
->dynamic
) {
5360 MonoDynamicImage
*dyn
= (MonoDynamicImage
*)image
;
5361 *pe_kind
= dyn
->pe_kind
;
5362 *machine
= dyn
->machine
;
5365 *pe_kind
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_cli_header
.ch_flags
& 0x3;
5366 *machine
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_header
.coff
.coff_machine
;
5371 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage
*image
)
5373 return (image
->md_version_major
<< 16) | (image
->md_version_minor
);
5377 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule
*module
)
5379 MonoArray
*exceptions
;
5382 MONO_ARCH_SAVE_REGS
;
5385 return mono_array_new (mono_object_domain (module
), mono_defaults
.monotype_class
, 0);
5387 MonoArray
*res
= mono_module_get_types (mono_object_domain (module
), module
->image
, &exceptions
, FALSE
);
5388 for (i
= 0; i
< mono_array_length (exceptions
); ++i
) {
5389 MonoException
*ex
= mono_array_get (exceptions
, MonoException
*, i
);
5391 mono_raise_exception (ex
);
5398 mono_metadata_memberref_is_method (MonoImage
*image
, guint32 token
)
5400 guint32 cols
[MONO_MEMBERREF_SIZE
];
5402 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
5403 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
5404 mono_metadata_decode_blob_size (sig
, &sig
);
5405 return (*sig
!= 0x6);
5409 init_generic_context_from_args (MonoGenericContext
*context
, MonoArray
*type_args
, MonoArray
*method_args
)
5412 context
->class_inst
= mono_metadata_get_generic_inst (mono_array_length (type_args
),
5413 mono_array_addr (type_args
, MonoType
*, 0));
5415 context
->class_inst
= NULL
;
5417 context
->method_inst
= mono_metadata_get_generic_inst (mono_array_length (method_args
),
5418 mono_array_addr (method_args
, MonoType
*, 0));
5420 context
->method_inst
= NULL
;
5424 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5427 int table
= mono_metadata_token_table (token
);
5428 int index
= mono_metadata_token_index (token
);
5429 MonoGenericContext context
;
5431 *error
= ResolveTokenError_Other
;
5433 /* Validate token */
5434 if ((table
!= MONO_TABLE_TYPEDEF
) && (table
!= MONO_TABLE_TYPEREF
) &&
5435 (table
!= MONO_TABLE_TYPESPEC
)) {
5436 *error
= ResolveTokenError_BadTable
;
5440 if (image
->dynamic
) {
5441 if (type_args
|| method_args
)
5442 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5443 klass
= mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5446 return &klass
->byval_arg
;
5449 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5450 *error
= ResolveTokenError_OutOfRange
;
5454 init_generic_context_from_args (&context
, type_args
, method_args
);
5455 klass
= mono_class_get_full (image
, token
, &context
);
5457 if (mono_loader_get_last_error ())
5458 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5461 return &klass
->byval_arg
;
5467 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5469 int table
= mono_metadata_token_table (token
);
5470 int index
= mono_metadata_token_index (token
);
5471 MonoGenericContext context
;
5474 *error
= ResolveTokenError_Other
;
5476 /* Validate token */
5477 if ((table
!= MONO_TABLE_METHOD
) && (table
!= MONO_TABLE_METHODSPEC
) &&
5478 (table
!= MONO_TABLE_MEMBERREF
)) {
5479 *error
= ResolveTokenError_BadTable
;
5483 if (image
->dynamic
) {
5484 if (type_args
|| method_args
)
5485 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5486 /* FIXME: validate memberref token type */
5487 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5490 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5491 *error
= ResolveTokenError_OutOfRange
;
5494 if ((table
== MONO_TABLE_MEMBERREF
) && (!mono_metadata_memberref_is_method (image
, token
))) {
5495 *error
= ResolveTokenError_BadTable
;
5499 init_generic_context_from_args (&context
, type_args
, method_args
);
5500 method
= mono_get_method_full (image
, token
, NULL
, &context
);
5502 if (mono_loader_get_last_error ())
5503 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5509 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*error
)
5511 int index
= mono_metadata_token_index (token
);
5513 *error
= ResolveTokenError_Other
;
5515 /* Validate token */
5516 if (mono_metadata_token_code (token
) != MONO_TOKEN_STRING
) {
5517 *error
= ResolveTokenError_BadTable
;
5522 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5524 if ((index
<= 0) || (index
>= image
->heap_us
.size
)) {
5525 *error
= ResolveTokenError_OutOfRange
;
5529 /* FIXME: What to do if the index points into the middle of a string ? */
5531 return mono_ldstr (mono_domain_get (), image
, index
);
5534 static MonoClassField
*
5535 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5538 int table
= mono_metadata_token_table (token
);
5539 int index
= mono_metadata_token_index (token
);
5540 MonoGenericContext context
;
5541 MonoClassField
*field
;
5543 *error
= ResolveTokenError_Other
;
5545 /* Validate token */
5546 if ((table
!= MONO_TABLE_FIELD
) && (table
!= MONO_TABLE_MEMBERREF
)) {
5547 *error
= ResolveTokenError_BadTable
;
5551 if (image
->dynamic
) {
5552 if (type_args
|| method_args
)
5553 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5554 /* FIXME: validate memberref token type */
5555 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5558 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5559 *error
= ResolveTokenError_OutOfRange
;
5562 if ((table
== MONO_TABLE_MEMBERREF
) && (mono_metadata_memberref_is_method (image
, token
))) {
5563 *error
= ResolveTokenError_BadTable
;
5567 init_generic_context_from_args (&context
, type_args
, method_args
);
5568 field
= mono_field_from_token (image
, token
, &klass
, &context
);
5570 if (mono_loader_get_last_error ())
5571 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5578 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5580 int table
= mono_metadata_token_table (token
);
5582 *error
= ResolveTokenError_Other
;
5585 case MONO_TABLE_TYPEDEF
:
5586 case MONO_TABLE_TYPEREF
:
5587 case MONO_TABLE_TYPESPEC
: {
5588 MonoType
*t
= ves_icall_System_Reflection_Module_ResolveTypeToken (image
, token
, type_args
, method_args
, error
);
5590 return (MonoObject
*)mono_type_get_object (mono_domain_get (), t
);
5594 case MONO_TABLE_METHOD
:
5595 case MONO_TABLE_METHODSPEC
: {
5596 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
5598 return (MonoObject
*)mono_method_get_object (mono_domain_get (), m
, m
->klass
);
5602 case MONO_TABLE_FIELD
: {
5603 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
5605 return (MonoObject
*)mono_field_get_object (mono_domain_get (), f
->parent
, f
);
5609 case MONO_TABLE_MEMBERREF
:
5610 if (mono_metadata_memberref_is_method (image
, token
)) {
5611 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
5613 return (MonoObject
*)mono_method_get_object (mono_domain_get (), m
, m
->klass
);
5618 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
5620 return (MonoObject
*)mono_field_get_object (mono_domain_get (), f
->parent
, f
);
5627 *error
= ResolveTokenError_BadTable
;
5634 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*error
)
5636 int table
= mono_metadata_token_table (token
);
5637 int idx
= mono_metadata_token_index (token
);
5638 MonoTableInfo
*tables
= image
->tables
;
5643 *error
= ResolveTokenError_OutOfRange
;
5645 /* FIXME: Support other tables ? */
5646 if (table
!= MONO_TABLE_STANDALONESIG
)
5652 if ((idx
== 0) || (idx
> tables
[MONO_TABLE_STANDALONESIG
].rows
))
5655 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
5657 ptr
= mono_metadata_blob_heap (image
, sig
);
5658 len
= mono_metadata_decode_blob_size (ptr
, &ptr
);
5660 res
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, len
);
5661 memcpy (mono_array_addr (res
, guint8
, 0), ptr
, len
);
5665 static MonoReflectionType
*
5666 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder
*tb
, MonoString
*smodifiers
)
5669 int isbyref
= 0, rank
;
5670 char *str
= mono_string_to_utf8 (smodifiers
);
5673 MONO_ARCH_SAVE_REGS
;
5675 klass
= mono_class_from_mono_type (tb
->type
.type
);
5677 /* logic taken from mono_reflection_parse_type(): keep in sync */
5681 if (isbyref
) { /* only one level allowed by the spec */
5688 return mono_type_get_object (mono_object_domain (tb
), &klass
->this_arg
);
5691 klass
= mono_ptr_class_get (&klass
->byval_arg
);
5692 mono_class_init (klass
);
5703 else if (*p
!= '*') { /* '*' means unknown lower bound */
5714 klass
= mono_array_class_get (klass
, rank
);
5715 mono_class_init (klass
);
5722 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
5726 ves_icall_Type_IsArrayImpl (MonoReflectionType
*t
)
5731 MONO_ARCH_SAVE_REGS
;
5734 res
= !type
->byref
&& (type
->type
== MONO_TYPE_ARRAY
|| type
->type
== MONO_TYPE_SZARRAY
);
5739 static MonoReflectionType
*
5740 ves_icall_Type_make_array_type (MonoReflectionType
*type
, int rank
)
5742 MonoClass
*klass
, *aklass
;
5744 MONO_ARCH_SAVE_REGS
;
5746 klass
= mono_class_from_mono_type (type
->type
);
5747 if (rank
== 0) //single dimentional array
5748 aklass
= mono_array_class_get (klass
, 1);
5750 aklass
= mono_bounded_array_class_get (klass
, rank
, TRUE
);
5752 return mono_type_get_object (mono_object_domain (type
), &aklass
->byval_arg
);
5755 static MonoReflectionType
*
5756 ves_icall_Type_make_byref_type (MonoReflectionType
*type
)
5760 MONO_ARCH_SAVE_REGS
;
5762 klass
= mono_class_from_mono_type (type
->type
);
5764 return mono_type_get_object (mono_object_domain (type
), &klass
->this_arg
);
5767 static MonoReflectionType
*
5768 ves_icall_Type_MakePointerType (MonoReflectionType
*type
)
5772 MONO_ARCH_SAVE_REGS
;
5774 pklass
= mono_ptr_class_get (type
->type
);
5776 return mono_type_get_object (mono_object_domain (type
), &pklass
->byval_arg
);
5780 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType
*type
, MonoObject
*target
,
5781 MonoReflectionMethod
*info
, MonoBoolean throwOnBindFailure
)
5783 MonoClass
*delegate_class
= mono_class_from_mono_type (type
->type
);
5784 MonoObject
*delegate
;
5786 MonoMethod
*method
= info
->method
;
5788 MONO_ARCH_SAVE_REGS
;
5790 mono_assert (delegate_class
->parent
== mono_defaults
.multicastdelegate_class
);
5792 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
) {
5793 if (!mono_security_core_clr_ensure_delegate_creation (method
, throwOnBindFailure
))
5797 delegate
= mono_object_new (mono_object_domain (type
), delegate_class
);
5799 if (method
->dynamic
) {
5800 /* Creating a trampoline would leak memory */
5801 func
= mono_compile_method (method
);
5803 func
= mono_create_ftnptr (mono_domain_get (),
5804 mono_runtime_create_jump_trampoline (mono_domain_get (), method
, TRUE
));
5807 mono_delegate_ctor_with_method (delegate
, target
, func
, method
);
5813 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate
*this)
5815 /* Reset the invoke impl to the default one */
5816 this->invoke_impl
= mono_runtime_create_delegate_trampoline (this->object
.vtable
->klass
);
5820 * Magic number to convert a time which is relative to
5821 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5823 #define EPOCH_ADJUST ((guint64)62135596800LL)
5826 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5828 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5831 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5833 convert_to_absolute_date(SYSTEMTIME
*date
)
5835 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5836 static int days_in_month
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5837 static int leap_days_in_month
[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5838 /* from the calendar FAQ */
5839 int a
= (14 - date
->wMonth
) / 12;
5840 int y
= date
->wYear
- a
;
5841 int m
= date
->wMonth
+ 12 * a
- 2;
5842 int d
= (1 + y
+ y
/4 - y
/100 + y
/400 + (31*m
)/12) % 7;
5844 /* d is now the day of the week for the first of the month (0 == Sunday) */
5846 int day_of_week
= date
->wDayOfWeek
;
5848 /* set day_in_month to the first day in the month which falls on day_of_week */
5849 int day_in_month
= 1 + (day_of_week
- d
);
5850 if (day_in_month
<= 0)
5853 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5854 date
->wDay
= day_in_month
+ (date
->wDay
- 1) * 7;
5855 if (date
->wDay
> (IS_LEAP(date
->wYear
) ? leap_days_in_month
[date
->wMonth
- 1] : days_in_month
[date
->wMonth
- 1]))
5862 * Return's the offset from GMT of a local time.
5864 * tm is a local time
5865 * t is the same local time as seconds.
5868 gmt_offset(struct tm
*tm
, time_t t
)
5870 #if defined (HAVE_TM_GMTOFF)
5871 return tm
->tm_gmtoff
;
5876 g
.tm_isdst
= tm
->tm_isdst
;
5878 return (int)difftime(t
, t2
);
5883 * This is heavily based on zdump.c from glibc 2.2.
5885 * * data[0]: start of daylight saving time (in DateTime ticks).
5886 * * data[1]: end of daylight saving time (in DateTime ticks).
5887 * * data[2]: utcoffset (in TimeSpan ticks).
5888 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5889 * * name[0]: name of this timezone when not daylight saving.
5890 * * name[1]: name of this timezone when daylight saving.
5892 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5893 * the class library allows years between 1 and 9999.
5895 * Returns true on success and zero on failure.
5898 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year
, MonoArray
**data
, MonoArray
**names
)
5901 MonoDomain
*domain
= mono_domain_get ();
5902 struct tm start
, tt
;
5906 int is_daylight
= 0, day
;
5909 MONO_ARCH_SAVE_REGS
;
5911 MONO_CHECK_ARG_NULL (data
);
5912 MONO_CHECK_ARG_NULL (names
);
5914 mono_gc_wbarrier_generic_store (data
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.int64_class
, 4));
5915 mono_gc_wbarrier_generic_store (names
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.string_class
, 2));
5918 * no info is better than crashing: we'll need our own tz data
5919 * to make this work properly, anyway. The range is probably
5920 * reduced to 1970 .. 2037 because that is what mktime is
5921 * guaranteed to support (we get into an infinite loop
5925 memset (&start
, 0, sizeof (start
));
5928 start
.tm_year
= year
-1900;
5930 t
= mktime (&start
);
5932 if ((year
< 1970) || (year
> 2037) || (t
== -1)) {
5934 tt
= *localtime (&t
);
5935 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5936 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5937 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5941 gmtoff
= gmt_offset (&start
, t
);
5943 /* For each day of the year, calculate the tm_gmtoff. */
5944 for (day
= 0; day
< 365; day
++) {
5947 tt
= *localtime (&t
);
5949 /* Daylight saving starts or ends here. */
5950 if (gmt_offset (&tt
, t
) != gmtoff
) {
5954 /* Try to find the exact hour when daylight saving starts/ends. */
5958 tt1
= *localtime (&t1
);
5959 } while (gmt_offset (&tt1
, t1
) != gmtoff
);
5961 /* Try to find the exact minute when daylight saving starts/ends. */
5964 tt1
= *localtime (&t1
);
5965 } while (gmt_offset (&tt1
, t1
) == gmtoff
);
5967 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5969 /* Write data, if we're already in daylight saving, we're done. */
5971 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5972 mono_array_set ((*data
), gint64
, 1, ((gint64
)t1
+ EPOCH_ADJUST
) * 10000000L);
5975 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5976 mono_array_set ((*data
), gint64
, 0, ((gint64
)t1
+ EPOCH_ADJUST
) * 10000000L);
5980 /* This is only set once when we enter daylight saving. */
5981 mono_array_set ((*data
), gint64
, 2, (gint64
)gmtoff
* 10000000L);
5982 mono_array_set ((*data
), gint64
, 3, (gint64
)(gmt_offset (&tt
, t
) - gmtoff
) * 10000000L);
5984 gmtoff
= gmt_offset (&tt
, t
);
5989 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5990 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5991 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5992 mono_array_set ((*data
), gint64
, 0, 0);
5993 mono_array_set ((*data
), gint64
, 1, 0);
5994 mono_array_set ((*data
), gint64
, 2, (gint64
) gmtoff
* 10000000L);
5995 mono_array_set ((*data
), gint64
, 3, 0);
6000 MonoDomain
*domain
= mono_domain_get ();
6001 TIME_ZONE_INFORMATION tz_info
;
6006 tz_id
= GetTimeZoneInformation (&tz_info
);
6007 if (tz_id
== TIME_ZONE_ID_INVALID
)
6010 MONO_CHECK_ARG_NULL (data
);
6011 MONO_CHECK_ARG_NULL (names
);
6013 mono_gc_wbarrier_generic_store (data
, mono_array_new (domain
, mono_defaults
.int64_class
, 4));
6014 mono_gc_wbarrier_generic_store (names
, mono_array_new (domain
, mono_defaults
.string_class
, 2));
6016 for (i
= 0; i
< 32; ++i
)
6017 if (!tz_info
.DaylightName
[i
])
6019 mono_array_setref ((*names
), 1, mono_string_new_utf16 (domain
, tz_info
.DaylightName
, i
));
6020 for (i
= 0; i
< 32; ++i
)
6021 if (!tz_info
.StandardName
[i
])
6023 mono_array_setref ((*names
), 0, mono_string_new_utf16 (domain
, tz_info
.StandardName
, i
));
6025 if ((year
<= 1601) || (year
> 30827)) {
6027 * According to MSDN, the MS time functions can't handle dates outside
6033 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6034 if (tz_id
!= TIME_ZONE_ID_UNKNOWN
) {
6035 tz_info
.StandardDate
.wYear
= year
;
6036 convert_to_absolute_date(&tz_info
.StandardDate
);
6037 err
= SystemTimeToFileTime (&tz_info
.StandardDate
, &ft
);
6042 mono_array_set ((*data
), gint64
, 1, FILETIME_ADJUST
+ (((guint64
)ft
.dwHighDateTime
<<32) | ft
.dwLowDateTime
));
6043 tz_info
.DaylightDate
.wYear
= year
;
6044 convert_to_absolute_date(&tz_info
.DaylightDate
);
6045 err
= SystemTimeToFileTime (&tz_info
.DaylightDate
, &ft
);
6050 mono_array_set ((*data
), gint64
, 0, FILETIME_ADJUST
+ (((guint64
)ft
.dwHighDateTime
<<32) | ft
.dwLowDateTime
));
6052 mono_array_set ((*data
), gint64
, 2, (tz_info
.Bias
+ tz_info
.StandardBias
) * -600000000LL);
6053 mono_array_set ((*data
), gint64
, 3, (tz_info
.DaylightBias
- tz_info
.StandardBias
) * -600000000LL);
6060 ves_icall_System_Object_obj_address (MonoObject
*this)
6062 MONO_ARCH_SAVE_REGS
;
6069 static inline gint32
6070 mono_array_get_byte_length (MonoArray
*array
)
6076 klass
= array
->obj
.vtable
->klass
;
6078 if (array
->bounds
== NULL
)
6079 length
= array
->max_length
;
6082 for (i
= 0; i
< klass
->rank
; ++ i
)
6083 length
*= array
->bounds
[i
].length
;
6086 switch (klass
->element_class
->byval_arg
.type
) {
6089 case MONO_TYPE_BOOLEAN
:
6093 case MONO_TYPE_CHAR
:
6101 return length
* sizeof (gpointer
);
6112 ves_icall_System_Buffer_ByteLengthInternal (MonoArray
*array
)
6114 MONO_ARCH_SAVE_REGS
;
6116 return mono_array_get_byte_length (array
);
6120 ves_icall_System_Buffer_GetByteInternal (MonoArray
*array
, gint32 idx
)
6122 MONO_ARCH_SAVE_REGS
;
6124 return mono_array_get (array
, gint8
, idx
);
6128 ves_icall_System_Buffer_SetByteInternal (MonoArray
*array
, gint32 idx
, gint8 value
)
6130 MONO_ARCH_SAVE_REGS
;
6132 mono_array_set (array
, gint8
, idx
, value
);
6136 ves_icall_System_Buffer_BlockCopyInternal (MonoArray
*src
, gint32 src_offset
, MonoArray
*dest
, gint32 dest_offset
, gint32 count
)
6138 guint8
*src_buf
, *dest_buf
;
6140 MONO_ARCH_SAVE_REGS
;
6142 /* watch out for integer overflow */
6143 if ((src_offset
> mono_array_get_byte_length (src
) - count
) || (dest_offset
> mono_array_get_byte_length (dest
) - count
))
6146 src_buf
= (guint8
*)src
->vector
+ src_offset
;
6147 dest_buf
= (guint8
*)dest
->vector
+ dest_offset
;
6150 memcpy (dest_buf
, src_buf
, count
);
6152 memmove (dest_buf
, src_buf
, count
); /* Source and dest are the same array */
6158 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject
*this, MonoString
*class_name
)
6160 MonoDomain
*domain
= mono_object_domain (this);
6162 MonoRealProxy
*rp
= ((MonoRealProxy
*)this);
6163 MonoTransparentProxy
*tp
;
6167 MONO_ARCH_SAVE_REGS
;
6169 res
= mono_object_new (domain
, mono_defaults
.transparent_proxy_class
);
6170 tp
= (MonoTransparentProxy
*) res
;
6172 MONO_OBJECT_SETREF (tp
, rp
, rp
);
6173 type
= ((MonoReflectionType
*)rp
->class_to_proxy
)->type
;
6174 klass
= mono_class_from_mono_type (type
);
6176 tp
->custom_type_info
= (mono_object_isinst (this, mono_defaults
.iremotingtypeinfo_class
) != NULL
);
6177 tp
->remote_class
= mono_remote_class (domain
, class_name
, klass
);
6179 res
->vtable
= mono_remote_class_vtable (domain
, tp
->remote_class
, rp
);
6183 static MonoReflectionType
*
6184 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy
*tp
)
6186 return mono_type_get_object (mono_object_domain (tp
), &tp
->remote_class
->proxy_class
->byval_arg
);
6189 /* System.Environment */
6192 ves_icall_System_Environment_get_UserName (void)
6194 MONO_ARCH_SAVE_REGS
;
6196 /* using glib is more portable */
6197 return mono_string_new (mono_domain_get (), g_get_user_name ());
6202 ves_icall_System_Environment_get_MachineName (void)
6204 #if defined (HOST_WIN32)
6209 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
6210 buf
= g_new (gunichar2
, len
);
6213 if (GetComputerName (buf
, (PDWORD
) &len
))
6214 result
= mono_string_new_utf16 (mono_domain_get (), buf
, len
);
6218 #elif !defined(DISABLE_SOCKETS)
6222 if (gethostname (buf
, sizeof (buf
)) == 0)
6223 result
= mono_string_new (mono_domain_get (), buf
);
6229 return mono_string_new (mono_domain_get (), "mono");
6234 ves_icall_System_Environment_get_Platform (void)
6236 #if defined (TARGET_WIN32)
6239 #elif defined(__MACH__)
6242 // For compatibility with our client code, this will be 4 for a while.
6243 // We will eventually move to 6 to match .NET, but it requires all client
6244 // code to be updated and the documentation everywhere to be updated
6255 ves_icall_System_Environment_get_NewLine (void)
6257 MONO_ARCH_SAVE_REGS
;
6259 #if defined (HOST_WIN32)
6260 return mono_string_new (mono_domain_get (), "\r\n");
6262 return mono_string_new (mono_domain_get (), "\n");
6267 ves_icall_System_Environment_GetEnvironmentVariable (MonoString
*name
)
6272 MONO_ARCH_SAVE_REGS
;
6277 utf8_name
= mono_string_to_utf8 (name
); /* FIXME: this should be ascii */
6278 value
= g_getenv (utf8_name
);
6285 return mono_string_new (mono_domain_get (), value
);
6289 * There is no standard way to get at environ.
6292 #ifndef __MINGW32_VERSION
6294 /* Apple defines this in crt_externs.h but doesn't provide that header for
6295 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6296 * in fact exist on all implementations (so far)
6298 gchar
***_NSGetEnviron(void);
6299 #define environ (*_NSGetEnviron())
6308 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6319 env_strings
= GetEnvironmentStrings();
6322 env_string
= env_strings
;
6323 while (*env_string
!= '\0') {
6324 /* weird case that MS seems to skip */
6325 if (*env_string
!= '=')
6327 while (*env_string
!= '\0')
6333 domain
= mono_domain_get ();
6334 names
= mono_array_new (domain
, mono_defaults
.string_class
, n
);
6338 env_string
= env_strings
;
6339 while (*env_string
!= '\0') {
6340 /* weird case that MS seems to skip */
6341 if (*env_string
!= '=') {
6342 equal_str
= wcschr(env_string
, '=');
6343 g_assert(equal_str
);
6344 str
= mono_string_new_utf16 (domain
, env_string
, equal_str
-env_string
);
6345 mono_array_setref (names
, n
, str
);
6348 while (*env_string
!= '\0')
6353 FreeEnvironmentStrings (env_strings
);
6365 MONO_ARCH_SAVE_REGS
;
6368 for (e
= environ
; *e
!= 0; ++ e
)
6371 domain
= mono_domain_get ();
6372 names
= mono_array_new (domain
, mono_defaults
.string_class
, n
);
6375 for (e
= environ
; *e
!= 0; ++ e
) {
6376 parts
= g_strsplit (*e
, "=", 2);
6378 str
= mono_string_new (domain
, *parts
);
6379 mono_array_setref (names
, n
, str
);
6392 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6394 #if !GLIB_CHECK_VERSION(2,4,0)
6395 #define g_setenv(a,b,c) setenv(a,b,c)
6396 #define g_unsetenv(a) unsetenv(a)
6400 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString
*name
, MonoString
*value
)
6405 gunichar2
*utf16_name
, *utf16_value
;
6407 gchar
*utf8_name
, *utf8_value
;
6410 MONO_ARCH_SAVE_REGS
;
6413 utf16_name
= mono_string_to_utf16 (name
);
6414 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
6415 SetEnvironmentVariable (utf16_name
, NULL
);
6416 g_free (utf16_name
);
6420 utf16_value
= mono_string_to_utf16 (value
);
6422 SetEnvironmentVariable (utf16_name
, utf16_value
);
6424 g_free (utf16_name
);
6425 g_free (utf16_value
);
6427 utf8_name
= mono_string_to_utf8 (name
); /* FIXME: this should be ascii */
6429 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
6430 g_unsetenv (utf8_name
);
6435 utf8_value
= mono_string_to_utf8_checked (value
, &error
);
6436 if (!mono_error_ok (&error
)) {
6438 mono_error_raise_exception (&error
);
6440 g_setenv (utf8_name
, utf8_value
, TRUE
);
6443 g_free (utf8_value
);
6448 ves_icall_System_Environment_Exit (int result
)
6450 MONO_ARCH_SAVE_REGS
;
6452 mono_threads_set_shutting_down ();
6454 mono_runtime_set_shutting_down ();
6456 /* Suspend all managed threads since the runtime is going away */
6457 mono_thread_suspend_all_other_threads ();
6459 mono_runtime_quit ();
6461 /* we may need to do some cleanup here... */
6466 ves_icall_System_Environment_GetGacPath (void)
6468 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6472 ves_icall_System_Environment_GetWindowsFolderPath (int folder
)
6474 #if defined (HOST_WIN32)
6475 #ifndef CSIDL_FLAG_CREATE
6476 #define CSIDL_FLAG_CREATE 0x8000
6479 WCHAR path
[MAX_PATH
];
6480 /* Create directory if no existing */
6481 if (SUCCEEDED (SHGetFolderPathW (NULL
, folder
| CSIDL_FLAG_CREATE
, NULL
, 0, path
))) {
6485 return mono_string_new_utf16 (mono_domain_get (), path
, len
);
6488 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6490 return mono_string_new (mono_domain_get (), "");
6494 ves_icall_System_Environment_GetLogicalDrives (void)
6496 gunichar2 buf
[128], *ptr
, *dname
;
6498 guint initial_size
= 127, size
= 128;
6501 MonoString
*drivestr
;
6502 MonoDomain
*domain
= mono_domain_get ();
6505 MONO_ARCH_SAVE_REGS
;
6510 while (size
> initial_size
) {
6511 size
= (guint
) GetLogicalDriveStrings (initial_size
, ptr
);
6512 if (size
> initial_size
) {
6515 ptr
= g_malloc0 ((size
+ 1) * sizeof (gunichar2
));
6516 initial_size
= size
;
6530 result
= mono_array_new (domain
, mono_defaults
.string_class
, ndrives
);
6535 while (*u16
) { u16
++; len
++; }
6536 drivestr
= mono_string_new_utf16 (domain
, dname
, len
);
6537 mono_array_setref (result
, ndrives
++, drivestr
);
6548 ves_icall_System_Environment_InternalGetHome (void)
6550 MONO_ARCH_SAVE_REGS
;
6552 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6555 static const char *encodings
[] = {
6557 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6558 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6559 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6561 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6562 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6563 "x_unicode_2_0_utf_7",
6565 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6566 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6568 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6571 "unicodefffe", "utf_16be",
6578 * Returns the internal codepage, if the value of "int_code_page" is
6579 * 1 at entry, and we can not compute a suitable code page number,
6580 * returns the code page as a string
6583 ves_icall_System_Text_Encoding_InternalCodePage (gint32
*int_code_page
)
6588 char *codepage
= NULL
;
6590 int want_name
= *int_code_page
;
6593 *int_code_page
= -1;
6594 MONO_ARCH_SAVE_REGS
;
6596 g_get_charset (&cset
);
6597 c
= codepage
= strdup (cset
);
6598 for (c
= codepage
; *c
; c
++){
6599 if (isascii (*c
) && isalpha (*c
))
6604 /* g_print ("charset: %s\n", cset); */
6606 /* handle some common aliases */
6609 for (i
= 0; p
!= 0; ){
6610 if ((gssize
) p
< 7){
6612 p
= encodings
[++i
];
6615 if (strcmp (p
, codepage
) == 0){
6616 *int_code_page
= code
;
6619 p
= encodings
[++i
];
6622 if (strstr (codepage
, "utf_8") != NULL
)
6623 *int_code_page
|= 0x10000000;
6626 if (want_name
&& *int_code_page
== -1)
6627 return mono_string_new (mono_domain_get (), cset
);
6633 ves_icall_System_Environment_get_HasShutdownStarted (void)
6635 if (mono_runtime_is_shutting_down ())
6638 if (mono_domain_is_unloading (mono_domain_get ()))
6645 ves_icall_System_Environment_BroadcastSettingChange (void)
6648 SendMessageTimeout (HWND_BROADCAST
, WM_SETTINGCHANGE
, NULL
, L
"Environment", SMTO_ABORTIFHUNG
, 2000, 0);
6653 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage
*this,
6654 MonoReflectionMethod
*method
,
6655 MonoArray
*out_args
)
6657 MONO_ARCH_SAVE_REGS
;
6659 mono_message_init (mono_object_domain (this), this, method
, out_args
);
6663 ves_icall_IsTransparentProxy (MonoObject
*proxy
)
6665 MONO_ARCH_SAVE_REGS
;
6670 if (proxy
->vtable
->klass
== mono_defaults
.transparent_proxy_class
)
6676 static MonoReflectionMethod
*
6677 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6678 MonoReflectionType
*rtype
, MonoReflectionMethod
*rmethod
)
6682 MonoMethod
**vtable
;
6683 MonoMethod
*res
= NULL
;
6685 MONO_CHECK_ARG_NULL (rtype
);
6686 MONO_CHECK_ARG_NULL (rmethod
);
6688 method
= rmethod
->method
;
6689 klass
= mono_class_from_mono_type (rtype
->type
);
6691 if (MONO_CLASS_IS_INTERFACE (klass
))
6694 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
)
6697 if ((method
->flags
& METHOD_ATTRIBUTE_FINAL
) || !(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
6698 if (klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
))
6704 mono_class_setup_vtable (klass
);
6705 vtable
= klass
->vtable
;
6707 if (method
->klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
6708 gboolean variance_used
= FALSE
;
6709 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6710 int offs
= mono_class_interface_offset_with_variance (klass
, method
->klass
, &variance_used
);
6712 res
= vtable
[offs
+ method
->slot
];
6714 if (!(klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
)))
6717 if (method
->slot
!= -1)
6718 res
= vtable
[method
->slot
];
6724 return mono_method_get_object (mono_domain_get (), res
, NULL
);
6728 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType
*type
, MonoBoolean enable
)
6733 MONO_ARCH_SAVE_REGS
;
6735 klass
= mono_class_from_mono_type (type
->type
);
6736 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, TRUE
);
6738 if (enable
) vtable
->remote
= 1;
6739 else vtable
->remote
= 0;
6743 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType
*type
)
6748 MONO_ARCH_SAVE_REGS
;
6750 domain
= mono_object_domain (type
);
6751 klass
= mono_class_from_mono_type (type
->type
);
6753 if (klass
->rank
>= 1) {
6754 g_assert (klass
->rank
== 1);
6755 return (MonoObject
*) mono_array_new (domain
, klass
->element_class
, 0);
6757 /* Bypass remoting object creation check */
6758 return mono_object_new_alloc_specific (mono_class_vtable_full (domain
, klass
, TRUE
));
6763 ves_icall_System_IO_get_temp_path (void)
6765 MONO_ARCH_SAVE_REGS
;
6767 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6770 #ifndef PLATFORM_NO_DRIVEINFO
6772 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString
*path_name
, guint64
*free_bytes_avail
,
6773 guint64
*total_number_of_bytes
, guint64
*total_number_of_free_bytes
,
6777 ULARGE_INTEGER wapi_free_bytes_avail
;
6778 ULARGE_INTEGER wapi_total_number_of_bytes
;
6779 ULARGE_INTEGER wapi_total_number_of_free_bytes
;
6781 MONO_ARCH_SAVE_REGS
;
6783 *error
= ERROR_SUCCESS
;
6784 result
= GetDiskFreeSpaceEx (mono_string_chars (path_name
), &wapi_free_bytes_avail
, &wapi_total_number_of_bytes
,
6785 &wapi_total_number_of_free_bytes
);
6788 *free_bytes_avail
= wapi_free_bytes_avail
.QuadPart
;
6789 *total_number_of_bytes
= wapi_total_number_of_bytes
.QuadPart
;
6790 *total_number_of_free_bytes
= wapi_total_number_of_free_bytes
.QuadPart
;
6792 *free_bytes_avail
= 0;
6793 *total_number_of_bytes
= 0;
6794 *total_number_of_free_bytes
= 0;
6795 *error
= GetLastError ();
6802 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString
*root_path_name
)
6804 MONO_ARCH_SAVE_REGS
;
6806 return GetDriveType (mono_string_chars (root_path_name
));
6811 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod
*method
)
6813 MONO_ARCH_SAVE_REGS
;
6815 return mono_compile_method (method
);
6819 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6824 MONO_ARCH_SAVE_REGS
;
6826 path
= g_build_path (G_DIR_SEPARATOR_S
, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version
, "machine.config", NULL
);
6828 #if defined (HOST_WIN32)
6829 /* Avoid mixing '/' and '\\' */
6832 for (i
= strlen (path
) - 1; i
>= 0; i
--)
6833 if (path
[i
] == '/')
6837 mcpath
= mono_string_new (mono_domain_get (), path
);
6844 get_bundled_machine_config (void)
6846 const gchar
*machine_config
;
6848 MONO_ARCH_SAVE_REGS
;
6850 machine_config
= mono_get_machine_config ();
6852 if (!machine_config
)
6855 return mono_string_new (mono_domain_get (), machine_config
);
6859 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6864 MONO_ARCH_SAVE_REGS
;
6866 path
= g_path_get_dirname (mono_get_config_dir ());
6868 #if defined (HOST_WIN32)
6869 /* Avoid mixing '/' and '\\' */
6872 for (i
= strlen (path
) - 1; i
>= 0; i
--)
6873 if (path
[i
] == '/')
6877 ipath
= mono_string_new (mono_domain_get (), path
);
6884 ves_icall_get_resources_ptr (MonoReflectionAssembly
*assembly
, gpointer
*result
, gint32
*size
)
6886 MonoPEResourceDataEntry
*entry
;
6889 MONO_ARCH_SAVE_REGS
;
6891 if (!assembly
|| !result
|| !size
)
6896 image
= assembly
->assembly
->image
;
6897 entry
= mono_image_lookup_resource (image
, MONO_PE_RESOURCE_ID_ASPNET_STRING
, 0, NULL
);
6901 *result
= mono_image_rva_map (image
, entry
->rde_data_offset
);
6906 *size
= entry
->rde_size
;
6912 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6914 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6918 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString
*message
)
6920 #if defined (HOST_WIN32)
6921 OutputDebugString (mono_string_chars (message
));
6923 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6927 /* Only used for value types */
6929 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType
*type
)
6934 MONO_ARCH_SAVE_REGS
;
6936 domain
= mono_object_domain (type
);
6937 klass
= mono_class_from_mono_type (type
->type
);
6939 if (mono_class_is_nullable (klass
))
6940 /* No arguments -> null */
6943 return mono_object_new (domain
, klass
);
6946 static MonoReflectionMethod
*
6947 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod
*m
, gboolean definition
)
6949 MonoClass
*klass
, *parent
;
6950 MonoMethod
*method
= m
->method
;
6951 MonoMethod
*result
= NULL
;
6953 MONO_ARCH_SAVE_REGS
;
6955 if (method
->klass
== NULL
)
6958 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
6959 MONO_CLASS_IS_INTERFACE (method
->klass
) ||
6960 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
6963 klass
= method
->klass
;
6964 if (klass
->generic_class
)
6965 klass
= klass
->generic_class
->container_class
;
6968 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6969 for (parent
= klass
->parent
; parent
!= NULL
; parent
= parent
->parent
) {
6970 mono_class_setup_vtable (parent
);
6971 if (parent
->vtable_size
<= method
->slot
)
6976 klass
= klass
->parent
;
6981 if (klass
== method
->klass
)
6984 result
= klass
->vtable
[method
->slot
];
6985 if (result
== NULL
) {
6986 /* It is an abstract method */
6987 gpointer iter
= NULL
;
6988 while ((result
= mono_class_get_methods (klass
, &iter
)))
6989 if (result
->slot
== method
->slot
)
6996 return mono_method_get_object (mono_domain_get (), result
, NULL
);
7000 ves_icall_MonoMethod_get_name (MonoReflectionMethod
*m
)
7002 MonoMethod
*method
= m
->method
;
7004 MONO_OBJECT_SETREF (m
, name
, mono_string_new (mono_object_domain (m
), method
->name
));
7009 mono_ArgIterator_Setup (MonoArgIterator
*iter
, char* argsp
, char* start
)
7011 MONO_ARCH_SAVE_REGS
;
7013 iter
->sig
= *(MonoMethodSignature
**)argsp
;
7015 g_assert (iter
->sig
->sentinelpos
<= iter
->sig
->param_count
);
7016 g_assert (iter
->sig
->call_convention
== MONO_CALL_VARARG
);
7019 /* FIXME: it's not documented what start is exactly... */
7023 iter
->args
= argsp
+ sizeof (gpointer
);
7025 iter
->num_args
= iter
->sig
->param_count
- iter
->sig
->sentinelpos
;
7027 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7031 mono_ArgIterator_IntGetNextArg (MonoArgIterator
*iter
)
7033 guint32 i
, arg_size
;
7036 MONO_ARCH_SAVE_REGS
;
7038 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7040 g_assert (i
< iter
->sig
->param_count
);
7042 res
.type
= iter
->sig
->params
[i
];
7043 res
.klass
= mono_class_from_mono_type (res
.type
);
7044 res
.value
= iter
->args
;
7045 arg_size
= mono_type_stack_size (res
.type
, &align
);
7046 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7047 if (arg_size
<= sizeof (gpointer
)) {
7049 int padding
= arg_size
- mono_type_size (res
.type
, &dummy
);
7050 res
.value
= (guint8
*)res
.value
+ padding
;
7053 iter
->args
= (char*)iter
->args
+ arg_size
;
7056 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7062 mono_ArgIterator_IntGetNextArgT (MonoArgIterator
*iter
, MonoType
*type
)
7064 guint32 i
, arg_size
;
7067 MONO_ARCH_SAVE_REGS
;
7069 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7071 g_assert (i
< iter
->sig
->param_count
);
7073 while (i
< iter
->sig
->param_count
) {
7074 if (!mono_metadata_type_equal (type
, iter
->sig
->params
[i
]))
7076 res
.type
= iter
->sig
->params
[i
];
7077 res
.klass
= mono_class_from_mono_type (res
.type
);
7078 /* FIXME: endianess issue... */
7079 res
.value
= iter
->args
;
7080 arg_size
= mono_type_stack_size (res
.type
, &align
);
7081 iter
->args
= (char*)iter
->args
+ arg_size
;
7083 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7086 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7095 mono_ArgIterator_IntGetNextArgType (MonoArgIterator
*iter
)
7098 MONO_ARCH_SAVE_REGS
;
7100 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7102 g_assert (i
< iter
->sig
->param_count
);
7104 return iter
->sig
->params
[i
];
7108 mono_TypedReference_ToObject (MonoTypedRef tref
)
7110 MONO_ARCH_SAVE_REGS
;
7112 if (MONO_TYPE_IS_REFERENCE (tref
.type
)) {
7113 MonoObject
** objp
= tref
.value
;
7117 return mono_value_box (mono_domain_get (), tref
.klass
, tref
.value
);
7121 mono_TypedReference_ToObjectInternal (MonoType
*type
, gpointer value
, MonoClass
*klass
)
7123 MONO_ARCH_SAVE_REGS
;
7125 if (MONO_TYPE_IS_REFERENCE (type
)) {
7126 MonoObject
** objp
= value
;
7130 return mono_value_box (mono_domain_get (), klass
, value
);
7134 prelink_method (MonoMethod
*method
)
7136 const char *exc_class
, *exc_arg
;
7137 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
7139 mono_lookup_pinvoke_call (method
, &exc_class
, &exc_arg
);
7141 mono_raise_exception(
7142 mono_exception_from_name_msg (mono_defaults
.corlib
, "System", exc_class
, exc_arg
) );
7144 /* create the wrapper, too? */
7148 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod
*method
)
7150 MONO_ARCH_SAVE_REGS
;
7151 prelink_method (method
->method
);
7155 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType
*type
)
7157 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
7159 gpointer iter
= NULL
;
7160 MONO_ARCH_SAVE_REGS
;
7162 while ((m
= mono_class_get_methods (klass
, &iter
)))
7166 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7168 ves_icall_System_NumberFormatter_GetFormatterTables (guint64
const **mantissas
,
7169 gint32
const **exponents
,
7170 gunichar2
const **digitLowerTable
,
7171 gunichar2
const **digitUpperTable
,
7172 gint64
const **tenPowersList
,
7173 gint32
const **decHexDigits
)
7175 *mantissas
= Formatter_MantissaBitsTable
;
7176 *exponents
= Formatter_TensExponentTable
;
7177 *digitLowerTable
= Formatter_DigitLowerTable
;
7178 *digitUpperTable
= Formatter_DigitUpperTable
;
7179 *tenPowersList
= Formatter_TenPowersList
;
7180 *decHexDigits
= Formatter_DecHexDigits
;
7183 /* These parameters are "readonly" in corlib/System/Char.cs */
7185 ves_icall_System_Char_GetDataTablePointers (guint8
const **category_data
,
7186 guint8
const **numeric_data
,
7187 gdouble
const **numeric_data_values
,
7188 guint16
const **to_lower_data_low
,
7189 guint16
const **to_lower_data_high
,
7190 guint16
const **to_upper_data_low
,
7191 guint16
const **to_upper_data_high
)
7193 *category_data
= CategoryData
;
7194 *numeric_data
= NumericData
;
7195 *numeric_data_values
= NumericDataValues
;
7196 *to_lower_data_low
= ToLowerDataLow
;
7197 *to_lower_data_high
= ToLowerDataHigh
;
7198 *to_upper_data_low
= ToUpperDataLow
;
7199 *to_upper_data_high
= ToUpperDataHigh
;
7203 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod
*method
)
7205 return method
->method
->token
;
7209 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7210 * and avoid useless allocations.
7213 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
)
7217 for (i
= 0; i
< type
->num_mods
; ++i
) {
7218 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
))
7223 res
= mono_array_new (mono_domain_get (), mono_defaults
.systemtype_class
, count
);
7225 for (i
= 0; i
< type
->num_mods
; ++i
) {
7226 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
)) {
7227 MonoClass
*klass
= mono_class_get (image
, type
->modifiers
[i
].token
);
7228 mono_array_setref (res
, count
, mono_type_get_object (mono_domain_get (), &klass
->byval_arg
));
7236 param_info_get_type_modifiers (MonoReflectionParameter
*param
, MonoBoolean optional
)
7238 MonoType
*type
= param
->ClassImpl
->type
;
7239 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
7240 MonoMethod
*method
= NULL
;
7243 MonoMethodSignature
*sig
;
7245 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
7246 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
7247 method
= rmethod
->method
;
7248 } else if (member_class
->image
== mono_defaults
.corlib
&& !strcmp ("MonoProperty", member_class
->name
)) {
7249 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
7250 if (!(method
= prop
->property
->get
))
7251 method
= prop
->property
->set
;
7254 char *type_name
= mono_type_get_full_name (member_class
);
7255 char *msg
= g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name
);
7256 MonoException
*ex
= mono_get_exception_not_supported (msg
);
7259 mono_raise_exception (ex
);
7262 image
= method
->klass
->image
;
7263 pos
= param
->PositionImpl
;
7264 sig
= mono_method_signature (method
);
7268 type
= sig
->params
[pos
];
7270 return type_array_from_modifiers (image
, type
, optional
);
7274 get_property_type (MonoProperty
*prop
)
7276 MonoMethodSignature
*sig
;
7278 sig
= mono_method_signature (prop
->get
);
7280 } else if (prop
->set
) {
7281 sig
= mono_method_signature (prop
->set
);
7282 return sig
->params
[sig
->param_count
- 1];
7288 property_info_get_type_modifiers (MonoReflectionProperty
*property
, MonoBoolean optional
)
7290 MonoType
*type
= get_property_type (property
->property
);
7291 MonoImage
*image
= property
->klass
->image
;
7295 return type_array_from_modifiers (image
, type
, optional
);
7299 *Construct a MonoType suited to be used to decode a constant blob object.
7301 * @type is the target type which will be constructed
7302 * @blob_type is the blob type, for example, that comes from the constant table
7303 * @real_type is the expected constructed type.
7306 mono_type_from_blob_type (MonoType
*type
, MonoTypeEnum blob_type
, MonoType
*real_type
)
7308 type
->type
= blob_type
;
7309 type
->data
.klass
= NULL
;
7310 if (blob_type
== MONO_TYPE_CLASS
)
7311 type
->data
.klass
= mono_defaults
.object_class
;
7312 else if (real_type
->type
== MONO_TYPE_VALUETYPE
&& real_type
->data
.klass
->enumtype
) {
7313 /* For enums, we need to use the base type */
7314 type
->type
= MONO_TYPE_VALUETYPE
;
7315 type
->data
.klass
= mono_class_from_mono_type (real_type
);
7317 type
->data
.klass
= mono_class_from_mono_type (real_type
);
7321 property_info_get_default_value (MonoReflectionProperty
*property
)
7324 MonoProperty
*prop
= property
->property
;
7325 MonoType
*type
= get_property_type (prop
);
7326 MonoDomain
*domain
= mono_object_domain (property
);
7327 MonoTypeEnum def_type
;
7328 const char *def_value
;
7331 g_assert (!prop
->parent
->image
->dynamic
);
7333 mono_class_init (prop
->parent
);
7335 if (!(prop
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
))
7336 mono_raise_exception (mono_get_exception_invalid_operation (NULL
));
7338 def_value
= mono_class_get_property_default_value (prop
, &def_type
);
7340 mono_type_from_blob_type (&blob_type
, def_type
, type
);
7341 o
= mono_get_object_from_blob (domain
, &blob_type
, def_value
);
7347 custom_attrs_defined_internal (MonoObject
*obj
, MonoReflectionType
*attr_type
)
7349 MonoCustomAttrInfo
*cinfo
;
7352 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
7355 found
= mono_custom_attrs_has_attr (cinfo
, mono_class_from_mono_type (attr_type
->type
));
7357 mono_custom_attrs_free (cinfo
);
7362 custom_attrs_get_by_type (MonoObject
*obj
, MonoReflectionType
*attr_type
)
7364 MonoArray
*res
= mono_reflection_get_custom_attrs_by_type (obj
, attr_type
? mono_class_from_mono_type (attr_type
->type
) : NULL
);
7366 if (mono_loader_get_last_error ()) {
7367 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7368 g_assert_not_reached ();
7377 ves_icall_Mono_Runtime_GetDisplayName (void)
7380 MonoString
*display_name
;
7382 info
= mono_get_runtime_callbacks ()->get_runtime_build_info ();
7383 display_name
= mono_string_new (mono_domain_get (), info
);
7385 return display_name
;
7389 ves_icall_Mono_Runtime_NewObject (MonoType
*t
)
7391 return mono_object_new (mono_domain_get (), mono_class_from_mono_type (t
));
7395 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code
)
7397 MonoString
*message
;
7401 ret
= FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
7402 FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, code
, 0,
7405 message
= mono_string_new (mono_domain_get (), "Error looking up error string");
7407 message
= mono_string_new_utf16 (mono_domain_get (), buf
, ret
);
7415 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7416 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7417 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7418 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7419 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7420 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7421 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7422 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7426 base64_to_byte_array (gunichar2
*start
, gint ilength
, MonoBoolean allowWhitespaceOnly
)
7431 gunichar2 last
, prev_last
, prev2_last
;
7439 last
= prev_last
= 0, prev2_last
= 0;
7440 for (i
= 0; i
< ilength
; i
++) {
7442 if (c
>= sizeof (dbase64
)) {
7443 exc
= mono_exception_from_name_msg (mono_get_corlib (),
7444 "System", "FormatException",
7445 "Invalid character found.");
7446 mono_raise_exception (exc
);
7447 } else if (isspace (c
)) {
7450 prev2_last
= prev_last
;
7456 olength
= ilength
- ignored
;
7458 if (allowWhitespaceOnly
&& olength
== 0) {
7459 return mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, 0);
7462 if ((olength
& 3) != 0 || olength
<= 0) {
7463 exc
= mono_exception_from_name_msg (mono_get_corlib (), "System",
7464 "FormatException", "Invalid length.");
7465 mono_raise_exception (exc
);
7468 if (prev2_last
== '=') {
7469 exc
= mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7470 mono_raise_exception (exc
);
7473 olength
= (olength
* 3) / 4;
7477 if (prev_last
== '=')
7480 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, olength
);
7481 res_ptr
= mono_array_addr (result
, guchar
, 0);
7482 for (i
= 0; i
< ilength
; ) {
7485 for (k
= 0; k
< 4 && i
< ilength
;) {
7491 if (((b
[k
] = dbase64
[c
]) & 0x80) != 0) {
7492 exc
= mono_exception_from_name_msg (mono_get_corlib (),
7493 "System", "FormatException",
7494 "Invalid character found.");
7495 mono_raise_exception (exc
);
7500 *res_ptr
++ = (b
[0] << 2) | (b
[1] >> 4);
7502 *res_ptr
++ = (b
[1] << 4) | (b
[2] >> 2);
7504 *res_ptr
++ = (b
[2] << 6) | b
[3];
7506 while (i
< ilength
&& isspace (start
[i
]))
7514 InternalFromBase64String (MonoString
*str
, MonoBoolean allowWhitespaceOnly
)
7516 MONO_ARCH_SAVE_REGS
;
7518 return base64_to_byte_array (mono_string_chars (str
),
7519 mono_string_length (str
), allowWhitespaceOnly
);
7523 InternalFromBase64CharArray (MonoArray
*input
, gint offset
, gint length
)
7525 MONO_ARCH_SAVE_REGS
;
7527 return base64_to_byte_array (mono_array_addr (input
, gunichar2
, offset
),
7531 #define ICALL_TYPE(id,name,first)
7532 #define ICALL(id,name,func) Icall_ ## id,
7535 #include "metadata/icall-def.h"
7541 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7542 #define ICALL(id,name,func)
7544 #include "metadata/icall-def.h"
7550 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7551 #define ICALL(id,name,func)
7553 guint16 first_icall
;
7556 static const IcallTypeDesc
7557 icall_type_descs
[] = {
7558 #include "metadata/icall-def.h"
7562 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7565 #define ICALL_TYPE(id,name,first)
7568 #ifdef HAVE_ARRAY_ELEM_INIT
7569 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7570 #define MSGSTRFIELD1(line) str##line
7572 static const struct msgstrtn_t
{
7573 #define ICALL(id,name,func)
7575 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7576 #include "metadata/icall-def.h"
7578 } icall_type_names_str
= {
7579 #define ICALL_TYPE(id,name,first) (name),
7580 #include "metadata/icall-def.h"
7583 static const guint16 icall_type_names_idx
[] = {
7584 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7585 #include "metadata/icall-def.h"
7588 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7590 static const struct msgstr_t
{
7592 #define ICALL_TYPE(id,name,first)
7593 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7594 #include "metadata/icall-def.h"
7596 } icall_names_str
= {
7597 #define ICALL(id,name,func) (name),
7598 #include "metadata/icall-def.h"
7601 static const guint16 icall_names_idx
[] = {
7602 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7603 #include "metadata/icall-def.h"
7606 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7612 #define ICALL_TYPE(id,name,first) name,
7613 #define ICALL(id,name,func)
7614 static const char* const
7615 icall_type_names
[] = {
7616 #include "metadata/icall-def.h"
7620 #define icall_type_name_get(id) (icall_type_names [(id)])
7624 #define ICALL_TYPE(id,name,first)
7625 #define ICALL(id,name,func) name,
7626 static const char* const
7628 #include "metadata/icall-def.h"
7631 #define icall_name_get(id) icall_names [(id)]
7633 #endif /* !HAVE_ARRAY_ELEM_INIT */
7637 #define ICALL_TYPE(id,name,first)
7638 #define ICALL(id,name,func) func,
7639 static const gconstpointer
7640 icall_functions
[] = {
7641 #include "metadata/icall-def.h"
7645 static GHashTable
*icall_hash
= NULL
;
7646 static GHashTable
*jit_icall_hash_name
= NULL
;
7647 static GHashTable
*jit_icall_hash_addr
= NULL
;
7650 mono_icall_init (void)
7654 /* check that tables are sorted: disable in release */
7657 const char *prev_class
= NULL
;
7658 const char *prev_method
;
7660 for (i
= 0; i
< Icall_type_num
; ++i
) {
7661 const IcallTypeDesc
*desc
;
7664 if (prev_class
&& strcmp (prev_class
, icall_type_name_get (i
)) >= 0)
7665 g_print ("class %s should come before class %s\n", icall_type_name_get (i
), prev_class
);
7666 prev_class
= icall_type_name_get (i
);
7667 desc
= &icall_type_descs
[i
];
7668 num_icalls
= icall_desc_num_icalls (desc
);
7669 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7670 for (j
= 0; j
< num_icalls
; ++j
) {
7671 const char *methodn
= icall_name_get (desc
->first_icall
+ j
);
7672 if (prev_method
&& strcmp (prev_method
, methodn
) >= 0)
7673 g_print ("method %s should come before method %s\n", methodn
, prev_method
);
7674 prev_method
= methodn
;
7679 icall_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
7683 mono_icall_cleanup (void)
7685 g_hash_table_destroy (icall_hash
);
7686 g_hash_table_destroy (jit_icall_hash_name
);
7687 g_hash_table_destroy (jit_icall_hash_addr
);
7691 mono_add_internal_call (const char *name
, gconstpointer method
)
7693 mono_loader_lock ();
7695 g_hash_table_insert (icall_hash
, g_strdup (name
), (gpointer
) method
);
7697 mono_loader_unlock ();
7700 #ifdef HAVE_ARRAY_ELEM_INIT
7702 compare_method_imap (const void *key
, const void *elem
)
7704 const char* method_name
= (const char*)&icall_names_str
+ (*(guint16
*)elem
);
7705 return strcmp (key
, method_name
);
7709 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
7711 const guint16
*nameslot
= bsearch (name
, icall_names_idx
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names_idx
[0]), compare_method_imap
);
7714 return (gpointer
)icall_functions
[(nameslot
- &icall_names_idx
[0])];
7718 compare_class_imap (const void *key
, const void *elem
)
7720 const char* class_name
= (const char*)&icall_type_names_str
+ (*(guint16
*)elem
);
7721 return strcmp (key
, class_name
);
7724 static const IcallTypeDesc
*
7725 find_class_icalls (const char *name
)
7727 const guint16
*nameslot
= bsearch (name
, icall_type_names_idx
, Icall_type_num
, sizeof (icall_type_names_idx
[0]), compare_class_imap
);
7730 return &icall_type_descs
[nameslot
- &icall_type_names_idx
[0]];
7735 compare_method_imap (const void *key
, const void *elem
)
7737 const char** method_name
= (const char**)elem
;
7738 return strcmp (key
, *method_name
);
7742 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
7744 const char **nameslot
= bsearch (name
, icall_names
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names
[0]), compare_method_imap
);
7747 return (gpointer
)icall_functions
[(nameslot
- icall_names
)];
7751 compare_class_imap (const void *key
, const void *elem
)
7753 const char** class_name
= (const char**)elem
;
7754 return strcmp (key
, *class_name
);
7757 static const IcallTypeDesc
*
7758 find_class_icalls (const char *name
)
7760 const char **nameslot
= bsearch (name
, icall_type_names
, Icall_type_num
, sizeof (icall_type_names
[0]), compare_class_imap
);
7763 return &icall_type_descs
[nameslot
- icall_type_names
];
7769 * we should probably export this as an helper (handle nested types).
7770 * Returns the number of chars written in buf.
7773 concat_class_name (char *buf
, int bufsize
, MonoClass
*klass
)
7775 int nspacelen
, cnamelen
;
7776 nspacelen
= strlen (klass
->name_space
);
7777 cnamelen
= strlen (klass
->name
);
7778 if (nspacelen
+ cnamelen
+ 2 > bufsize
)
7781 memcpy (buf
, klass
->name_space
, nspacelen
);
7782 buf
[nspacelen
++] = '.';
7784 memcpy (buf
+ nspacelen
, klass
->name
, cnamelen
);
7785 buf
[nspacelen
+ cnamelen
] = 0;
7786 return nspacelen
+ cnamelen
;
7790 mono_lookup_internal_call (MonoMethod
*method
)
7795 int typelen
= 0, mlen
, siglen
;
7797 const IcallTypeDesc
*imap
;
7799 g_assert (method
!= NULL
);
7801 if (method
->is_inflated
)
7802 method
= ((MonoMethodInflated
*) method
)->declaring
;
7804 if (method
->klass
->nested_in
) {
7805 int pos
= concat_class_name (mname
, sizeof (mname
)-2, method
->klass
->nested_in
);
7809 mname
[pos
++] = '/';
7812 typelen
= concat_class_name (mname
+pos
, sizeof (mname
)-pos
-1, method
->klass
);
7818 typelen
= concat_class_name (mname
, sizeof (mname
), method
->klass
);
7823 imap
= find_class_icalls (mname
);
7825 mname
[typelen
] = ':';
7826 mname
[typelen
+ 1] = ':';
7828 mlen
= strlen (method
->name
);
7829 memcpy (mname
+ typelen
+ 2, method
->name
, mlen
);
7830 sigstart
= mname
+ typelen
+ 2 + mlen
;
7833 tmpsig
= mono_signature_get_desc (mono_method_signature (method
), TRUE
);
7834 siglen
= strlen (tmpsig
);
7835 if (typelen
+ mlen
+ siglen
+ 6 > sizeof (mname
))
7838 memcpy (sigstart
+ 1, tmpsig
, siglen
);
7839 sigstart
[siglen
+ 1] = ')';
7840 sigstart
[siglen
+ 2] = 0;
7843 mono_loader_lock ();
7845 res
= g_hash_table_lookup (icall_hash
, mname
);
7847 mono_loader_unlock ();
7850 /* try without signature */
7852 res
= g_hash_table_lookup (icall_hash
, mname
);
7854 mono_loader_unlock ();
7858 /* it wasn't found in the static call tables */
7860 mono_loader_unlock ();
7863 res
= find_method_icall (imap
, sigstart
- mlen
);
7865 mono_loader_unlock ();
7868 /* try _with_ signature */
7870 res
= find_method_icall (imap
, sigstart
- mlen
);
7872 mono_loader_unlock ();
7876 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname
);
7877 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7878 g_print ("The out of sync library is: %s\n", method
->klass
->image
->name
);
7879 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7880 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");
7881 g_print ("If you see other errors or faults after this message they are probably related\n");
7882 g_print ("and you need to fix your mono install first.\n");
7884 mono_loader_unlock ();
7890 type_from_typename (char *typename
)
7892 MonoClass
*klass
= NULL
; /* assignment to shut GCC warning up */
7894 if (!strcmp (typename
, "int"))
7895 klass
= mono_defaults
.int_class
;
7896 else if (!strcmp (typename
, "ptr"))
7897 klass
= mono_defaults
.int_class
;
7898 else if (!strcmp (typename
, "void"))
7899 klass
= mono_defaults
.void_class
;
7900 else if (!strcmp (typename
, "int32"))
7901 klass
= mono_defaults
.int32_class
;
7902 else if (!strcmp (typename
, "uint32"))
7903 klass
= mono_defaults
.uint32_class
;
7904 else if (!strcmp (typename
, "int8"))
7905 klass
= mono_defaults
.sbyte_class
;
7906 else if (!strcmp (typename
, "uint8"))
7907 klass
= mono_defaults
.byte_class
;
7908 else if (!strcmp (typename
, "int16"))
7909 klass
= mono_defaults
.int16_class
;
7910 else if (!strcmp (typename
, "uint16"))
7911 klass
= mono_defaults
.uint16_class
;
7912 else if (!strcmp (typename
, "long"))
7913 klass
= mono_defaults
.int64_class
;
7914 else if (!strcmp (typename
, "ulong"))
7915 klass
= mono_defaults
.uint64_class
;
7916 else if (!strcmp (typename
, "float"))
7917 klass
= mono_defaults
.single_class
;
7918 else if (!strcmp (typename
, "double"))
7919 klass
= mono_defaults
.double_class
;
7920 else if (!strcmp (typename
, "object"))
7921 klass
= mono_defaults
.object_class
;
7922 else if (!strcmp (typename
, "obj"))
7923 klass
= mono_defaults
.object_class
;
7924 else if (!strcmp (typename
, "string"))
7925 klass
= mono_defaults
.string_class
;
7926 else if (!strcmp (typename
, "bool"))
7927 klass
= mono_defaults
.boolean_class
;
7928 else if (!strcmp (typename
, "boolean"))
7929 klass
= mono_defaults
.boolean_class
;
7931 g_error ("%s", typename
);
7932 g_assert_not_reached ();
7934 return &klass
->byval_arg
;
7937 MonoMethodSignature
*
7938 mono_create_icall_signature (const char *sigstr
)
7943 MonoMethodSignature
*res
;
7945 mono_loader_lock ();
7946 res
= g_hash_table_lookup (mono_defaults
.corlib
->helper_signatures
, sigstr
);
7948 mono_loader_unlock ();
7952 parts
= g_strsplit (sigstr
, " ", 256);
7961 res
= mono_metadata_signature_alloc (mono_defaults
.corlib
, len
- 1);
7966 * Under windows, the default pinvoke calling convention is STDCALL but
7969 res
->call_convention
= MONO_CALL_C
;
7972 res
->ret
= type_from_typename (parts
[0]);
7973 for (i
= 1; i
< len
; ++i
) {
7974 res
->params
[i
- 1] = type_from_typename (parts
[i
]);
7979 g_hash_table_insert (mono_defaults
.corlib
->helper_signatures
, (gpointer
)sigstr
, res
);
7981 mono_loader_unlock ();
7987 mono_find_jit_icall_by_name (const char *name
)
7989 MonoJitICallInfo
*info
;
7990 g_assert (jit_icall_hash_name
);
7992 mono_loader_lock ();
7993 info
= g_hash_table_lookup (jit_icall_hash_name
, name
);
7994 mono_loader_unlock ();
7999 mono_find_jit_icall_by_addr (gconstpointer addr
)
8001 MonoJitICallInfo
*info
;
8002 g_assert (jit_icall_hash_addr
);
8004 mono_loader_lock ();
8005 info
= g_hash_table_lookup (jit_icall_hash_addr
, (gpointer
)addr
);
8006 mono_loader_unlock ();
8012 * mono_get_jit_icall_info:
8014 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8015 * caller should access it while holding the loader lock.
8018 mono_get_jit_icall_info (void)
8020 return jit_icall_hash_name
;
8024 mono_register_jit_icall_wrapper (MonoJitICallInfo
*info
, gconstpointer wrapper
)
8026 mono_loader_lock ();
8027 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)wrapper
, info
);
8028 mono_loader_unlock ();
8032 mono_register_jit_icall (gconstpointer func
, const char *name
, MonoMethodSignature
*sig
, gboolean is_save
)
8034 MonoJitICallInfo
*info
;
8039 mono_loader_lock ();
8041 if (!jit_icall_hash_name
) {
8042 jit_icall_hash_name
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, g_free
);
8043 jit_icall_hash_addr
= g_hash_table_new (NULL
, NULL
);
8046 if (g_hash_table_lookup (jit_icall_hash_name
, name
)) {
8047 g_warning ("jit icall already defined \"%s\"\n", name
);
8048 g_assert_not_reached ();
8051 info
= g_new0 (MonoJitICallInfo
, 1);
8058 info
->wrapper
= func
;
8060 info
->wrapper
= NULL
;
8063 g_hash_table_insert (jit_icall_hash_name
, (gpointer
)info
->name
, info
);
8064 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)func
, info
);
8066 mono_loader_unlock ();