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 #ifndef MONO_SMALL_CONFIG
2091 if (event
->event
->other
) {
2093 while (event
->event
->other
[n
])
2095 MONO_STRUCT_SETREF (info
, other_methods
, mono_array_new (domain
, mono_defaults
.method_info_class
, n
));
2097 for (i
= 0; i
< n
; i
++)
2098 mono_array_setref (info
->other_methods
, i
, mono_method_get_object (domain
, event
->event
->other
[i
], NULL
));
2104 ves_icall_Type_GetInterfaces (MonoReflectionType
* type
)
2107 MonoDomain
*domain
= mono_object_domain (type
);
2109 GPtrArray
*ifaces
= NULL
;
2111 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2114 MonoGenericContext
*context
= NULL
;
2116 MONO_ARCH_SAVE_REGS
;
2118 if (class->generic_class
&& class->generic_class
->context
.class_inst
->is_open
) {
2119 context
= mono_class_get_context (class);
2120 class = class->generic_class
->container_class
;
2123 mono_class_setup_vtable (class);
2125 slots
= mono_bitset_new (class->max_interface_id
+ 1, 0);
2127 for (parent
= class; parent
; parent
= parent
->parent
) {
2128 GPtrArray
*tmp_ifaces
= mono_class_get_implemented_interfaces (parent
, &error
);
2129 if (!mono_error_ok (&error
)) {
2130 mono_bitset_free (slots
);
2131 mono_error_raise_exception (&error
);
2133 } else if (tmp_ifaces
) {
2134 for (i
= 0; i
< tmp_ifaces
->len
; ++i
) {
2135 MonoClass
*ic
= g_ptr_array_index (tmp_ifaces
, i
);
2137 if (mono_bitset_test (slots
, ic
->interface_id
))
2140 mono_bitset_set (slots
, ic
->interface_id
);
2142 ifaces
= g_ptr_array_new ();
2143 g_ptr_array_add (ifaces
, ic
);
2145 g_ptr_array_free (tmp_ifaces
, TRUE
);
2148 mono_bitset_free (slots
);
2151 return mono_array_new_cached (domain
, mono_defaults
.monotype_class
, 0);
2153 intf
= mono_array_new_cached (domain
, mono_defaults
.monotype_class
, ifaces
->len
);
2154 for (i
= 0; i
< ifaces
->len
; ++i
) {
2155 MonoClass
*ic
= g_ptr_array_index (ifaces
, i
);
2156 MonoType
*ret
= &ic
->byval_arg
, *inflated
= NULL
;
2157 if (context
&& ic
->generic_class
&& ic
->generic_class
->context
.class_inst
->is_open
)
2158 inflated
= ret
= mono_class_inflate_generic_type (ret
, context
);
2160 mono_array_setref (intf
, i
, mono_type_get_object (domain
, ret
));
2162 mono_metadata_free_type (inflated
);
2164 g_ptr_array_free (ifaces
, TRUE
);
2170 ves_icall_Type_GetInterfaceMapData (MonoReflectionType
*type
, MonoReflectionType
*iface
, MonoArray
**targets
, MonoArray
**methods
)
2172 gboolean variance_used
;
2173 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2174 MonoClass
*iclass
= mono_class_from_mono_type (iface
->type
);
2175 MonoReflectionMethod
*member
;
2178 int i
= 0, len
, ioffset
;
2181 MONO_ARCH_SAVE_REGS
;
2183 mono_class_setup_vtable (class);
2185 ioffset
= mono_class_interface_offset_with_variance (class, iclass
, &variance_used
);
2189 len
= mono_class_num_methods (iclass
);
2190 domain
= mono_object_domain (type
);
2191 mono_gc_wbarrier_generic_store (targets
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.method_info_class
, len
));
2192 mono_gc_wbarrier_generic_store (methods
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.method_info_class
, len
));
2194 while ((method
= mono_class_get_methods (iclass
, &iter
))) {
2195 member
= mono_method_get_object (domain
, method
, iclass
);
2196 mono_array_setref (*methods
, i
, member
);
2197 member
= mono_method_get_object (domain
, class->vtable
[i
+ ioffset
], class);
2198 mono_array_setref (*targets
, i
, member
);
2205 ves_icall_Type_GetPacking (MonoReflectionType
*type
, guint32
*packing
, guint32
*size
)
2207 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2209 if (klass
->image
->dynamic
) {
2210 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)type
;
2211 *packing
= tb
->packing_size
;
2212 *size
= tb
->class_size
;
2214 mono_metadata_packing_from_typedef (klass
->image
, klass
->type_token
, packing
, size
);
2218 static MonoReflectionType
*
2219 ves_icall_MonoType_GetElementType (MonoReflectionType
*type
)
2223 MONO_ARCH_SAVE_REGS
;
2225 if (!type
->type
->byref
&& type
->type
->type
== MONO_TYPE_SZARRAY
)
2226 return mono_type_get_object (mono_object_domain (type
), &type
->type
->data
.klass
->byval_arg
);
2228 class = mono_class_from_mono_type (type
->type
);
2230 // GetElementType should only return a type for:
2231 // Array Pointer PassedByRef
2232 if (type
->type
->byref
)
2233 return mono_type_get_object (mono_object_domain (type
), &class->byval_arg
);
2234 else if (class->element_class
&& MONO_CLASS_IS_ARRAY (class))
2235 return mono_type_get_object (mono_object_domain (type
), &class->element_class
->byval_arg
);
2236 else if (class->element_class
&& type
->type
->type
== MONO_TYPE_PTR
)
2237 return mono_type_get_object (mono_object_domain (type
), &class->element_class
->byval_arg
);
2242 static MonoReflectionType
*
2243 ves_icall_get_type_parent (MonoReflectionType
*type
)
2245 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2247 MONO_ARCH_SAVE_REGS
;
2249 return class->parent
? mono_type_get_object (mono_object_domain (type
), &class->parent
->byval_arg
): NULL
;
2253 ves_icall_type_ispointer (MonoReflectionType
*type
)
2255 MONO_ARCH_SAVE_REGS
;
2257 return type
->type
->type
== MONO_TYPE_PTR
;
2261 ves_icall_type_isprimitive (MonoReflectionType
*type
)
2263 MONO_ARCH_SAVE_REGS
;
2265 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
)));
2269 ves_icall_type_isbyref (MonoReflectionType
*type
)
2271 MONO_ARCH_SAVE_REGS
;
2273 return type
->type
->byref
;
2277 ves_icall_type_iscomobject (MonoReflectionType
*type
)
2279 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2280 MONO_ARCH_SAVE_REGS
;
2282 return (klass
&& klass
->is_com_object
);
2285 static MonoReflectionModule
*
2286 ves_icall_MonoType_get_Module (MonoReflectionType
*type
)
2288 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2290 MONO_ARCH_SAVE_REGS
;
2292 return mono_module_get_object (mono_object_domain (type
), class->image
);
2295 static MonoReflectionAssembly
*
2296 ves_icall_MonoType_get_Assembly (MonoReflectionType
*type
)
2298 MonoDomain
*domain
= mono_domain_get ();
2299 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2301 MONO_ARCH_SAVE_REGS
;
2303 return mono_assembly_get_object (domain
, class->image
->assembly
);
2306 static MonoReflectionType
*
2307 ves_icall_MonoType_get_DeclaringType (MonoReflectionType
*type
)
2309 MonoDomain
*domain
= mono_domain_get ();
2312 MONO_ARCH_SAVE_REGS
;
2314 if (type
->type
->byref
)
2316 if (type
->type
->type
== MONO_TYPE_VAR
)
2317 class = mono_type_get_generic_param_owner (type
->type
)->owner
.klass
;
2318 else if (type
->type
->type
== MONO_TYPE_MVAR
)
2319 class = mono_type_get_generic_param_owner (type
->type
)->owner
.method
->klass
;
2321 class = mono_class_from_mono_type (type
->type
)->nested_in
;
2323 return class ? mono_type_get_object (domain
, &class->byval_arg
) : NULL
;
2326 static MonoReflectionType
*
2327 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType
*type
)
2329 MonoDomain
*domain
= mono_domain_get ();
2330 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2332 MONO_ARCH_SAVE_REGS
;
2334 if (class->enumtype
&& mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2335 return mono_type_get_object (domain
, mono_class_enum_basetype (class));
2336 else if (class->element_class
)
2337 return mono_type_get_object (domain
, &class->element_class
->byval_arg
);
2343 ves_icall_MonoType_get_Name (MonoReflectionType
*type
)
2345 MonoDomain
*domain
= mono_domain_get ();
2346 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2348 MONO_ARCH_SAVE_REGS
;
2350 if (type
->type
->byref
) {
2351 char *n
= g_strdup_printf ("%s&", class->name
);
2352 MonoString
*res
= mono_string_new (domain
, n
);
2358 return mono_string_new (domain
, class->name
);
2363 ves_icall_MonoType_get_Namespace (MonoReflectionType
*type
)
2365 MonoDomain
*domain
= mono_domain_get ();
2366 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2368 MONO_ARCH_SAVE_REGS
;
2370 while (class->nested_in
)
2371 class = class->nested_in
;
2373 if (class->name_space
[0] == '\0')
2376 return mono_string_new (domain
, class->name_space
);
2380 ves_icall_MonoType_GetArrayRank (MonoReflectionType
*type
)
2384 if (type
->type
->type
!= MONO_TYPE_ARRAY
&& type
->type
->type
!= MONO_TYPE_SZARRAY
)
2385 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2387 class = mono_class_from_mono_type (type
->type
);
2392 ves_icall_MonoType_GetGenericArguments (MonoReflectionType
*type
)
2395 MonoClass
*klass
, *pklass
;
2396 MonoDomain
*domain
= mono_object_domain (type
);
2397 MonoVTable
*array_vtable
= mono_class_vtable_full (domain
, mono_array_class_get_cached (mono_defaults
.systemtype_class
, 1), TRUE
);
2399 MONO_ARCH_SAVE_REGS
;
2401 klass
= mono_class_from_mono_type (type
->type
);
2403 if (klass
->generic_container
) {
2404 MonoGenericContainer
*container
= klass
->generic_container
;
2405 res
= mono_array_new_specific (array_vtable
, container
->type_argc
);
2406 for (i
= 0; i
< container
->type_argc
; ++i
) {
2407 pklass
= mono_class_from_generic_parameter (mono_generic_container_get_param (container
, i
), klass
->image
, FALSE
);
2408 mono_array_setref (res
, i
, mono_type_get_object (domain
, &pklass
->byval_arg
));
2410 } else if (klass
->generic_class
) {
2411 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
2412 res
= mono_array_new_specific (array_vtable
, inst
->type_argc
);
2413 for (i
= 0; i
< inst
->type_argc
; ++i
)
2414 mono_array_setref (res
, i
, mono_type_get_object (domain
, inst
->type_argv
[i
]));
2416 res
= mono_array_new_specific (array_vtable
, 0);
2422 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType
*type
)
2425 MONO_ARCH_SAVE_REGS
;
2427 if (!IS_MONOTYPE (type
))
2430 if (type
->type
->byref
)
2433 klass
= mono_class_from_mono_type (type
->type
);
2435 return klass
->generic_container
!= NULL
;
2438 static MonoReflectionType
*
2439 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType
*type
)
2442 MONO_ARCH_SAVE_REGS
;
2444 if (type
->type
->byref
)
2447 klass
= mono_class_from_mono_type (type
->type
);
2448 if (klass
->generic_container
) {
2449 return type
; /* check this one */
2451 if (klass
->generic_class
) {
2452 MonoClass
*generic_class
= klass
->generic_class
->container_class
;
2455 tb
= mono_class_get_ref_info (generic_class
);
2457 if (generic_class
->wastypebuilder
&& tb
)
2460 return mono_type_get_object (mono_object_domain (type
), &generic_class
->byval_arg
);
2465 static MonoReflectionType
*
2466 ves_icall_Type_MakeGenericType (MonoReflectionType
*type
, MonoArray
*type_array
)
2468 MonoType
*geninst
, **types
;
2471 MONO_ARCH_SAVE_REGS
;
2473 count
= mono_array_length (type_array
);
2474 types
= g_new0 (MonoType
*, count
);
2476 for (i
= 0; i
< count
; i
++) {
2477 MonoReflectionType
*t
= mono_array_get (type_array
, gpointer
, i
);
2478 types
[i
] = t
->type
;
2481 geninst
= mono_reflection_bind_generic_parameters (type
, count
, types
);
2486 return mono_type_get_object (mono_object_domain (type
), geninst
);
2490 ves_icall_Type_get_IsGenericInstance (MonoReflectionType
*type
)
2493 MONO_ARCH_SAVE_REGS
;
2495 if (type
->type
->byref
)
2498 klass
= mono_class_from_mono_type (type
->type
);
2499 return klass
->generic_class
!= NULL
;
2503 ves_icall_Type_get_IsGenericType (MonoReflectionType
*type
)
2506 MONO_ARCH_SAVE_REGS
;
2508 if (!IS_MONOTYPE (type
))
2511 if (type
->type
->byref
)
2514 klass
= mono_class_from_mono_type (type
->type
);
2515 return klass
->generic_class
!= NULL
|| klass
->generic_container
!= NULL
;
2519 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType
*type
)
2521 MONO_ARCH_SAVE_REGS
;
2523 if (!IS_MONOTYPE (type
))
2526 if (is_generic_parameter (type
->type
))
2527 return mono_type_get_generic_param_num (type
->type
);
2531 static GenericParameterAttributes
2532 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType
*type
)
2534 MONO_ARCH_SAVE_REGS
;
2536 g_assert (IS_MONOTYPE (type
));
2537 g_assert (is_generic_parameter (type
->type
));
2538 return mono_generic_param_info (type
->type
->data
.generic_param
)->flags
;
2542 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType
*type
)
2544 MonoGenericParamInfo
*param_info
;
2550 MONO_ARCH_SAVE_REGS
;
2552 g_assert (IS_MONOTYPE (type
));
2554 domain
= mono_object_domain (type
);
2555 param_info
= mono_generic_param_info (type
->type
->data
.generic_param
);
2556 for (count
= 0, ptr
= param_info
->constraints
; ptr
&& *ptr
; ptr
++, count
++)
2559 res
= mono_array_new (domain
, mono_defaults
.monotype_class
, count
);
2560 for (i
= 0; i
< count
; i
++)
2561 mono_array_setref (res
, i
, mono_type_get_object (domain
, ¶m_info
->constraints
[i
]->byval_arg
));
2568 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType
*type
)
2570 MONO_ARCH_SAVE_REGS
;
2571 return is_generic_parameter (type
->type
);
2575 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder
*tb
)
2577 MONO_ARCH_SAVE_REGS
;
2578 return is_generic_parameter (tb
->type
.type
);
2582 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType
*enumtype
,
2583 MonoReflectionType
*t
)
2585 enumtype
->type
= t
->type
;
2588 static MonoReflectionMethod
*
2589 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType
*type
,
2590 MonoReflectionMethod
* generic
)
2597 MONO_ARCH_SAVE_REGS
;
2599 domain
= ((MonoObject
*)type
)->vtable
->domain
;
2601 klass
= mono_class_from_mono_type (type
->type
);
2604 while ((method
= mono_class_get_methods (klass
, &iter
))) {
2605 if (method
->token
== generic
->method
->token
)
2606 return mono_method_get_object (domain
, method
, klass
);
2614 static MonoReflectionMethod
*
2615 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType
*ref_type
)
2618 MonoType
*type
= ref_type
->type
;
2620 MONO_ARCH_SAVE_REGS
;
2622 if (type
->byref
|| (type
->type
!= MONO_TYPE_MVAR
&& type
->type
!= MONO_TYPE_VAR
))
2623 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2624 if (type
->type
== MONO_TYPE_VAR
)
2627 method
= mono_type_get_generic_param_owner (type
)->owner
.method
;
2629 return mono_method_get_object (mono_object_domain (ref_type
), method
, method
->klass
);
2632 static MonoReflectionDllImportAttribute
*
2633 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod
*method
)
2635 static MonoClass
*DllImportAttributeClass
= NULL
;
2636 MonoDomain
*domain
= mono_domain_get ();
2637 MonoReflectionDllImportAttribute
*attr
;
2638 MonoImage
*image
= method
->klass
->image
;
2639 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)method
;
2640 MonoTableInfo
*tables
= image
->tables
;
2641 MonoTableInfo
*im
= &tables
[MONO_TABLE_IMPLMAP
];
2642 MonoTableInfo
*mr
= &tables
[MONO_TABLE_MODULEREF
];
2643 guint32 im_cols
[MONO_IMPLMAP_SIZE
];
2644 guint32 scope_token
;
2645 const char *import
= NULL
;
2646 const char *scope
= NULL
;
2649 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
2652 if (!DllImportAttributeClass
) {
2653 DllImportAttributeClass
=
2654 mono_class_from_name (mono_defaults
.corlib
,
2655 "System.Runtime.InteropServices", "DllImportAttribute");
2656 g_assert (DllImportAttributeClass
);
2659 if (method
->klass
->image
->dynamic
) {
2660 MonoReflectionMethodAux
*method_aux
=
2661 g_hash_table_lookup (
2662 ((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
2664 import
= method_aux
->dllentry
;
2665 scope
= method_aux
->dll
;
2668 if (!import
|| !scope
) {
2669 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2674 if (piinfo
->implmap_idx
) {
2675 mono_metadata_decode_row (im
, piinfo
->implmap_idx
- 1, im_cols
, MONO_IMPLMAP_SIZE
);
2677 piinfo
->piflags
= im_cols
[MONO_IMPLMAP_FLAGS
];
2678 import
= mono_metadata_string_heap (image
, im_cols
[MONO_IMPLMAP_NAME
]);
2679 scope_token
= mono_metadata_decode_row_col (mr
, im_cols
[MONO_IMPLMAP_SCOPE
] - 1, MONO_MODULEREF_NAME
);
2680 scope
= mono_metadata_string_heap (image
, scope_token
);
2683 flags
= piinfo
->piflags
;
2685 attr
= (MonoReflectionDllImportAttribute
*)mono_object_new (domain
, DllImportAttributeClass
);
2687 MONO_OBJECT_SETREF (attr
, dll
, mono_string_new (domain
, scope
));
2688 MONO_OBJECT_SETREF (attr
, entry_point
, mono_string_new (domain
, import
));
2689 attr
->call_conv
= (flags
& 0x700) >> 8;
2690 attr
->charset
= ((flags
& 0x6) >> 1) + 1;
2691 if (attr
->charset
== 1)
2693 attr
->exact_spelling
= (flags
& 0x1) != 0;
2694 attr
->set_last_error
= (flags
& 0x40) != 0;
2695 attr
->best_fit_mapping
= (flags
& 0x30) == 0x10;
2696 attr
->throw_on_unmappable
= (flags
& 0x3000) == 0x1000;
2697 attr
->preserve_sig
= FALSE
;
2702 static MonoReflectionMethod
*
2703 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod
*method
)
2705 MonoMethodInflated
*imethod
;
2708 MONO_ARCH_SAVE_REGS
;
2710 if (method
->method
->is_generic
)
2713 if (!method
->method
->is_inflated
)
2716 imethod
= (MonoMethodInflated
*) method
->method
;
2718 result
= imethod
->declaring
;
2719 /* Not a generic method. */
2720 if (!result
->is_generic
)
2723 if (method
->method
->klass
->image
->dynamic
) {
2724 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->method
->klass
->image
;
2725 MonoReflectionMethod
*res
;
2728 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2729 * the dynamic case as well ?
2731 mono_loader_lock ();
2732 res
= mono_g_hash_table_lookup (image
->generic_def_objects
, imethod
);
2733 mono_loader_unlock ();
2739 if (imethod
->context
.class_inst
) {
2740 MonoClass
*klass
= ((MonoMethod
*) imethod
)->klass
;
2741 /*Generic methods gets the context of the GTD.*/
2742 if (mono_class_get_context (klass
))
2743 result
= mono_class_inflate_generic_method_full (result
, klass
, mono_class_get_context (klass
));
2746 return mono_method_get_object (mono_object_domain (method
), result
, NULL
);
2750 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod
*method
)
2752 MONO_ARCH_SAVE_REGS
;
2754 return mono_method_signature (method
->method
)->generic_param_count
!= 0;
2758 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod
*method
)
2760 MONO_ARCH_SAVE_REGS
;
2762 return method
->method
->is_generic
;
2766 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod
*method
)
2771 MONO_ARCH_SAVE_REGS
;
2773 domain
= mono_object_domain (method
);
2775 if (method
->method
->is_inflated
) {
2776 MonoGenericInst
*inst
= mono_method_get_context (method
->method
)->method_inst
;
2779 count
= inst
->type_argc
;
2780 res
= mono_array_new (domain
, mono_defaults
.systemtype_class
, count
);
2782 for (i
= 0; i
< count
; i
++)
2783 mono_array_setref (res
, i
, mono_type_get_object (domain
, inst
->type_argv
[i
]));
2789 count
= mono_method_signature (method
->method
)->generic_param_count
;
2790 res
= mono_array_new (domain
, mono_defaults
.systemtype_class
, count
);
2792 for (i
= 0; i
< count
; i
++) {
2793 MonoGenericContainer
*container
= mono_method_get_generic_container (method
->method
);
2794 MonoGenericParam
*param
= mono_generic_container_get_param (container
, i
);
2795 MonoClass
*pklass
= mono_class_from_generic_parameter (
2796 param
, method
->method
->klass
->image
, TRUE
);
2797 mono_array_setref (res
, i
,
2798 mono_type_get_object (domain
, &pklass
->byval_arg
));
2805 ves_icall_InternalInvoke (MonoReflectionMethod
*method
, MonoObject
*this, MonoArray
*params
, MonoException
**exc
)
2808 * Invoke from reflection is supposed to always be a virtual call (the API
2809 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2810 * greater flexibility.
2812 MonoMethod
*m
= method
->method
;
2816 MONO_ARCH_SAVE_REGS
;
2820 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
2821 mono_security_core_clr_ensure_reflection_access_method (m
);
2823 if (!(m
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
2825 if (!mono_object_isinst (this, m
->klass
)) {
2826 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Object does not match target type."));
2829 m
= mono_object_get_virtual_method (this, m
);
2830 /* must pass the pointer to the value for valuetype methods */
2831 if (m
->klass
->valuetype
)
2832 obj
= mono_object_unbox (this);
2833 } else if (strcmp (m
->name
, ".ctor") && !m
->wrapper_type
) {
2834 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Non-static method requires a target."));
2839 pcount
= params
? mono_array_length (params
): 0;
2840 if (pcount
!= mono_method_signature (m
)->param_count
) {
2841 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name (mono_defaults
.corlib
, "System.Reflection", "TargetParameterCountException"));
2845 if ((m
->klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
) && !strcmp (m
->name
, ".ctor") && !this) {
2846 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."));
2850 if (m
->klass
->image
->assembly
->ref_only
) {
2851 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."));
2855 if (m
->klass
->rank
&& !strcmp (m
->name
, ".ctor")) {
2857 mono_array_size_t
*lengths
;
2858 mono_array_size_t
*lower_bounds
;
2859 pcount
= mono_array_length (params
);
2860 lengths
= alloca (sizeof (mono_array_size_t
) * pcount
);
2861 for (i
= 0; i
< pcount
; ++i
)
2862 lengths
[i
] = *(mono_array_size_t
*) ((char*)mono_array_get (params
, gpointer
, i
) + sizeof (MonoObject
));
2864 if (m
->klass
->rank
== pcount
) {
2865 /* Only lengths provided. */
2866 lower_bounds
= NULL
;
2868 g_assert (pcount
== (m
->klass
->rank
* 2));
2869 /* lower bounds are first. */
2870 lower_bounds
= lengths
;
2871 lengths
+= m
->klass
->rank
;
2874 return (MonoObject
*)mono_array_new_full (mono_object_domain (params
), m
->klass
, lengths
, lower_bounds
);
2876 return mono_runtime_invoke_array (m
, obj
, params
, NULL
);
2880 ves_icall_InternalExecute (MonoReflectionMethod
*method
, MonoObject
*this, MonoArray
*params
, MonoArray
**outArgs
)
2882 MonoDomain
*domain
= mono_object_domain (method
);
2883 MonoMethod
*m
= method
->method
;
2884 MonoMethodSignature
*sig
= mono_method_signature (m
);
2885 MonoArray
*out_args
;
2887 int i
, j
, outarg_count
= 0;
2889 MONO_ARCH_SAVE_REGS
;
2891 if (m
->klass
== mono_defaults
.object_class
) {
2893 if (!strcmp (m
->name
, "FieldGetter")) {
2894 MonoClass
*k
= this->vtable
->klass
;
2898 /* If this is a proxy, then it must be a CBO */
2899 if (k
== mono_defaults
.transparent_proxy_class
) {
2900 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
2901 this = tp
->rp
->unwrapped_server
;
2903 k
= this->vtable
->klass
;
2906 name
= mono_array_get (params
, MonoString
*, 1);
2907 str
= mono_string_to_utf8 (name
);
2910 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
2912 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2913 if (field_klass
->valuetype
)
2914 result
= mono_value_box (domain
, field_klass
, (char *)this + field
->offset
);
2916 result
= *((gpointer
*)((char *)this + field
->offset
));
2918 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 1);
2919 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2920 mono_array_setref (out_args
, 0, result
);
2928 g_assert_not_reached ();
2930 } else if (!strcmp (m
->name
, "FieldSetter")) {
2931 MonoClass
*k
= this->vtable
->klass
;
2937 /* If this is a proxy, then it must be a CBO */
2938 if (k
== mono_defaults
.transparent_proxy_class
) {
2939 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
2940 this = tp
->rp
->unwrapped_server
;
2942 k
= this->vtable
->klass
;
2945 name
= mono_array_get (params
, MonoString
*, 1);
2946 str
= mono_string_to_utf8 (name
);
2949 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
2951 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2952 MonoObject
*val
= mono_array_get (params
, gpointer
, 2);
2954 if (field_klass
->valuetype
) {
2955 size
= mono_type_size (field
->type
, &align
);
2956 g_assert (size
== mono_class_value_size (field_klass
, NULL
));
2957 mono_gc_wbarrier_value_copy ((char *)this + field
->offset
, (char*)val
+ sizeof (MonoObject
), 1, field_klass
);
2959 mono_gc_wbarrier_set_field (this, (char*)this + field
->offset
, val
);
2962 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 0);
2963 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2973 g_assert_not_reached ();
2978 for (i
= 0; i
< mono_array_length (params
); i
++) {
2979 if (sig
->params
[i
]->byref
)
2983 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, outarg_count
);
2985 /* handle constructors only for objects already allocated */
2986 if (!strcmp (method
->method
->name
, ".ctor"))
2989 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2990 g_assert (!method
->method
->klass
->valuetype
);
2991 result
= mono_runtime_invoke_array (method
->method
, this, params
, NULL
);
2993 for (i
= 0, j
= 0; i
< mono_array_length (params
); i
++) {
2994 if (sig
->params
[i
]->byref
) {
2996 arg
= mono_array_get (params
, gpointer
, i
);
2997 mono_array_setref (out_args
, j
, arg
);
3002 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
3008 read_enum_value (char *mem
, int type
)
3012 return *(guint8
*)mem
;
3014 return *(gint8
*)mem
;
3016 return *(guint16
*)mem
;
3018 return *(gint16
*)mem
;
3020 return *(guint32
*)mem
;
3022 return *(gint32
*)mem
;
3024 return *(guint64
*)mem
;
3026 return *(gint64
*)mem
;
3028 g_assert_not_reached ();
3034 write_enum_value (char *mem
, int type
, guint64 value
)
3038 case MONO_TYPE_I1
: {
3039 guint8
*p
= (guint8
*)mem
;
3044 case MONO_TYPE_I2
: {
3045 guint16
*p
= (void*)mem
;
3050 case MONO_TYPE_I4
: {
3051 guint32
*p
= (void*)mem
;
3056 case MONO_TYPE_I8
: {
3057 guint64
*p
= (void*)mem
;
3062 g_assert_not_reached ();
3068 ves_icall_System_Enum_ToObject (MonoReflectionType
*enumType
, MonoObject
*value
)
3071 MonoClass
*enumc
, *objc
;
3075 MONO_ARCH_SAVE_REGS
;
3077 MONO_CHECK_ARG_NULL (enumType
);
3078 MONO_CHECK_ARG_NULL (value
);
3080 domain
= mono_object_domain (enumType
);
3081 enumc
= mono_class_from_mono_type (enumType
->type
);
3082 objc
= value
->vtable
->klass
;
3084 if (!enumc
->enumtype
)
3085 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3086 if (!((objc
->enumtype
) || (objc
->byval_arg
.type
>= MONO_TYPE_I1
&& objc
->byval_arg
.type
<= MONO_TYPE_U8
)))
3087 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."));
3089 res
= mono_object_new (domain
, enumc
);
3090 val
= read_enum_value ((char *)value
+ sizeof (MonoObject
), objc
->enumtype
? mono_class_enum_basetype (objc
)->type
: objc
->byval_arg
.type
);
3091 write_enum_value ((char *)res
+ sizeof (MonoObject
), mono_class_enum_basetype (enumc
)->type
, val
);
3097 ves_icall_System_Enum_get_value (MonoObject
*this)
3105 MONO_ARCH_SAVE_REGS
;
3110 g_assert (this->vtable
->klass
->enumtype
);
3112 enumc
= mono_class_from_mono_type (mono_class_enum_basetype (this->vtable
->klass
));
3113 res
= mono_object_new (mono_object_domain (this), enumc
);
3114 dst
= (char *)res
+ sizeof (MonoObject
);
3115 src
= (char *)this + sizeof (MonoObject
);
3116 size
= mono_class_value_size (enumc
, NULL
);
3118 memcpy (dst
, src
, size
);
3123 static MonoReflectionType
*
3124 ves_icall_System_Enum_get_underlying_type (MonoReflectionType
*type
)
3126 MONO_ARCH_SAVE_REGS
;
3128 return mono_type_get_object (mono_object_domain (type
), mono_class_enum_basetype (mono_class_from_mono_type (type
->type
)));
3132 ves_icall_System_Enum_compare_value_to (MonoObject
*this, MonoObject
*other
)
3134 gpointer tdata
= (char *)this + sizeof (MonoObject
);
3135 gpointer odata
= (char *)other
+ sizeof (MonoObject
);
3136 MonoType
*basetype
= mono_class_enum_basetype (this->vtable
->klass
);
3137 g_assert (basetype
);
3139 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3140 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3141 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3144 return me > other ? 1 : -1; \
3147 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3148 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3149 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3152 return me - other; \
3155 switch (basetype
->type
) {
3157 COMPARE_ENUM_VALUES (guint8
);
3159 COMPARE_ENUM_VALUES (gint8
);
3160 case MONO_TYPE_CHAR
:
3162 COMPARE_ENUM_VALUES_RANGE (guint16
);
3164 COMPARE_ENUM_VALUES (gint16
);
3166 COMPARE_ENUM_VALUES (guint32
);
3168 COMPARE_ENUM_VALUES (gint32
);
3170 COMPARE_ENUM_VALUES (guint64
);
3172 COMPARE_ENUM_VALUES (gint64
);
3174 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3176 #undef COMPARE_ENUM_VALUES_RANGE
3177 #undef COMPARE_ENUM_VALUES
3182 ves_icall_System_Enum_get_hashcode (MonoObject
*this)
3184 gpointer data
= (char *)this + sizeof (MonoObject
);
3185 MonoType
*basetype
= mono_class_enum_basetype (this->vtable
->klass
);
3186 g_assert (basetype
);
3188 switch (basetype
->type
) {
3190 return *((gint8
*)data
);
3192 return *((guint8
*)data
);
3193 case MONO_TYPE_CHAR
:
3195 return *((guint16
*)data
);
3198 return *((gint16
*)data
);
3200 return *((guint32
*)data
);
3202 return *((gint32
*)data
);
3204 case MONO_TYPE_I8
: {
3205 gint64 value
= *((gint64
*)data
);
3206 return (gint
)(value
& 0xffffffff) ^ (int)(value
>> 32);
3209 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3215 ves_icall_get_enum_info (MonoReflectionType
*type
, MonoEnumInfo
*info
)
3217 MonoDomain
*domain
= mono_object_domain (type
);
3218 MonoClass
*enumc
= mono_class_from_mono_type (type
->type
);
3219 guint j
= 0, nvalues
, crow
;
3221 MonoClassField
*field
;
3223 MONO_ARCH_SAVE_REGS
;
3225 MONO_STRUCT_SETREF (info
, utype
, mono_type_get_object (domain
, mono_class_enum_basetype (enumc
)));
3226 nvalues
= mono_class_num_fields (enumc
) ? mono_class_num_fields (enumc
) - 1 : 0;
3227 MONO_STRUCT_SETREF (info
, names
, mono_array_new (domain
, mono_defaults
.string_class
, nvalues
));
3228 MONO_STRUCT_SETREF (info
, values
, mono_array_new (domain
, enumc
, nvalues
));
3232 while ((field
= mono_class_get_fields (enumc
, &iter
))) {
3235 MonoTypeEnum def_type
;
3237 if (strcmp ("value__", mono_field_get_name (field
)) == 0)
3239 if (mono_field_is_deleted (field
))
3241 mono_array_setref (info
->names
, j
, mono_string_new (domain
, mono_field_get_name (field
)));
3243 p
= mono_class_get_field_default_value (field
, &def_type
);
3244 len
= mono_metadata_decode_blob_size (p
, &p
);
3245 switch (mono_class_enum_basetype (enumc
)->type
) {
3248 mono_array_set (info
->values
, gchar
, j
, *p
);
3250 case MONO_TYPE_CHAR
:
3253 mono_array_set (info
->values
, gint16
, j
, read16 (p
));
3257 mono_array_set (info
->values
, gint32
, j
, read32 (p
));
3261 mono_array_set (info
->values
, gint64
, j
, read64 (p
));
3264 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc
)->type
);
3271 BFLAGS_IgnoreCase
= 1,
3272 BFLAGS_DeclaredOnly
= 2,
3273 BFLAGS_Instance
= 4,
3275 BFLAGS_Public
= 0x10,
3276 BFLAGS_NonPublic
= 0x20,
3277 BFLAGS_FlattenHierarchy
= 0x40,
3278 BFLAGS_InvokeMethod
= 0x100,
3279 BFLAGS_CreateInstance
= 0x200,
3280 BFLAGS_GetField
= 0x400,
3281 BFLAGS_SetField
= 0x800,
3282 BFLAGS_GetProperty
= 0x1000,
3283 BFLAGS_SetProperty
= 0x2000,
3284 BFLAGS_ExactBinding
= 0x10000,
3285 BFLAGS_SuppressChangeType
= 0x20000,
3286 BFLAGS_OptionalParamBinding
= 0x40000
3289 static MonoReflectionField
*
3290 ves_icall_Type_GetField (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3293 MonoClass
*startklass
, *klass
;
3295 MonoClassField
*field
;
3298 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3299 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3300 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3302 MONO_ARCH_SAVE_REGS
;
3305 mono_raise_exception (mono_get_exception_argument_null ("name"));
3306 if (type
->type
->byref
)
3309 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
3312 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3313 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3316 while ((field
= mono_class_get_fields (klass
, &iter
))) {
3319 if (field
->type
== NULL
)
3321 if (mono_field_is_deleted (field
))
3323 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3324 if (bflags
& BFLAGS_Public
)
3326 } else if ((klass
== startklass
) || (field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3327 if (bflags
& BFLAGS_NonPublic
) {
3334 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
3335 if (bflags
& BFLAGS_Static
)
3336 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3339 if (bflags
& BFLAGS_Instance
)
3346 utf8_name
= mono_string_to_utf8 (name
);
3348 if (compare_func (mono_field_get_name (field
), utf8_name
)) {
3354 return mono_field_get_object (domain
, klass
, field
);
3356 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3363 ves_icall_Type_GetFields_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3366 MonoClass
*startklass
, *klass
, *refklass
;
3371 MonoClassField
*field
;
3372 MonoPtrArray tmp_array
;
3374 MONO_ARCH_SAVE_REGS
;
3376 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3377 if (type
->type
->byref
)
3378 return mono_array_new (domain
, mono_defaults
.field_info_class
, 0);
3379 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3380 refklass
= mono_class_from_mono_type (reftype
->type
);
3382 mono_ptr_array_init (tmp_array
, 2);
3385 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3386 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3389 while ((field
= mono_class_get_fields (klass
, &iter
))) {
3391 if (mono_field_is_deleted (field
))
3393 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3394 if (bflags
& BFLAGS_Public
)
3396 } else if ((klass
== startklass
) || (field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3397 if (bflags
& BFLAGS_NonPublic
) {
3404 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
3405 if (bflags
& BFLAGS_Static
)
3406 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3409 if (bflags
& BFLAGS_Instance
)
3415 member
= (MonoObject
*)mono_field_get_object (domain
, refklass
, field
);
3416 mono_ptr_array_append (tmp_array
, member
);
3418 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3421 res
= mono_array_new_cached (domain
, mono_defaults
.field_info_class
, mono_ptr_array_size (tmp_array
));
3423 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3424 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3426 mono_ptr_array_destroy (tmp_array
);
3432 method_nonpublic (MonoMethod
* method
, gboolean start_klass
)
3434 switch (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) {
3435 case METHOD_ATTRIBUTE_ASSEM
:
3436 return (start_klass
|| mono_defaults
.generic_ilist_class
);
3437 case METHOD_ATTRIBUTE_PRIVATE
:
3439 case METHOD_ATTRIBUTE_PUBLIC
:
3447 ves_icall_Type_GetMethodsByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3449 static MonoClass
*MethodInfo_array
;
3451 MonoClass
*startklass
, *klass
, *refklass
;
3456 int i
, len
, match
, nslots
;
3457 /*FIXME, use MonoBitSet*/
3458 guint32 method_slots_default
[8];
3459 guint32
*method_slots
= NULL
;
3460 gchar
*mname
= NULL
;
3461 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3462 MonoVTable
*array_vtable
;
3464 MonoPtrArray tmp_array
;
3466 MONO_ARCH_SAVE_REGS
;
3468 mono_ptr_array_init (tmp_array
, 4);
3470 if (!MethodInfo_array
) {
3471 MonoClass
*klass
= mono_array_class_get (mono_defaults
.method_info_class
, 1);
3472 mono_memory_barrier ();
3473 MethodInfo_array
= klass
;
3476 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3477 array_vtable
= mono_class_vtable_full (domain
, MethodInfo_array
, TRUE
);
3478 if (type
->type
->byref
)
3479 return mono_array_new_specific (array_vtable
, 0);
3480 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3481 refklass
= mono_class_from_mono_type (reftype
->type
);
3484 mname
= mono_string_to_utf8 (name
);
3485 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3488 /* An optimization for calls made from Delegate:CreateDelegate () */
3489 if (klass
->delegate
&& mname
&& !strcmp (mname
, "Invoke") && (bflags
== (BFLAGS_Public
| BFLAGS_Static
| BFLAGS_Instance
))) {
3490 method
= mono_get_delegate_invoke (klass
);
3491 if (mono_loader_get_last_error ())
3494 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3496 res
= mono_array_new_specific (array_vtable
, 1);
3497 mono_array_setref (res
, 0, member
);
3502 mono_class_setup_vtable (klass
);
3503 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3506 if (is_generic_parameter (type
->type
))
3507 nslots
= mono_class_get_vtable_size (klass
->parent
);
3509 nslots
= MONO_CLASS_IS_INTERFACE (klass
) ? mono_class_num_methods (klass
) : mono_class_get_vtable_size (klass
);
3510 if (nslots
>= sizeof (method_slots_default
) * 8) {
3511 method_slots
= g_new0 (guint32
, nslots
/ 32 + 1);
3513 method_slots
= method_slots_default
;
3514 memset (method_slots
, 0, sizeof (method_slots_default
));
3517 mono_class_setup_vtable (klass
);
3518 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3522 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3524 if (method
->slot
!= -1) {
3525 g_assert (method
->slot
< nslots
);
3526 if (method_slots
[method
->slot
>> 5] & (1 << (method
->slot
& 0x1f)))
3528 if (!(method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
))
3529 method_slots
[method
->slot
>> 5] |= 1 << (method
->slot
& 0x1f);
3532 if (method
->name
[0] == '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0))
3534 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3535 if (bflags
& BFLAGS_Public
)
3537 } else if ((bflags
& BFLAGS_NonPublic
) && method_nonpublic (method
, (klass
== startklass
))) {
3543 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3544 if (bflags
& BFLAGS_Static
)
3545 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3548 if (bflags
& BFLAGS_Instance
)
3556 if (compare_func (mname
, method
->name
))
3562 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3564 mono_ptr_array_append (tmp_array
, member
);
3566 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3570 if (method_slots
!= method_slots_default
)
3571 g_free (method_slots
);
3573 res
= mono_array_new_specific (array_vtable
, mono_ptr_array_size (tmp_array
));
3575 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3576 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3578 mono_ptr_array_destroy (tmp_array
);
3583 if (method_slots
!= method_slots_default
)
3584 g_free (method_slots
);
3585 mono_ptr_array_destroy (tmp_array
);
3586 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3587 ex
= mono_class_get_exception_for_failure (klass
);
3589 ex
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3590 mono_loader_clear_error ();
3592 mono_raise_exception (ex
);
3597 ves_icall_Type_GetConstructors_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3600 static MonoClass
*System_Reflection_ConstructorInfo
;
3601 MonoClass
*startklass
, *klass
, *refklass
;
3606 gpointer iter
= NULL
;
3607 MonoPtrArray tmp_array
;
3609 MONO_ARCH_SAVE_REGS
;
3611 mono_ptr_array_init (tmp_array
, 4); /*FIXME, guestimating*/
3613 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3614 if (type
->type
->byref
)
3615 return mono_array_new_cached (domain
, mono_defaults
.method_info_class
, 0);
3616 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3617 refklass
= mono_class_from_mono_type (reftype
->type
);
3619 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3620 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3622 if (!System_Reflection_ConstructorInfo
)
3623 System_Reflection_ConstructorInfo
= mono_class_from_name (
3624 mono_defaults
.corlib
, "System.Reflection", "ConstructorInfo");
3627 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3629 if (strcmp (method
->name
, ".ctor") && strcmp (method
->name
, ".cctor"))
3631 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3632 if (bflags
& BFLAGS_Public
)
3635 if (bflags
& BFLAGS_NonPublic
)
3641 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3642 if (bflags
& BFLAGS_Static
)
3643 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3646 if (bflags
& BFLAGS_Instance
)
3652 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3654 mono_ptr_array_append (tmp_array
, member
);
3657 res
= mono_array_new_cached (domain
, System_Reflection_ConstructorInfo
, mono_ptr_array_size (tmp_array
));
3659 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3660 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3662 mono_ptr_array_destroy (tmp_array
);
3668 property_hash (gconstpointer data
)
3670 MonoProperty
*prop
= (MonoProperty
*)data
;
3672 return g_str_hash (prop
->name
);
3676 property_equal (MonoProperty
*prop1
, MonoProperty
*prop2
)
3678 // Properties are hide-by-name-and-signature
3679 if (!g_str_equal (prop1
->name
, prop2
->name
))
3682 if (prop1
->get
&& prop2
->get
&& !mono_metadata_signature_equal (mono_method_signature (prop1
->get
), mono_method_signature (prop2
->get
)))
3684 if (prop1
->set
&& prop2
->set
&& !mono_metadata_signature_equal (mono_method_signature (prop1
->set
), mono_method_signature (prop2
->set
)))
3690 property_accessor_nonpublic (MonoMethod
* accessor
, gboolean start_klass
)
3695 return method_nonpublic (accessor
, start_klass
);
3699 ves_icall_Type_GetPropertiesByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3702 static MonoClass
*System_Reflection_PropertyInfo
;
3703 MonoClass
*startklass
, *klass
;
3709 gchar
*propname
= NULL
;
3710 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3712 GHashTable
*properties
;
3713 MonoPtrArray tmp_array
;
3715 MONO_ARCH_SAVE_REGS
;
3717 mono_ptr_array_init (tmp_array
, 8); /*This the average for ASP.NET types*/
3719 if (!System_Reflection_PropertyInfo
)
3720 System_Reflection_PropertyInfo
= mono_class_from_name (
3721 mono_defaults
.corlib
, "System.Reflection", "PropertyInfo");
3723 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3724 if (type
->type
->byref
)
3725 return mono_array_new_cached (domain
, System_Reflection_PropertyInfo
, 0);
3726 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3728 propname
= mono_string_to_utf8 (name
);
3729 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3732 mono_class_setup_vtable (klass
);
3734 properties
= g_hash_table_new (property_hash
, (GEqualFunc
)property_equal
);
3736 mono_class_setup_vtable (klass
);
3737 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3738 g_hash_table_destroy (properties
);
3741 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3745 while ((prop
= mono_class_get_properties (klass
, &iter
))) {
3751 flags
= method
->flags
;
3754 if ((prop
->get
&& ((prop
->get
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
)) ||
3755 (prop
->set
&& ((prop
->set
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
))) {
3756 if (bflags
& BFLAGS_Public
)
3758 } else if (bflags
& BFLAGS_NonPublic
) {
3759 if (property_accessor_nonpublic(prop
->get
, startklass
== klass
) ||
3760 property_accessor_nonpublic(prop
->set
, startklass
== klass
)) {
3767 if (flags
& METHOD_ATTRIBUTE_STATIC
) {
3768 if (bflags
& BFLAGS_Static
)
3769 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3772 if (bflags
& BFLAGS_Instance
)
3781 if (compare_func (propname
, prop
->name
))
3785 if (g_hash_table_lookup (properties
, prop
))
3788 mono_ptr_array_append (tmp_array
, mono_property_get_object (domain
, startklass
, prop
));
3790 g_hash_table_insert (properties
, prop
, prop
);
3792 if ((!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
)))
3795 g_hash_table_destroy (properties
);
3798 res
= mono_array_new_cached (domain
, System_Reflection_PropertyInfo
, mono_ptr_array_size (tmp_array
));
3799 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3800 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3802 mono_ptr_array_destroy (tmp_array
);
3807 static MonoReflectionEvent
*
3808 ves_icall_MonoType_GetEvent (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3811 MonoClass
*klass
, *startklass
;
3817 MONO_ARCH_SAVE_REGS
;
3819 event_name
= mono_string_to_utf8 (name
);
3820 if (type
->type
->byref
)
3822 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3823 domain
= mono_object_domain (type
);
3826 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3827 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3830 while ((event
= mono_class_get_events (klass
, &iter
))) {
3831 if (strcmp (event
->name
, event_name
))
3834 method
= event
->add
;
3836 method
= event
->remove
;
3838 method
= event
->raise
;
3840 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3841 if (!(bflags
& BFLAGS_Public
))
3844 if (!(bflags
& BFLAGS_NonPublic
))
3846 if ((klass
!= startklass
) && (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PRIVATE
)
3850 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3851 if (!(bflags
& BFLAGS_Static
))
3853 if (!(bflags
& BFLAGS_FlattenHierarchy
) && (klass
!= startklass
))
3856 if (!(bflags
& BFLAGS_Instance
))
3860 if (!(bflags
& BFLAGS_NonPublic
))
3863 g_free (event_name
);
3864 return mono_event_get_object (domain
, startklass
, event
);
3867 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3870 g_free (event_name
);
3875 ves_icall_Type_GetEvents_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3878 static MonoClass
*System_Reflection_EventInfo
;
3879 MonoClass
*startklass
, *klass
;
3886 MonoPtrArray tmp_array
;
3888 MONO_ARCH_SAVE_REGS
;
3890 mono_ptr_array_init (tmp_array
, 4);
3892 if (!System_Reflection_EventInfo
)
3893 System_Reflection_EventInfo
= mono_class_from_name (
3894 mono_defaults
.corlib
, "System.Reflection", "EventInfo");
3896 domain
= mono_object_domain (type
);
3897 if (type
->type
->byref
)
3898 return mono_array_new_cached (domain
, System_Reflection_EventInfo
, 0);
3899 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3902 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3903 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3906 while ((event
= mono_class_get_events (klass
, &iter
))) {
3908 method
= event
->add
;
3910 method
= event
->remove
;
3912 method
= event
->raise
;
3914 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3915 if (bflags
& BFLAGS_Public
)
3917 } else if ((klass
== startklass
) || (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) {
3918 if (bflags
& BFLAGS_NonPublic
)
3923 if (bflags
& BFLAGS_NonPublic
)
3929 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3930 if (bflags
& BFLAGS_Static
)
3931 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3934 if (bflags
& BFLAGS_Instance
)
3939 if (bflags
& BFLAGS_Instance
)
3943 mono_ptr_array_append (tmp_array
, mono_event_get_object (domain
, startklass
, event
));
3945 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3948 res
= mono_array_new_cached (domain
, System_Reflection_EventInfo
, mono_ptr_array_size (tmp_array
));
3950 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3951 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3953 mono_ptr_array_destroy (tmp_array
);
3958 static MonoReflectionType
*
3959 ves_icall_Type_GetNestedType (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3967 MONO_ARCH_SAVE_REGS
;
3970 mono_raise_exception (mono_get_exception_argument_null ("name"));
3972 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3973 if (type
->type
->byref
)
3975 klass
= mono_class_from_mono_type (type
->type
);
3976 str
= mono_string_to_utf8 (name
);
3979 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3980 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3983 * If a nested type is generic, return its generic type definition.
3984 * Note that this means that the return value is essentially a
3985 * nested type of the generic type definition of @klass.
3987 * A note in MSDN claims that a generic type definition can have
3988 * nested types that aren't generic. In any case, the container of that
3989 * nested type would be the generic type definition.
3991 if (klass
->generic_class
)
3992 klass
= klass
->generic_class
->container_class
;
3995 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
3997 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
3998 if (bflags
& BFLAGS_Public
)
4001 if (bflags
& BFLAGS_NonPublic
)
4006 if (strcmp (nested
->name
, str
) == 0){
4008 return mono_type_get_object (domain
, &nested
->byval_arg
);
4011 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
4018 ves_icall_Type_GetNestedTypes (MonoReflectionType
*type
, guint32 bflags
)
4027 MonoPtrArray tmp_array
;
4029 MONO_ARCH_SAVE_REGS
;
4031 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4032 if (type
->type
->byref
)
4033 return mono_array_new (domain
, mono_defaults
.monotype_class
, 0);
4034 klass
= mono_class_from_mono_type (type
->type
);
4035 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
4036 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
4039 * If a nested type is generic, return its generic type definition.
4040 * Note that this means that the return value is essentially the set
4041 * of nested types of the generic type definition of @klass.
4043 * A note in MSDN claims that a generic type definition can have
4044 * nested types that aren't generic. In any case, the container of that
4045 * nested type would be the generic type definition.
4047 if (klass
->generic_class
)
4048 klass
= klass
->generic_class
->container_class
;
4050 mono_ptr_array_init (tmp_array
, 1);
4052 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
4054 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
4055 if (bflags
& BFLAGS_Public
)
4058 if (bflags
& BFLAGS_NonPublic
)
4063 member
= (MonoObject
*)mono_type_get_object (domain
, &nested
->byval_arg
);
4064 mono_ptr_array_append (tmp_array
, member
);
4067 res
= mono_array_new_cached (domain
, mono_defaults
.monotype_class
, mono_ptr_array_size (tmp_array
));
4069 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4070 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4072 mono_ptr_array_destroy (tmp_array
);
4077 static MonoReflectionType
*
4078 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly
*assembly
, MonoReflectionModule
*module
, MonoString
*name
, MonoBoolean throwOnError
, MonoBoolean ignoreCase
)
4081 MonoType
*type
= NULL
;
4082 MonoTypeNameParse info
;
4083 gboolean type_resolve
;
4085 MONO_ARCH_SAVE_REGS
;
4087 /* On MS.NET, this does not fire a TypeResolve event */
4088 type_resolve
= TRUE
;
4089 str
= mono_string_to_utf8 (name
);
4090 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4091 if (!mono_reflection_parse_type (str
, &info
)) {
4093 mono_reflection_free_type_info (&info
);
4094 if (throwOnError
) /* uhm: this is a parse error, though... */
4095 mono_raise_exception (mono_get_exception_type_load (name
, NULL
));
4096 /*g_print ("failed parse\n");*/
4100 if (info
.assembly
.name
) {
4102 mono_reflection_free_type_info (&info
);
4104 /* 1.0 and 2.0 throw different exceptions */
4105 if (mono_defaults
.generic_ilist_class
)
4106 mono_raise_exception (mono_get_exception_argument (NULL
, "Type names passed to Assembly.GetType() must not specify an assembly."));
4108 mono_raise_exception (mono_get_exception_type_load (name
, NULL
));
4113 if (module
!= NULL
) {
4115 type
= mono_reflection_get_type (module
->image
, &info
, ignoreCase
, &type_resolve
);
4120 if (assembly
->assembly
->dynamic
) {
4121 /* Enumerate all modules */
4122 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)assembly
;
4126 if (abuilder
->modules
) {
4127 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
4128 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
4129 type
= mono_reflection_get_type (&mb
->dynamic_image
->image
, &info
, ignoreCase
, &type_resolve
);
4135 if (!type
&& abuilder
->loaded_modules
) {
4136 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
4137 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
4138 type
= mono_reflection_get_type (mod
->image
, &info
, ignoreCase
, &type_resolve
);
4145 type
= mono_reflection_get_type (assembly
->assembly
->image
, &info
, ignoreCase
, &type_resolve
);
4147 mono_reflection_free_type_info (&info
);
4149 MonoException
*e
= NULL
;
4152 e
= mono_get_exception_type_load (name
, NULL
);
4154 if (mono_loader_get_last_error () && mono_defaults
.generic_ilist_class
)
4155 e
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4157 mono_loader_clear_error ();
4160 mono_raise_exception (e
);
4165 if (type
->type
== MONO_TYPE_CLASS
) {
4166 MonoClass
*klass
= mono_type_get_class (type
);
4168 if (mono_is_security_manager_active () && !klass
->exception_type
)
4169 /* Some security problems are detected during generic vtable construction */
4170 mono_class_setup_vtable (klass
);
4171 /* need to report exceptions ? */
4172 if (throwOnError
&& klass
->exception_type
) {
4173 /* report SecurityException (or others) that occured when loading the assembly */
4174 MonoException
*exc
= mono_class_get_exception_for_failure (klass
);
4175 mono_loader_clear_error ();
4176 mono_raise_exception (exc
);
4177 } else if (klass
->exception_type
== MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND
) {
4182 /* g_print ("got it\n"); */
4183 return mono_type_get_object (mono_object_domain (assembly
), type
);
4187 replace_shadow_path (MonoDomain
*domain
, gchar
*dirname
, gchar
**filename
)
4190 gchar
*shadow_ini_file
;
4193 /* Check for shadow-copied assembly */
4194 if (mono_is_shadow_copy_enabled (domain
, dirname
)) {
4195 shadow_ini_file
= g_build_filename (dirname
, "__AssemblyInfo__.ini", NULL
);
4197 if (!g_file_get_contents (shadow_ini_file
, &content
, &len
, NULL
) ||
4198 !g_file_test (content
, G_FILE_TEST_IS_REGULAR
)) {
4204 g_free (shadow_ini_file
);
4205 if (content
!= NULL
) {
4208 *filename
= content
;
4216 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly
*assembly
, MonoBoolean escaped
)
4218 MonoDomain
*domain
= mono_object_domain (assembly
);
4219 MonoAssembly
*mass
= assembly
->assembly
;
4220 MonoString
*res
= NULL
;
4225 MONO_ARCH_SAVE_REGS
;
4227 if (g_path_is_absolute (mass
->image
->name
)) {
4228 absolute
= g_strdup (mass
->image
->name
);
4229 dirname
= g_path_get_dirname (absolute
);
4231 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
4232 dirname
= g_strdup (mass
->basedir
);
4235 replace_shadow_path (domain
, dirname
, &absolute
);
4240 for (i
= strlen (absolute
) - 1; i
>= 0; i
--)
4241 if (absolute
[i
] == '\\')
4246 uri
= g_filename_to_uri (absolute
, NULL
, NULL
);
4248 const char *prepend
= "file://";
4250 if (*absolute
== '/' && *(absolute
+ 1) == '/') {
4253 prepend
= "file:///";
4256 uri
= g_strconcat (prepend
, absolute
, NULL
);
4260 res
= mono_string_new (domain
, uri
);
4268 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly
*assembly
)
4270 MonoAssembly
*mass
= assembly
->assembly
;
4272 MONO_ARCH_SAVE_REGS
;
4274 return mass
->in_gac
;
4277 static MonoReflectionAssembly
*
4278 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString
*mname
, MonoObject
*evidence
)
4282 MonoImageOpenStatus status
;
4284 MONO_ARCH_SAVE_REGS
;
4286 name
= mono_string_to_utf8 (mname
);
4287 res
= mono_assembly_load_with_partial_name (name
, &status
);
4293 return mono_assembly_get_object (mono_domain_get (), res
);
4297 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly
*assembly
)
4299 MonoDomain
*domain
= mono_object_domain (assembly
);
4302 MONO_ARCH_SAVE_REGS
;
4304 res
= mono_string_new (domain
, mono_image_get_filename (assembly
->assembly
->image
));
4310 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly
*assembly
)
4312 MONO_ARCH_SAVE_REGS
;
4314 return assembly
->assembly
->ref_only
;
4318 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly
*assembly
)
4320 MonoDomain
*domain
= mono_object_domain (assembly
);
4322 MONO_ARCH_SAVE_REGS
;
4324 return mono_string_new (domain
, assembly
->assembly
->image
->version
);
4327 static MonoReflectionMethod
*
4328 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly
*assembly
)
4330 guint32 token
= mono_image_get_entry_point (assembly
->assembly
->image
);
4332 MONO_ARCH_SAVE_REGS
;
4336 return mono_method_get_object (mono_object_domain (assembly
), mono_get_method (assembly
->assembly
->image
, token
, NULL
), NULL
);
4339 static MonoReflectionModule
*
4340 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly
*assembly
)
4342 return mono_module_get_object (mono_object_domain (assembly
), assembly
->assembly
->image
);
4346 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly
*assembly
)
4348 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4349 MonoArray
*result
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, table
->rows
);
4353 MONO_ARCH_SAVE_REGS
;
4355 for (i
= 0; i
< table
->rows
; ++i
) {
4356 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_MANIFEST_NAME
));
4357 mono_array_setref (result
, i
, mono_string_new (mono_object_domain (assembly
), val
));
4363 create_version (MonoDomain
*domain
, guint32 major
, guint32 minor
, guint32 build
, guint32 revision
)
4365 static MonoClass
*System_Version
= NULL
;
4366 static MonoMethod
*create_version
= NULL
;
4370 if (!System_Version
) {
4371 System_Version
= mono_class_from_name (mono_defaults
.corlib
, "System", "Version");
4372 g_assert (System_Version
);
4375 if (!create_version
) {
4376 MonoMethodDesc
*desc
= mono_method_desc_new (":.ctor(int,int,int,int)", FALSE
);
4377 create_version
= mono_method_desc_search_in_class (desc
, System_Version
);
4378 g_assert (create_version
);
4379 mono_method_desc_free (desc
);
4385 args
[3] = &revision
;
4386 result
= mono_object_new (domain
, System_Version
);
4387 mono_runtime_invoke (create_version
, result
, args
, NULL
);
4393 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly
*assembly
)
4395 static MonoClass
*System_Reflection_AssemblyName
;
4397 MonoDomain
*domain
= mono_object_domain (assembly
);
4399 static MonoMethod
*create_culture
= NULL
;
4400 MonoImage
*image
= assembly
->assembly
->image
;
4403 MONO_ARCH_SAVE_REGS
;
4405 if (!System_Reflection_AssemblyName
)
4406 System_Reflection_AssemblyName
= mono_class_from_name (
4407 mono_defaults
.corlib
, "System.Reflection", "AssemblyName");
4409 t
= &assembly
->assembly
->image
->tables
[MONO_TABLE_ASSEMBLYREF
];
4412 result
= mono_array_new (domain
, System_Reflection_AssemblyName
, count
);
4414 if (count
> 0 && !create_culture
) {
4415 MonoMethodDesc
*desc
= mono_method_desc_new (
4416 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4417 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4418 g_assert (create_culture
);
4419 mono_method_desc_free (desc
);
4422 for (i
= 0; i
< count
; i
++) {
4423 MonoReflectionAssemblyName
*aname
;
4424 guint32 cols
[MONO_ASSEMBLYREF_SIZE
];
4426 mono_metadata_decode_row (t
, i
, cols
, MONO_ASSEMBLYREF_SIZE
);
4428 aname
= (MonoReflectionAssemblyName
*) mono_object_new (
4429 domain
, System_Reflection_AssemblyName
);
4431 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_NAME
])));
4433 aname
->major
= cols
[MONO_ASSEMBLYREF_MAJOR_VERSION
];
4434 aname
->minor
= cols
[MONO_ASSEMBLYREF_MINOR_VERSION
];
4435 aname
->build
= cols
[MONO_ASSEMBLYREF_BUILD_NUMBER
];
4436 aname
->revision
= cols
[MONO_ASSEMBLYREF_REV_NUMBER
];
4437 aname
->flags
= cols
[MONO_ASSEMBLYREF_FLAGS
];
4438 aname
->versioncompat
= 1; /* SameMachine (default) */
4439 aname
->hashalg
= ASSEMBLY_HASH_SHA1
; /* SHA1 (default) */
4440 MONO_OBJECT_SETREF (aname
, version
, create_version (domain
, aname
->major
, aname
->minor
, aname
->build
, aname
->revision
));
4442 if (create_culture
) {
4444 MonoBoolean assembly_ref
= 1;
4445 args
[0] = mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_CULTURE
]));
4446 args
[1] = &assembly_ref
;
4447 MONO_OBJECT_SETREF (aname
, cultureInfo
, mono_runtime_invoke (create_culture
, NULL
, args
, NULL
));
4450 if (cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]) {
4451 const gchar
*pkey_ptr
= mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]);
4452 guint32 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
4454 if ((cols
[MONO_ASSEMBLYREF_FLAGS
] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
)) {
4455 /* public key token isn't copied - the class library will
4456 automatically generate it from the public key if required */
4457 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4458 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
4460 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4461 memcpy (mono_array_addr (aname
->keyToken
, guint8
, 0), pkey_ptr
, pkey_len
);
4464 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
4467 /* note: this function doesn't return the codebase on purpose (i.e. it can
4468 be used under partial trust as path information isn't present). */
4470 mono_array_setref (result
, i
, aname
);
4481 foreach_namespace (const char* key
, gconstpointer val
, NameSpaceInfo
*info
)
4483 MonoString
*name
= mono_string_new (mono_object_domain (info
->res
), key
);
4485 mono_array_setref (info
->res
, info
->idx
, name
);
4490 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly
*assembly
)
4492 MonoImage
*img
= assembly
->assembly
->image
;
4497 MONO_ARCH_SAVE_REGS
;
4499 mono_image_lock (img
);
4500 mono_image_init_name_cache (img
);
4503 len
= g_hash_table_size (img
->name_cache
);
4504 mono_image_unlock (img
);
4506 /*we can't create objects holding the image lock */
4507 res
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, len
);
4509 mono_image_lock (img
);
4510 /*len might have changed, create a new array*/
4511 if (len
!= g_hash_table_size (img
->name_cache
))
4516 g_hash_table_foreach (img
->name_cache
, (GHFunc
)foreach_namespace
, &info
);
4517 mono_image_unlock (img
);
4522 /* move this in some file in mono/util/ */
4524 g_concat_dir_and_file (const char *dir
, const char *file
)
4526 g_return_val_if_fail (dir
!= NULL
, NULL
);
4527 g_return_val_if_fail (file
!= NULL
, NULL
);
4530 * If the directory name doesn't have a / on the end, we need
4531 * to add one so we get a proper path to the file
4533 if (dir
[strlen(dir
) - 1] != G_DIR_SEPARATOR
)
4534 return g_strconcat (dir
, G_DIR_SEPARATOR_S
, file
, NULL
);
4536 return g_strconcat (dir
, file
, NULL
);
4540 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, gint32
*size
, MonoReflectionModule
**ref_module
)
4542 char *n
= mono_string_to_utf8 (name
);
4543 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4545 guint32 cols
[MONO_MANIFEST_SIZE
];
4546 guint32 impl
, file_idx
;
4550 MONO_ARCH_SAVE_REGS
;
4552 for (i
= 0; i
< table
->rows
; ++i
) {
4553 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
4554 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
4555 if (strcmp (val
, n
) == 0)
4559 if (i
== table
->rows
)
4562 impl
= cols
[MONO_MANIFEST_IMPLEMENTATION
];
4565 * this code should only be called after obtaining the
4566 * ResourceInfo and handling the other cases.
4568 g_assert ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
);
4569 file_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
4571 module
= mono_image_load_file_for_image (assembly
->assembly
->image
, file_idx
);
4576 module
= assembly
->assembly
->image
;
4578 mono_gc_wbarrier_generic_store (ref_module
, (MonoObject
*) mono_module_get_object (mono_domain_get (), module
));
4580 return (void*)mono_image_get_resource (module
, cols
[MONO_MANIFEST_OFFSET
], (guint32
*)size
);
4584 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoManifestResourceInfo
*info
)
4586 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4588 guint32 cols
[MONO_MANIFEST_SIZE
];
4589 guint32 file_cols
[MONO_FILE_SIZE
];
4593 MONO_ARCH_SAVE_REGS
;
4595 n
= mono_string_to_utf8 (name
);
4596 for (i
= 0; i
< table
->rows
; ++i
) {
4597 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
4598 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
4599 if (strcmp (val
, n
) == 0)
4603 if (i
== table
->rows
)
4606 if (!cols
[MONO_MANIFEST_IMPLEMENTATION
]) {
4607 info
->location
= RESOURCE_LOCATION_EMBEDDED
| RESOURCE_LOCATION_IN_MANIFEST
;
4610 switch (cols
[MONO_MANIFEST_IMPLEMENTATION
] & MONO_IMPLEMENTATION_MASK
) {
4611 case MONO_IMPLEMENTATION_FILE
:
4612 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
4613 table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
4614 mono_metadata_decode_row (table
, i
- 1, file_cols
, MONO_FILE_SIZE
);
4615 val
= mono_metadata_string_heap (assembly
->assembly
->image
, file_cols
[MONO_FILE_NAME
]);
4616 MONO_OBJECT_SETREF (info
, filename
, mono_string_new (mono_object_domain (assembly
), val
));
4617 if (file_cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
4620 info
->location
= RESOURCE_LOCATION_EMBEDDED
;
4623 case MONO_IMPLEMENTATION_ASSEMBLYREF
:
4624 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
4625 mono_assembly_load_reference (assembly
->assembly
->image
, i
- 1);
4626 if (assembly
->assembly
->image
->references
[i
- 1] == (gpointer
)-1) {
4627 char *msg
= g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i
- 1, assembly
->assembly
->image
->name
);
4628 MonoException
*ex
= mono_get_exception_file_not_found2 (msg
, NULL
);
4630 mono_raise_exception (ex
);
4632 MONO_OBJECT_SETREF (info
, assembly
, mono_assembly_get_object (mono_domain_get (), assembly
->assembly
->image
->references
[i
- 1]));
4634 /* Obtain info recursively */
4635 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info
->assembly
, name
, info
);
4636 info
->location
|= RESOURCE_LOCATION_ANOTHER_ASSEMBLY
;
4639 case MONO_IMPLEMENTATION_EXP_TYPE
:
4640 g_assert_not_reached ();
4649 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoBoolean resource_modules
)
4651 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
4652 MonoArray
*result
= NULL
;
4657 MONO_ARCH_SAVE_REGS
;
4659 /* check hash if needed */
4661 n
= mono_string_to_utf8 (name
);
4662 for (i
= 0; i
< table
->rows
; ++i
) {
4663 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
4664 if (strcmp (val
, n
) == 0) {
4667 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
4668 fn
= mono_string_new (mono_object_domain (assembly
), n
);
4670 return (MonoObject
*)fn
;
4678 for (i
= 0; i
< table
->rows
; ++i
) {
4679 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
))
4683 result
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, count
);
4686 for (i
= 0; i
< table
->rows
; ++i
) {
4687 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
4688 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
4689 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
4690 mono_array_setref (result
, count
, mono_string_new (mono_object_domain (assembly
), n
));
4695 return (MonoObject
*)result
;
4699 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly
*assembly
)
4701 MonoDomain
*domain
= mono_domain_get();
4704 int i
, j
, file_count
= 0;
4705 MonoImage
**modules
;
4706 guint32 module_count
, real_module_count
;
4707 MonoTableInfo
*table
;
4708 guint32 cols
[MONO_FILE_SIZE
];
4709 MonoImage
*image
= assembly
->assembly
->image
;
4711 g_assert (image
!= NULL
);
4712 g_assert (!assembly
->assembly
->dynamic
);
4714 table
= &image
->tables
[MONO_TABLE_FILE
];
4715 file_count
= table
->rows
;
4717 modules
= image
->modules
;
4718 module_count
= image
->module_count
;
4720 real_module_count
= 0;
4721 for (i
= 0; i
< module_count
; ++i
)
4723 real_module_count
++;
4725 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Module");
4726 res
= mono_array_new (domain
, klass
, 1 + real_module_count
+ file_count
);
4728 mono_array_setref (res
, 0, mono_module_get_object (domain
, image
));
4730 for (i
= 0; i
< module_count
; ++i
)
4732 mono_array_setref (res
, j
, mono_module_get_object (domain
, modules
[i
]));
4736 for (i
= 0; i
< file_count
; ++i
, ++j
) {
4737 mono_metadata_decode_row (table
, i
, cols
, MONO_FILE_SIZE
);
4738 if (cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
4739 mono_array_setref (res
, j
, mono_module_file_get_object (domain
, image
, i
));
4741 MonoImage
*m
= mono_image_load_file_for_image (image
, i
+ 1);
4743 MonoString
*fname
= mono_string_new (mono_domain_get (), mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]));
4744 mono_raise_exception (mono_get_exception_file_not_found2 (NULL
, fname
));
4746 mono_array_setref (res
, j
, mono_module_get_object (domain
, m
));
4753 static MonoReflectionMethod
*
4754 ves_icall_GetCurrentMethod (void)
4756 MonoMethod
*m
= mono_method_get_last_managed ();
4758 while (m
->is_inflated
)
4759 m
= ((MonoMethodInflated
*)m
)->declaring
;
4761 return mono_method_get_object (mono_domain_get (), m
, NULL
);
4766 mono_method_get_equivalent_method (MonoMethod
*method
, MonoClass
*klass
)
4769 if (method
->is_inflated
&& ((MonoMethodInflated
*)method
)->context
.method_inst
) {
4770 MonoMethodInflated
*inflated
= (MonoMethodInflated
*)method
;
4771 //method is inflated, we should inflate it on the other class
4772 MonoGenericContext ctx
;
4773 ctx
.method_inst
= inflated
->context
.method_inst
;
4774 ctx
.class_inst
= inflated
->context
.class_inst
;
4775 if (klass
->generic_class
)
4776 ctx
.class_inst
= klass
->generic_class
->context
.class_inst
;
4777 else if (klass
->generic_container
)
4778 ctx
.class_inst
= klass
->generic_container
->context
.class_inst
;
4779 return mono_class_inflate_generic_method_full (inflated
->declaring
, klass
, &ctx
);
4782 mono_class_setup_methods (method
->klass
);
4783 if (method
->klass
->exception_type
)
4785 for (i
= 0; i
< method
->klass
->method
.count
; ++i
) {
4786 if (method
->klass
->methods
[i
] == method
) {
4791 mono_class_setup_methods (klass
);
4792 if (klass
->exception_type
)
4794 g_assert (offset
>= 0 && offset
< klass
->method
.count
);
4795 return klass
->methods
[offset
];
4798 static MonoReflectionMethod
*
4799 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod
*method
, MonoType
*type
)
4803 klass
= mono_class_from_mono_type (type
);
4804 if (mono_class_get_generic_type_definition (method
->klass
) != mono_class_get_generic_type_definition (klass
))
4806 if (method
->klass
!= klass
) {
4807 method
= mono_method_get_equivalent_method (method
, klass
);
4812 klass
= method
->klass
;
4813 return mono_method_get_object (mono_domain_get (), method
, klass
);
4816 static MonoReflectionMethod
*
4817 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod
*method
)
4819 return mono_method_get_object (mono_domain_get (), method
, NULL
);
4822 static MonoReflectionMethodBody
*
4823 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod
*method
)
4825 return mono_method_body_get_object (mono_domain_get (), method
);
4828 static MonoReflectionAssembly
*
4829 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4831 MonoMethod
*dest
= NULL
;
4833 MONO_ARCH_SAVE_REGS
;
4835 mono_stack_walk_no_il (get_executing
, &dest
);
4836 return mono_assembly_get_object (mono_domain_get (), dest
->klass
->image
->assembly
);
4840 static MonoReflectionAssembly
*
4841 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4843 MonoDomain
* domain
= mono_domain_get ();
4845 MONO_ARCH_SAVE_REGS
;
4847 if (!domain
->entry_assembly
)
4850 return mono_assembly_get_object (domain
, domain
->entry_assembly
);
4853 static MonoReflectionAssembly
*
4854 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4859 MONO_ARCH_SAVE_REGS
;
4862 mono_stack_walk_no_il (get_executing
, &dest
);
4864 mono_stack_walk_no_il (get_caller
, &dest
);
4867 return mono_assembly_get_object (mono_domain_get (), dest
->klass
->image
->assembly
);
4871 ves_icall_System_MonoType_getFullName (MonoReflectionType
*object
, gboolean full_name
,
4872 gboolean assembly_qualified
)
4874 MonoDomain
*domain
= mono_object_domain (object
);
4875 MonoTypeNameFormat format
;
4879 MONO_ARCH_SAVE_REGS
;
4881 format
= assembly_qualified
?
4882 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
:
4883 MONO_TYPE_NAME_FORMAT_FULL_NAME
;
4885 format
= MONO_TYPE_NAME_FORMAT_REFLECTION
;
4887 name
= mono_type_get_name_full (object
->type
, format
);
4891 if (full_name
&& (object
->type
->type
== MONO_TYPE_VAR
|| object
->type
->type
== MONO_TYPE_MVAR
)) {
4896 res
= mono_string_new (domain
, name
);
4903 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType
*this)
4905 MonoClass
*klass
= mono_class_from_mono_type (this->type
);
4906 return mono_security_core_clr_class_level (klass
);
4910 fill_reflection_assembly_name (MonoDomain
*domain
, MonoReflectionAssemblyName
*aname
, MonoAssemblyName
*name
, const char *absolute
, gboolean by_default_version
, gboolean default_publickey
, gboolean default_token
)
4912 static MonoMethod
*create_culture
= NULL
;
4915 const char *pkey_ptr
;
4917 MonoBoolean assembly_ref
= 0;
4919 MONO_ARCH_SAVE_REGS
;
4921 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, name
->name
));
4922 aname
->major
= name
->major
;
4923 aname
->minor
= name
->minor
;
4924 aname
->build
= name
->build
;
4925 aname
->flags
= name
->flags
;
4926 aname
->revision
= name
->revision
;
4927 aname
->hashalg
= name
->hash_alg
;
4928 aname
->versioncompat
= 1; /* SameMachine (default) */
4930 if (by_default_version
)
4931 MONO_OBJECT_SETREF (aname
, version
, create_version (domain
, name
->major
, name
->minor
, name
->build
, name
->revision
));
4934 if (absolute
!= NULL
&& *absolute
!= '\0') {
4935 const gchar
*prepend
= "file://";
4938 codebase
= g_strdup (absolute
);
4943 for (i
= strlen (codebase
) - 1; i
>= 0; i
--)
4944 if (codebase
[i
] == '\\')
4947 if (*codebase
== '/' && *(codebase
+ 1) == '/') {
4950 prepend
= "file:///";
4954 result
= g_strconcat (prepend
, codebase
, NULL
);
4960 MONO_OBJECT_SETREF (aname
, codebase
, mono_string_new (domain
, codebase
));
4964 if (!create_culture
) {
4965 MonoMethodDesc
*desc
= mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4966 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4967 g_assert (create_culture
);
4968 mono_method_desc_free (desc
);
4971 if (name
->culture
) {
4972 args
[0] = mono_string_new (domain
, name
->culture
);
4973 args
[1] = &assembly_ref
;
4974 MONO_OBJECT_SETREF (aname
, cultureInfo
, mono_runtime_invoke (create_culture
, NULL
, args
, NULL
));
4977 if (name
->public_key
) {
4978 pkey_ptr
= (char*)name
->public_key
;
4979 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
4981 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4982 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
4983 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
4984 } else if (default_publickey
) {
4985 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
4986 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
4989 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4990 if (name
->public_key_token
[0]) {
4994 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 8));
4995 p
= mono_array_addr (aname
->keyToken
, char, 0);
4997 for (i
= 0, j
= 0; i
< 8; i
++) {
4998 *p
= g_ascii_xdigit_value (name
->public_key_token
[j
++]) << 4;
4999 *p
|= g_ascii_xdigit_value (name
->public_key_token
[j
++]);
5002 } else if (default_token
) {
5003 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
5008 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly
*assembly
)
5010 MonoDomain
*domain
= mono_object_domain (assembly
);
5011 MonoAssembly
*mass
= assembly
->assembly
;
5015 name
= g_strdup_printf (
5016 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5018 mass
->aname
.major
, mass
->aname
.minor
, mass
->aname
.build
, mass
->aname
.revision
,
5019 mass
->aname
.culture
&& *mass
->aname
.culture
? mass
->aname
.culture
: "neutral",
5020 mass
->aname
.public_key_token
[0] ? (char *)mass
->aname
.public_key_token
: "null",
5021 (mass
->aname
.flags
& ASSEMBLYREF_RETARGETABLE_FLAG
) ? ", Retargetable=Yes" : "");
5023 res
= mono_string_new (domain
, name
);
5030 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly
*assembly
, MonoReflectionAssemblyName
*aname
)
5033 MonoAssembly
*mass
= assembly
->assembly
;
5035 MONO_ARCH_SAVE_REGS
;
5037 if (g_path_is_absolute (mass
->image
->name
)) {
5038 fill_reflection_assembly_name (mono_object_domain (assembly
),
5039 aname
, &mass
->aname
, mass
->image
->name
, TRUE
,
5043 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
5045 fill_reflection_assembly_name (mono_object_domain (assembly
),
5046 aname
, &mass
->aname
, absolute
, TRUE
, TRUE
,
5053 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString
*fname
, MonoReflectionAssemblyName
*aname
)
5056 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
5059 MonoAssemblyName name
;
5062 MONO_ARCH_SAVE_REGS
;
5064 filename
= mono_string_to_utf8 (fname
);
5066 dirname
= g_path_get_dirname (filename
);
5067 replace_shadow_path (mono_domain_get (), dirname
, &filename
);
5070 image
= mono_image_open (filename
, &status
);
5076 if (status
== MONO_IMAGE_IMAGE_INVALID
)
5077 exc
= mono_get_exception_bad_image_format2 (NULL
, fname
);
5079 exc
= mono_get_exception_file_not_found2 (NULL
, fname
);
5080 mono_raise_exception (exc
);
5083 res
= mono_assembly_fill_assembly_name (image
, &name
);
5085 mono_image_close (image
);
5087 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5090 fill_reflection_assembly_name (mono_domain_get (), aname
, &name
, filename
,
5094 mono_image_close (image
);
5098 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly
*assembly
,
5099 char **minimum
, guint32
*minLength
, char **optional
, guint32
*optLength
, char **refused
, guint32
*refLength
)
5101 MonoBoolean result
= FALSE
;
5102 MonoDeclSecurityEntry entry
;
5104 /* SecurityAction.RequestMinimum */
5105 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQMIN
, &entry
)) {
5106 *minimum
= entry
.blob
;
5107 *minLength
= entry
.size
;
5110 /* SecurityAction.RequestOptional */
5111 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQOPT
, &entry
)) {
5112 *optional
= entry
.blob
;
5113 *optLength
= entry
.size
;
5116 /* SecurityAction.RequestRefuse */
5117 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQREFUSE
, &entry
)) {
5118 *refused
= entry
.blob
;
5119 *refLength
= entry
.size
;
5127 mono_module_get_types (MonoDomain
*domain
, MonoImage
*image
, MonoArray
**exceptions
, MonoBoolean exportedOnly
)
5131 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_TYPEDEF
];
5133 guint32 attrs
, visibility
;
5135 /* we start the count from 1 because we skip the special type <Module> */
5138 for (i
= 1; i
< tdef
->rows
; ++i
) {
5139 attrs
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEDEF_FLAGS
);
5140 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5141 if (visibility
== TYPE_ATTRIBUTE_PUBLIC
|| visibility
== TYPE_ATTRIBUTE_NESTED_PUBLIC
)
5145 count
= tdef
->rows
- 1;
5147 res
= mono_array_new (domain
, mono_defaults
.monotype_class
, count
);
5148 *exceptions
= mono_array_new (domain
, mono_defaults
.exception_class
, count
);
5150 for (i
= 1; i
< tdef
->rows
; ++i
) {
5151 attrs
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEDEF_FLAGS
);
5152 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5153 if (!exportedOnly
|| (visibility
== TYPE_ATTRIBUTE_PUBLIC
|| visibility
== TYPE_ATTRIBUTE_NESTED_PUBLIC
)) {
5154 klass
= mono_class_get (image
, (i
+ 1) | MONO_TOKEN_TYPE_DEF
);
5156 mono_array_setref (res
, count
, mono_type_get_object (domain
, &klass
->byval_arg
));
5158 MonoLoaderError
*error
;
5161 error
= mono_loader_get_last_error ();
5162 g_assert (error
!= NULL
);
5164 ex
= mono_loader_error_prepare_exception (error
);
5165 mono_array_setref (*exceptions
, count
, ex
);
5167 if (mono_loader_get_last_error ())
5168 mono_loader_clear_error ();
5177 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly
*assembly
, MonoBoolean exportedOnly
)
5179 MonoArray
*res
= NULL
;
5180 MonoArray
*exceptions
= NULL
;
5181 MonoImage
*image
= NULL
;
5182 MonoTableInfo
*table
= NULL
;
5185 int i
, len
, ex_count
;
5187 MONO_ARCH_SAVE_REGS
;
5189 domain
= mono_object_domain (assembly
);
5191 g_assert (!assembly
->assembly
->dynamic
);
5192 image
= assembly
->assembly
->image
;
5193 table
= &image
->tables
[MONO_TABLE_FILE
];
5194 res
= mono_module_get_types (domain
, image
, &exceptions
, exportedOnly
);
5196 /* Append data from all modules in the assembly */
5197 for (i
= 0; i
< table
->rows
; ++i
) {
5198 if (!(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
5199 MonoImage
*loaded_image
= mono_assembly_load_module (image
->assembly
, i
+ 1);
5202 MonoArray
*res2
= mono_module_get_types (domain
, loaded_image
, &ex2
, exportedOnly
);
5203 /* Append the new types to the end of the array */
5204 if (mono_array_length (res2
) > 0) {
5206 MonoArray
*res3
, *ex3
;
5208 len1
= mono_array_length (res
);
5209 len2
= mono_array_length (res2
);
5211 res3
= mono_array_new (domain
, mono_defaults
.monotype_class
, len1
+ len2
);
5212 mono_array_memcpy_refs (res3
, 0, res
, 0, len1
);
5213 mono_array_memcpy_refs (res3
, len1
, res2
, 0, len2
);
5216 ex3
= mono_array_new (domain
, mono_defaults
.monotype_class
, len1
+ len2
);
5217 mono_array_memcpy_refs (ex3
, 0, exceptions
, 0, len1
);
5218 mono_array_memcpy_refs (ex3
, len1
, ex2
, 0, len2
);
5225 /* the ReflectionTypeLoadException must have all the types (Types property),
5226 * NULL replacing types which throws an exception. The LoaderException must
5227 * contain all exceptions for NULL items.
5230 len
= mono_array_length (res
);
5233 for (i
= 0; i
< len
; i
++) {
5234 MonoReflectionType
*t
= mono_array_get (res
, gpointer
, i
);
5238 klass
= mono_type_get_class (t
->type
);
5239 if ((klass
!= NULL
) && klass
->exception_type
) {
5240 /* keep the class in the list */
5241 list
= g_list_append (list
, klass
);
5242 /* and replace Type with NULL */
5243 mono_array_setref (res
, i
, NULL
);
5250 if (list
|| ex_count
) {
5252 MonoException
*exc
= NULL
;
5253 MonoArray
*exl
= NULL
;
5254 int j
, length
= g_list_length (list
) + ex_count
;
5256 mono_loader_clear_error ();
5258 exl
= mono_array_new (domain
, mono_defaults
.exception_class
, length
);
5259 /* Types for which mono_class_get () succeeded */
5260 for (i
= 0, tmp
= list
; tmp
; i
++, tmp
= tmp
->next
) {
5261 MonoException
*exc
= mono_class_get_exception_for_failure (tmp
->data
);
5262 mono_array_setref (exl
, i
, exc
);
5264 /* Types for which it don't */
5265 for (j
= 0; j
< mono_array_length (exceptions
); ++j
) {
5266 MonoException
*exc
= mono_array_get (exceptions
, MonoException
*, j
);
5268 g_assert (i
< length
);
5269 mono_array_setref (exl
, i
, exc
);
5276 exc
= mono_get_exception_reflection_type_load (res
, exl
);
5277 mono_loader_clear_error ();
5278 mono_raise_exception (exc
);
5285 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName
*name
, MonoString
*assname
)
5287 MonoAssemblyName aname
;
5288 MonoDomain
*domain
= mono_object_domain (name
);
5290 gboolean is_version_defined
;
5291 gboolean is_token_defined
;
5293 aname
.public_key
= NULL
;
5294 val
= mono_string_to_utf8 (assname
);
5295 if (!mono_assembly_name_parse_full (val
, &aname
, TRUE
, &is_version_defined
, &is_token_defined
)) {
5296 g_free ((guint8
*) aname
.public_key
);
5301 fill_reflection_assembly_name (domain
, name
, &aname
, "", is_version_defined
,
5302 FALSE
, is_token_defined
);
5304 mono_assembly_name_free (&aname
);
5305 g_free ((guint8
*) aname
.public_key
);
5311 static MonoReflectionType
*
5312 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule
*module
)
5314 MonoDomain
*domain
= mono_object_domain (module
);
5317 MONO_ARCH_SAVE_REGS
;
5319 g_assert (module
->image
);
5321 if (module
->image
->dynamic
&& ((MonoDynamicImage
*)(module
->image
))->initial_image
)
5322 /* These images do not have a global type */
5325 klass
= mono_class_get (module
->image
, 1 | MONO_TOKEN_TYPE_DEF
);
5326 return mono_type_get_object (domain
, &klass
->byval_arg
);
5330 ves_icall_System_Reflection_Module_Close (MonoReflectionModule
*module
)
5332 /*if (module->image)
5333 mono_image_close (module->image);*/
5337 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule
*module
)
5339 MonoDomain
*domain
= mono_object_domain (module
);
5341 MONO_ARCH_SAVE_REGS
;
5343 g_assert (module
->image
);
5344 return mono_string_new (domain
, module
->image
->guid
);
5348 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule
*module
)
5351 if (module
->image
&& module
->image
->is_module_handle
)
5352 return module
->image
->raw_data
;
5355 return (gpointer
) (-1);
5359 ves_icall_System_Reflection_Module_GetPEKind (MonoImage
*image
, gint32
*pe_kind
, gint32
*machine
)
5361 if (image
->dynamic
) {
5362 MonoDynamicImage
*dyn
= (MonoDynamicImage
*)image
;
5363 *pe_kind
= dyn
->pe_kind
;
5364 *machine
= dyn
->machine
;
5367 *pe_kind
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_cli_header
.ch_flags
& 0x3;
5368 *machine
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_header
.coff
.coff_machine
;
5373 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage
*image
)
5375 return (image
->md_version_major
<< 16) | (image
->md_version_minor
);
5379 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule
*module
)
5381 MonoArray
*exceptions
;
5384 MONO_ARCH_SAVE_REGS
;
5387 return mono_array_new (mono_object_domain (module
), mono_defaults
.monotype_class
, 0);
5389 MonoArray
*res
= mono_module_get_types (mono_object_domain (module
), module
->image
, &exceptions
, FALSE
);
5390 for (i
= 0; i
< mono_array_length (exceptions
); ++i
) {
5391 MonoException
*ex
= mono_array_get (exceptions
, MonoException
*, i
);
5393 mono_raise_exception (ex
);
5400 mono_metadata_memberref_is_method (MonoImage
*image
, guint32 token
)
5402 guint32 cols
[MONO_MEMBERREF_SIZE
];
5404 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
5405 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
5406 mono_metadata_decode_blob_size (sig
, &sig
);
5407 return (*sig
!= 0x6);
5411 init_generic_context_from_args (MonoGenericContext
*context
, MonoArray
*type_args
, MonoArray
*method_args
)
5414 context
->class_inst
= mono_metadata_get_generic_inst (mono_array_length (type_args
),
5415 mono_array_addr (type_args
, MonoType
*, 0));
5417 context
->class_inst
= NULL
;
5419 context
->method_inst
= mono_metadata_get_generic_inst (mono_array_length (method_args
),
5420 mono_array_addr (method_args
, MonoType
*, 0));
5422 context
->method_inst
= NULL
;
5426 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5429 int table
= mono_metadata_token_table (token
);
5430 int index
= mono_metadata_token_index (token
);
5431 MonoGenericContext context
;
5433 *error
= ResolveTokenError_Other
;
5435 /* Validate token */
5436 if ((table
!= MONO_TABLE_TYPEDEF
) && (table
!= MONO_TABLE_TYPEREF
) &&
5437 (table
!= MONO_TABLE_TYPESPEC
)) {
5438 *error
= ResolveTokenError_BadTable
;
5442 if (image
->dynamic
) {
5443 if (type_args
|| method_args
)
5444 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5445 klass
= mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5448 return &klass
->byval_arg
;
5451 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5452 *error
= ResolveTokenError_OutOfRange
;
5456 init_generic_context_from_args (&context
, type_args
, method_args
);
5457 klass
= mono_class_get_full (image
, token
, &context
);
5459 if (mono_loader_get_last_error ())
5460 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5463 return &klass
->byval_arg
;
5469 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5471 int table
= mono_metadata_token_table (token
);
5472 int index
= mono_metadata_token_index (token
);
5473 MonoGenericContext context
;
5476 *error
= ResolveTokenError_Other
;
5478 /* Validate token */
5479 if ((table
!= MONO_TABLE_METHOD
) && (table
!= MONO_TABLE_METHODSPEC
) &&
5480 (table
!= MONO_TABLE_MEMBERREF
)) {
5481 *error
= ResolveTokenError_BadTable
;
5485 if (image
->dynamic
) {
5486 if (type_args
|| method_args
)
5487 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5488 /* FIXME: validate memberref token type */
5489 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5492 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5493 *error
= ResolveTokenError_OutOfRange
;
5496 if ((table
== MONO_TABLE_MEMBERREF
) && (!mono_metadata_memberref_is_method (image
, token
))) {
5497 *error
= ResolveTokenError_BadTable
;
5501 init_generic_context_from_args (&context
, type_args
, method_args
);
5502 method
= mono_get_method_full (image
, token
, NULL
, &context
);
5504 if (mono_loader_get_last_error ())
5505 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5511 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*error
)
5513 int index
= mono_metadata_token_index (token
);
5515 *error
= ResolveTokenError_Other
;
5517 /* Validate token */
5518 if (mono_metadata_token_code (token
) != MONO_TOKEN_STRING
) {
5519 *error
= ResolveTokenError_BadTable
;
5524 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5526 if ((index
<= 0) || (index
>= image
->heap_us
.size
)) {
5527 *error
= ResolveTokenError_OutOfRange
;
5531 /* FIXME: What to do if the index points into the middle of a string ? */
5533 return mono_ldstr (mono_domain_get (), image
, index
);
5536 static MonoClassField
*
5537 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5540 int table
= mono_metadata_token_table (token
);
5541 int index
= mono_metadata_token_index (token
);
5542 MonoGenericContext context
;
5543 MonoClassField
*field
;
5545 *error
= ResolveTokenError_Other
;
5547 /* Validate token */
5548 if ((table
!= MONO_TABLE_FIELD
) && (table
!= MONO_TABLE_MEMBERREF
)) {
5549 *error
= ResolveTokenError_BadTable
;
5553 if (image
->dynamic
) {
5554 if (type_args
|| method_args
)
5555 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5556 /* FIXME: validate memberref token type */
5557 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5560 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5561 *error
= ResolveTokenError_OutOfRange
;
5564 if ((table
== MONO_TABLE_MEMBERREF
) && (mono_metadata_memberref_is_method (image
, token
))) {
5565 *error
= ResolveTokenError_BadTable
;
5569 init_generic_context_from_args (&context
, type_args
, method_args
);
5570 field
= mono_field_from_token (image
, token
, &klass
, &context
);
5572 if (mono_loader_get_last_error ())
5573 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5580 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5582 int table
= mono_metadata_token_table (token
);
5584 *error
= ResolveTokenError_Other
;
5587 case MONO_TABLE_TYPEDEF
:
5588 case MONO_TABLE_TYPEREF
:
5589 case MONO_TABLE_TYPESPEC
: {
5590 MonoType
*t
= ves_icall_System_Reflection_Module_ResolveTypeToken (image
, token
, type_args
, method_args
, error
);
5592 return (MonoObject
*)mono_type_get_object (mono_domain_get (), t
);
5596 case MONO_TABLE_METHOD
:
5597 case MONO_TABLE_METHODSPEC
: {
5598 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
5600 return (MonoObject
*)mono_method_get_object (mono_domain_get (), m
, m
->klass
);
5604 case MONO_TABLE_FIELD
: {
5605 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
5607 return (MonoObject
*)mono_field_get_object (mono_domain_get (), f
->parent
, f
);
5611 case MONO_TABLE_MEMBERREF
:
5612 if (mono_metadata_memberref_is_method (image
, token
)) {
5613 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
5615 return (MonoObject
*)mono_method_get_object (mono_domain_get (), m
, m
->klass
);
5620 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
5622 return (MonoObject
*)mono_field_get_object (mono_domain_get (), f
->parent
, f
);
5629 *error
= ResolveTokenError_BadTable
;
5636 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*error
)
5638 int table
= mono_metadata_token_table (token
);
5639 int idx
= mono_metadata_token_index (token
);
5640 MonoTableInfo
*tables
= image
->tables
;
5645 *error
= ResolveTokenError_OutOfRange
;
5647 /* FIXME: Support other tables ? */
5648 if (table
!= MONO_TABLE_STANDALONESIG
)
5654 if ((idx
== 0) || (idx
> tables
[MONO_TABLE_STANDALONESIG
].rows
))
5657 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
5659 ptr
= mono_metadata_blob_heap (image
, sig
);
5660 len
= mono_metadata_decode_blob_size (ptr
, &ptr
);
5662 res
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, len
);
5663 memcpy (mono_array_addr (res
, guint8
, 0), ptr
, len
);
5667 static MonoReflectionType
*
5668 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder
*tb
, MonoString
*smodifiers
)
5671 int isbyref
= 0, rank
;
5672 char *str
= mono_string_to_utf8 (smodifiers
);
5675 MONO_ARCH_SAVE_REGS
;
5677 klass
= mono_class_from_mono_type (tb
->type
.type
);
5679 /* logic taken from mono_reflection_parse_type(): keep in sync */
5683 if (isbyref
) { /* only one level allowed by the spec */
5690 return mono_type_get_object (mono_object_domain (tb
), &klass
->this_arg
);
5693 klass
= mono_ptr_class_get (&klass
->byval_arg
);
5694 mono_class_init (klass
);
5705 else if (*p
!= '*') { /* '*' means unknown lower bound */
5716 klass
= mono_array_class_get (klass
, rank
);
5717 mono_class_init (klass
);
5724 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
5728 ves_icall_Type_IsArrayImpl (MonoReflectionType
*t
)
5733 MONO_ARCH_SAVE_REGS
;
5736 res
= !type
->byref
&& (type
->type
== MONO_TYPE_ARRAY
|| type
->type
== MONO_TYPE_SZARRAY
);
5741 static MonoReflectionType
*
5742 ves_icall_Type_make_array_type (MonoReflectionType
*type
, int rank
)
5744 MonoClass
*klass
, *aklass
;
5746 MONO_ARCH_SAVE_REGS
;
5748 klass
= mono_class_from_mono_type (type
->type
);
5749 if (rank
== 0) //single dimentional array
5750 aklass
= mono_array_class_get (klass
, 1);
5752 aklass
= mono_bounded_array_class_get (klass
, rank
, TRUE
);
5754 return mono_type_get_object (mono_object_domain (type
), &aklass
->byval_arg
);
5757 static MonoReflectionType
*
5758 ves_icall_Type_make_byref_type (MonoReflectionType
*type
)
5762 MONO_ARCH_SAVE_REGS
;
5764 klass
= mono_class_from_mono_type (type
->type
);
5766 return mono_type_get_object (mono_object_domain (type
), &klass
->this_arg
);
5769 static MonoReflectionType
*
5770 ves_icall_Type_MakePointerType (MonoReflectionType
*type
)
5774 MONO_ARCH_SAVE_REGS
;
5776 pklass
= mono_ptr_class_get (type
->type
);
5778 return mono_type_get_object (mono_object_domain (type
), &pklass
->byval_arg
);
5782 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType
*type
, MonoObject
*target
,
5783 MonoReflectionMethod
*info
, MonoBoolean throwOnBindFailure
)
5785 MonoClass
*delegate_class
= mono_class_from_mono_type (type
->type
);
5786 MonoObject
*delegate
;
5788 MonoMethod
*method
= info
->method
;
5790 MONO_ARCH_SAVE_REGS
;
5792 mono_assert (delegate_class
->parent
== mono_defaults
.multicastdelegate_class
);
5794 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
) {
5795 if (!mono_security_core_clr_ensure_delegate_creation (method
, throwOnBindFailure
))
5799 delegate
= mono_object_new (mono_object_domain (type
), delegate_class
);
5801 if (method
->dynamic
) {
5802 /* Creating a trampoline would leak memory */
5803 func
= mono_compile_method (method
);
5805 func
= mono_create_ftnptr (mono_domain_get (),
5806 mono_runtime_create_jump_trampoline (mono_domain_get (), method
, TRUE
));
5809 mono_delegate_ctor_with_method (delegate
, target
, func
, method
);
5815 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate
*this)
5817 /* Reset the invoke impl to the default one */
5818 this->invoke_impl
= mono_runtime_create_delegate_trampoline (this->object
.vtable
->klass
);
5822 * Magic number to convert a time which is relative to
5823 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5825 #define EPOCH_ADJUST ((guint64)62135596800LL)
5828 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5830 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5833 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5835 convert_to_absolute_date(SYSTEMTIME
*date
)
5837 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5838 static int days_in_month
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5839 static int leap_days_in_month
[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5840 /* from the calendar FAQ */
5841 int a
= (14 - date
->wMonth
) / 12;
5842 int y
= date
->wYear
- a
;
5843 int m
= date
->wMonth
+ 12 * a
- 2;
5844 int d
= (1 + y
+ y
/4 - y
/100 + y
/400 + (31*m
)/12) % 7;
5846 /* d is now the day of the week for the first of the month (0 == Sunday) */
5848 int day_of_week
= date
->wDayOfWeek
;
5850 /* set day_in_month to the first day in the month which falls on day_of_week */
5851 int day_in_month
= 1 + (day_of_week
- d
);
5852 if (day_in_month
<= 0)
5855 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5856 date
->wDay
= day_in_month
+ (date
->wDay
- 1) * 7;
5857 if (date
->wDay
> (IS_LEAP(date
->wYear
) ? leap_days_in_month
[date
->wMonth
- 1] : days_in_month
[date
->wMonth
- 1]))
5864 * Return's the offset from GMT of a local time.
5866 * tm is a local time
5867 * t is the same local time as seconds.
5870 gmt_offset(struct tm
*tm
, time_t t
)
5872 #if defined (HAVE_TM_GMTOFF)
5873 return tm
->tm_gmtoff
;
5878 g
.tm_isdst
= tm
->tm_isdst
;
5880 return (int)difftime(t
, t2
);
5885 * This is heavily based on zdump.c from glibc 2.2.
5887 * * data[0]: start of daylight saving time (in DateTime ticks).
5888 * * data[1]: end of daylight saving time (in DateTime ticks).
5889 * * data[2]: utcoffset (in TimeSpan ticks).
5890 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5891 * * name[0]: name of this timezone when not daylight saving.
5892 * * name[1]: name of this timezone when daylight saving.
5894 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5895 * the class library allows years between 1 and 9999.
5897 * Returns true on success and zero on failure.
5900 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year
, MonoArray
**data
, MonoArray
**names
)
5903 MonoDomain
*domain
= mono_domain_get ();
5904 struct tm start
, tt
;
5908 int is_daylight
= 0, day
;
5911 MONO_ARCH_SAVE_REGS
;
5913 MONO_CHECK_ARG_NULL (data
);
5914 MONO_CHECK_ARG_NULL (names
);
5916 mono_gc_wbarrier_generic_store (data
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.int64_class
, 4));
5917 mono_gc_wbarrier_generic_store (names
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.string_class
, 2));
5920 * no info is better than crashing: we'll need our own tz data
5921 * to make this work properly, anyway. The range is probably
5922 * reduced to 1970 .. 2037 because that is what mktime is
5923 * guaranteed to support (we get into an infinite loop
5927 memset (&start
, 0, sizeof (start
));
5930 start
.tm_year
= year
-1900;
5932 t
= mktime (&start
);
5934 if ((year
< 1970) || (year
> 2037) || (t
== -1)) {
5936 tt
= *localtime (&t
);
5937 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5938 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5939 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5943 gmtoff
= gmt_offset (&start
, t
);
5945 /* For each day of the year, calculate the tm_gmtoff. */
5946 for (day
= 0; day
< 365; day
++) {
5949 tt
= *localtime (&t
);
5951 /* Daylight saving starts or ends here. */
5952 if (gmt_offset (&tt
, t
) != gmtoff
) {
5956 /* Try to find the exact hour when daylight saving starts/ends. */
5960 tt1
= *localtime (&t1
);
5961 } while (gmt_offset (&tt1
, t1
) != gmtoff
);
5963 /* Try to find the exact minute when daylight saving starts/ends. */
5966 tt1
= *localtime (&t1
);
5967 } while (gmt_offset (&tt1
, t1
) == gmtoff
);
5969 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5971 /* Write data, if we're already in daylight saving, we're done. */
5973 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5974 mono_array_set ((*data
), gint64
, 1, ((gint64
)t1
+ EPOCH_ADJUST
) * 10000000L);
5977 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5978 mono_array_set ((*data
), gint64
, 0, ((gint64
)t1
+ EPOCH_ADJUST
) * 10000000L);
5982 /* This is only set once when we enter daylight saving. */
5983 mono_array_set ((*data
), gint64
, 2, (gint64
)gmtoff
* 10000000L);
5984 mono_array_set ((*data
), gint64
, 3, (gint64
)(gmt_offset (&tt
, t
) - gmtoff
) * 10000000L);
5986 gmtoff
= gmt_offset (&tt
, t
);
5991 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5992 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5993 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5994 mono_array_set ((*data
), gint64
, 0, 0);
5995 mono_array_set ((*data
), gint64
, 1, 0);
5996 mono_array_set ((*data
), gint64
, 2, (gint64
) gmtoff
* 10000000L);
5997 mono_array_set ((*data
), gint64
, 3, 0);
6002 MonoDomain
*domain
= mono_domain_get ();
6003 TIME_ZONE_INFORMATION tz_info
;
6008 tz_id
= GetTimeZoneInformation (&tz_info
);
6009 if (tz_id
== TIME_ZONE_ID_INVALID
)
6012 MONO_CHECK_ARG_NULL (data
);
6013 MONO_CHECK_ARG_NULL (names
);
6015 mono_gc_wbarrier_generic_store (data
, mono_array_new (domain
, mono_defaults
.int64_class
, 4));
6016 mono_gc_wbarrier_generic_store (names
, mono_array_new (domain
, mono_defaults
.string_class
, 2));
6018 for (i
= 0; i
< 32; ++i
)
6019 if (!tz_info
.DaylightName
[i
])
6021 mono_array_setref ((*names
), 1, mono_string_new_utf16 (domain
, tz_info
.DaylightName
, i
));
6022 for (i
= 0; i
< 32; ++i
)
6023 if (!tz_info
.StandardName
[i
])
6025 mono_array_setref ((*names
), 0, mono_string_new_utf16 (domain
, tz_info
.StandardName
, i
));
6027 if ((year
<= 1601) || (year
> 30827)) {
6029 * According to MSDN, the MS time functions can't handle dates outside
6035 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6036 if (tz_id
!= TIME_ZONE_ID_UNKNOWN
) {
6037 tz_info
.StandardDate
.wYear
= year
;
6038 convert_to_absolute_date(&tz_info
.StandardDate
);
6039 err
= SystemTimeToFileTime (&tz_info
.StandardDate
, &ft
);
6044 mono_array_set ((*data
), gint64
, 1, FILETIME_ADJUST
+ (((guint64
)ft
.dwHighDateTime
<<32) | ft
.dwLowDateTime
));
6045 tz_info
.DaylightDate
.wYear
= year
;
6046 convert_to_absolute_date(&tz_info
.DaylightDate
);
6047 err
= SystemTimeToFileTime (&tz_info
.DaylightDate
, &ft
);
6052 mono_array_set ((*data
), gint64
, 0, FILETIME_ADJUST
+ (((guint64
)ft
.dwHighDateTime
<<32) | ft
.dwLowDateTime
));
6054 mono_array_set ((*data
), gint64
, 2, (tz_info
.Bias
+ tz_info
.StandardBias
) * -600000000LL);
6055 mono_array_set ((*data
), gint64
, 3, (tz_info
.DaylightBias
- tz_info
.StandardBias
) * -600000000LL);
6062 ves_icall_System_Object_obj_address (MonoObject
*this)
6064 MONO_ARCH_SAVE_REGS
;
6071 static inline gint32
6072 mono_array_get_byte_length (MonoArray
*array
)
6078 klass
= array
->obj
.vtable
->klass
;
6080 if (array
->bounds
== NULL
)
6081 length
= array
->max_length
;
6084 for (i
= 0; i
< klass
->rank
; ++ i
)
6085 length
*= array
->bounds
[i
].length
;
6088 switch (klass
->element_class
->byval_arg
.type
) {
6091 case MONO_TYPE_BOOLEAN
:
6095 case MONO_TYPE_CHAR
:
6103 return length
* sizeof (gpointer
);
6114 ves_icall_System_Buffer_ByteLengthInternal (MonoArray
*array
)
6116 MONO_ARCH_SAVE_REGS
;
6118 return mono_array_get_byte_length (array
);
6122 ves_icall_System_Buffer_GetByteInternal (MonoArray
*array
, gint32 idx
)
6124 MONO_ARCH_SAVE_REGS
;
6126 return mono_array_get (array
, gint8
, idx
);
6130 ves_icall_System_Buffer_SetByteInternal (MonoArray
*array
, gint32 idx
, gint8 value
)
6132 MONO_ARCH_SAVE_REGS
;
6134 mono_array_set (array
, gint8
, idx
, value
);
6138 ves_icall_System_Buffer_BlockCopyInternal (MonoArray
*src
, gint32 src_offset
, MonoArray
*dest
, gint32 dest_offset
, gint32 count
)
6140 guint8
*src_buf
, *dest_buf
;
6142 MONO_ARCH_SAVE_REGS
;
6144 /* watch out for integer overflow */
6145 if ((src_offset
> mono_array_get_byte_length (src
) - count
) || (dest_offset
> mono_array_get_byte_length (dest
) - count
))
6148 src_buf
= (guint8
*)src
->vector
+ src_offset
;
6149 dest_buf
= (guint8
*)dest
->vector
+ dest_offset
;
6152 memcpy (dest_buf
, src_buf
, count
);
6154 memmove (dest_buf
, src_buf
, count
); /* Source and dest are the same array */
6160 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject
*this, MonoString
*class_name
)
6162 MonoDomain
*domain
= mono_object_domain (this);
6164 MonoRealProxy
*rp
= ((MonoRealProxy
*)this);
6165 MonoTransparentProxy
*tp
;
6169 MONO_ARCH_SAVE_REGS
;
6171 res
= mono_object_new (domain
, mono_defaults
.transparent_proxy_class
);
6172 tp
= (MonoTransparentProxy
*) res
;
6174 MONO_OBJECT_SETREF (tp
, rp
, rp
);
6175 type
= ((MonoReflectionType
*)rp
->class_to_proxy
)->type
;
6176 klass
= mono_class_from_mono_type (type
);
6178 tp
->custom_type_info
= (mono_object_isinst (this, mono_defaults
.iremotingtypeinfo_class
) != NULL
);
6179 tp
->remote_class
= mono_remote_class (domain
, class_name
, klass
);
6181 res
->vtable
= mono_remote_class_vtable (domain
, tp
->remote_class
, rp
);
6185 static MonoReflectionType
*
6186 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy
*tp
)
6188 return mono_type_get_object (mono_object_domain (tp
), &tp
->remote_class
->proxy_class
->byval_arg
);
6191 /* System.Environment */
6194 ves_icall_System_Environment_get_UserName (void)
6196 MONO_ARCH_SAVE_REGS
;
6198 /* using glib is more portable */
6199 return mono_string_new (mono_domain_get (), g_get_user_name ());
6204 ves_icall_System_Environment_get_MachineName (void)
6206 #if defined (HOST_WIN32)
6211 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
6212 buf
= g_new (gunichar2
, len
);
6215 if (GetComputerName (buf
, (PDWORD
) &len
))
6216 result
= mono_string_new_utf16 (mono_domain_get (), buf
, len
);
6220 #elif !defined(DISABLE_SOCKETS)
6224 if (gethostname (buf
, sizeof (buf
)) == 0)
6225 result
= mono_string_new (mono_domain_get (), buf
);
6231 return mono_string_new (mono_domain_get (), "mono");
6236 ves_icall_System_Environment_get_Platform (void)
6238 #if defined (TARGET_WIN32)
6241 #elif defined(__MACH__)
6244 // For compatibility with our client code, this will be 4 for a while.
6245 // We will eventually move to 6 to match .NET, but it requires all client
6246 // code to be updated and the documentation everywhere to be updated
6257 ves_icall_System_Environment_get_NewLine (void)
6259 MONO_ARCH_SAVE_REGS
;
6261 #if defined (HOST_WIN32)
6262 return mono_string_new (mono_domain_get (), "\r\n");
6264 return mono_string_new (mono_domain_get (), "\n");
6269 ves_icall_System_Environment_GetEnvironmentVariable (MonoString
*name
)
6274 MONO_ARCH_SAVE_REGS
;
6279 utf8_name
= mono_string_to_utf8 (name
); /* FIXME: this should be ascii */
6280 value
= g_getenv (utf8_name
);
6287 return mono_string_new (mono_domain_get (), value
);
6291 * There is no standard way to get at environ.
6294 #ifndef __MINGW32_VERSION
6296 /* Apple defines this in crt_externs.h but doesn't provide that header for
6297 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6298 * in fact exist on all implementations (so far)
6300 gchar
***_NSGetEnviron(void);
6301 #define environ (*_NSGetEnviron())
6310 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6321 env_strings
= GetEnvironmentStrings();
6324 env_string
= env_strings
;
6325 while (*env_string
!= '\0') {
6326 /* weird case that MS seems to skip */
6327 if (*env_string
!= '=')
6329 while (*env_string
!= '\0')
6335 domain
= mono_domain_get ();
6336 names
= mono_array_new (domain
, mono_defaults
.string_class
, n
);
6340 env_string
= env_strings
;
6341 while (*env_string
!= '\0') {
6342 /* weird case that MS seems to skip */
6343 if (*env_string
!= '=') {
6344 equal_str
= wcschr(env_string
, '=');
6345 g_assert(equal_str
);
6346 str
= mono_string_new_utf16 (domain
, env_string
, equal_str
-env_string
);
6347 mono_array_setref (names
, n
, str
);
6350 while (*env_string
!= '\0')
6355 FreeEnvironmentStrings (env_strings
);
6367 MONO_ARCH_SAVE_REGS
;
6370 for (e
= environ
; *e
!= 0; ++ e
)
6373 domain
= mono_domain_get ();
6374 names
= mono_array_new (domain
, mono_defaults
.string_class
, n
);
6377 for (e
= environ
; *e
!= 0; ++ e
) {
6378 parts
= g_strsplit (*e
, "=", 2);
6380 str
= mono_string_new (domain
, *parts
);
6381 mono_array_setref (names
, n
, str
);
6394 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6396 #if !GLIB_CHECK_VERSION(2,4,0)
6397 #define g_setenv(a,b,c) setenv(a,b,c)
6398 #define g_unsetenv(a) unsetenv(a)
6402 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString
*name
, MonoString
*value
)
6407 gunichar2
*utf16_name
, *utf16_value
;
6409 gchar
*utf8_name
, *utf8_value
;
6412 MONO_ARCH_SAVE_REGS
;
6415 utf16_name
= mono_string_to_utf16 (name
);
6416 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
6417 SetEnvironmentVariable (utf16_name
, NULL
);
6418 g_free (utf16_name
);
6422 utf16_value
= mono_string_to_utf16 (value
);
6424 SetEnvironmentVariable (utf16_name
, utf16_value
);
6426 g_free (utf16_name
);
6427 g_free (utf16_value
);
6429 utf8_name
= mono_string_to_utf8 (name
); /* FIXME: this should be ascii */
6431 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
6432 g_unsetenv (utf8_name
);
6437 utf8_value
= mono_string_to_utf8_checked (value
, &error
);
6438 if (!mono_error_ok (&error
)) {
6440 mono_error_raise_exception (&error
);
6442 g_setenv (utf8_name
, utf8_value
, TRUE
);
6445 g_free (utf8_value
);
6450 ves_icall_System_Environment_Exit (int result
)
6452 MONO_ARCH_SAVE_REGS
;
6454 mono_threads_set_shutting_down ();
6456 mono_runtime_set_shutting_down ();
6458 /* Suspend all managed threads since the runtime is going away */
6459 mono_thread_suspend_all_other_threads ();
6461 mono_runtime_quit ();
6463 /* we may need to do some cleanup here... */
6468 ves_icall_System_Environment_GetGacPath (void)
6470 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6474 ves_icall_System_Environment_GetWindowsFolderPath (int folder
)
6476 #if defined (HOST_WIN32)
6477 #ifndef CSIDL_FLAG_CREATE
6478 #define CSIDL_FLAG_CREATE 0x8000
6481 WCHAR path
[MAX_PATH
];
6482 /* Create directory if no existing */
6483 if (SUCCEEDED (SHGetFolderPathW (NULL
, folder
| CSIDL_FLAG_CREATE
, NULL
, 0, path
))) {
6487 return mono_string_new_utf16 (mono_domain_get (), path
, len
);
6490 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6492 return mono_string_new (mono_domain_get (), "");
6496 ves_icall_System_Environment_GetLogicalDrives (void)
6498 gunichar2 buf
[128], *ptr
, *dname
;
6500 guint initial_size
= 127, size
= 128;
6503 MonoString
*drivestr
;
6504 MonoDomain
*domain
= mono_domain_get ();
6507 MONO_ARCH_SAVE_REGS
;
6512 while (size
> initial_size
) {
6513 size
= (guint
) GetLogicalDriveStrings (initial_size
, ptr
);
6514 if (size
> initial_size
) {
6517 ptr
= g_malloc0 ((size
+ 1) * sizeof (gunichar2
));
6518 initial_size
= size
;
6532 result
= mono_array_new (domain
, mono_defaults
.string_class
, ndrives
);
6537 while (*u16
) { u16
++; len
++; }
6538 drivestr
= mono_string_new_utf16 (domain
, dname
, len
);
6539 mono_array_setref (result
, ndrives
++, drivestr
);
6550 ves_icall_System_Environment_InternalGetHome (void)
6552 MONO_ARCH_SAVE_REGS
;
6554 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6557 static const char *encodings
[] = {
6559 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6560 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6561 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6563 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6564 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6565 "x_unicode_2_0_utf_7",
6567 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6568 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6570 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6573 "unicodefffe", "utf_16be",
6580 * Returns the internal codepage, if the value of "int_code_page" is
6581 * 1 at entry, and we can not compute a suitable code page number,
6582 * returns the code page as a string
6585 ves_icall_System_Text_Encoding_InternalCodePage (gint32
*int_code_page
)
6590 char *codepage
= NULL
;
6592 int want_name
= *int_code_page
;
6595 *int_code_page
= -1;
6596 MONO_ARCH_SAVE_REGS
;
6598 g_get_charset (&cset
);
6599 c
= codepage
= strdup (cset
);
6600 for (c
= codepage
; *c
; c
++){
6601 if (isascii (*c
) && isalpha (*c
))
6606 /* g_print ("charset: %s\n", cset); */
6608 /* handle some common aliases */
6611 for (i
= 0; p
!= 0; ){
6612 if ((gssize
) p
< 7){
6614 p
= encodings
[++i
];
6617 if (strcmp (p
, codepage
) == 0){
6618 *int_code_page
= code
;
6621 p
= encodings
[++i
];
6624 if (strstr (codepage
, "utf_8") != NULL
)
6625 *int_code_page
|= 0x10000000;
6628 if (want_name
&& *int_code_page
== -1)
6629 return mono_string_new (mono_domain_get (), cset
);
6635 ves_icall_System_Environment_get_HasShutdownStarted (void)
6637 if (mono_runtime_is_shutting_down ())
6640 if (mono_domain_is_unloading (mono_domain_get ()))
6647 ves_icall_System_Environment_BroadcastSettingChange (void)
6650 SendMessageTimeout (HWND_BROADCAST
, WM_SETTINGCHANGE
, NULL
, L
"Environment", SMTO_ABORTIFHUNG
, 2000, 0);
6655 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage
*this,
6656 MonoReflectionMethod
*method
,
6657 MonoArray
*out_args
)
6659 MONO_ARCH_SAVE_REGS
;
6661 mono_message_init (mono_object_domain (this), this, method
, out_args
);
6665 ves_icall_IsTransparentProxy (MonoObject
*proxy
)
6667 MONO_ARCH_SAVE_REGS
;
6672 if (proxy
->vtable
->klass
== mono_defaults
.transparent_proxy_class
)
6678 static MonoReflectionMethod
*
6679 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6680 MonoReflectionType
*rtype
, MonoReflectionMethod
*rmethod
)
6684 MonoMethod
**vtable
;
6685 MonoMethod
*res
= NULL
;
6687 MONO_CHECK_ARG_NULL (rtype
);
6688 MONO_CHECK_ARG_NULL (rmethod
);
6690 method
= rmethod
->method
;
6691 klass
= mono_class_from_mono_type (rtype
->type
);
6693 if (MONO_CLASS_IS_INTERFACE (klass
))
6696 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
)
6699 if ((method
->flags
& METHOD_ATTRIBUTE_FINAL
) || !(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
6700 if (klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
))
6706 mono_class_setup_vtable (klass
);
6707 vtable
= klass
->vtable
;
6709 if (method
->klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
6710 gboolean variance_used
= FALSE
;
6711 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6712 int offs
= mono_class_interface_offset_with_variance (klass
, method
->klass
, &variance_used
);
6714 res
= vtable
[offs
+ method
->slot
];
6716 if (!(klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
)))
6719 if (method
->slot
!= -1)
6720 res
= vtable
[method
->slot
];
6726 return mono_method_get_object (mono_domain_get (), res
, NULL
);
6730 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType
*type
, MonoBoolean enable
)
6735 MONO_ARCH_SAVE_REGS
;
6737 klass
= mono_class_from_mono_type (type
->type
);
6738 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, TRUE
);
6740 if (enable
) vtable
->remote
= 1;
6741 else vtable
->remote
= 0;
6745 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType
*type
)
6750 MONO_ARCH_SAVE_REGS
;
6752 domain
= mono_object_domain (type
);
6753 klass
= mono_class_from_mono_type (type
->type
);
6755 if (klass
->rank
>= 1) {
6756 g_assert (klass
->rank
== 1);
6757 return (MonoObject
*) mono_array_new (domain
, klass
->element_class
, 0);
6759 /* Bypass remoting object creation check */
6760 return mono_object_new_alloc_specific (mono_class_vtable_full (domain
, klass
, TRUE
));
6765 ves_icall_System_IO_get_temp_path (void)
6767 MONO_ARCH_SAVE_REGS
;
6769 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6772 #ifndef PLATFORM_NO_DRIVEINFO
6774 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString
*path_name
, guint64
*free_bytes_avail
,
6775 guint64
*total_number_of_bytes
, guint64
*total_number_of_free_bytes
,
6779 ULARGE_INTEGER wapi_free_bytes_avail
;
6780 ULARGE_INTEGER wapi_total_number_of_bytes
;
6781 ULARGE_INTEGER wapi_total_number_of_free_bytes
;
6783 MONO_ARCH_SAVE_REGS
;
6785 *error
= ERROR_SUCCESS
;
6786 result
= GetDiskFreeSpaceEx (mono_string_chars (path_name
), &wapi_free_bytes_avail
, &wapi_total_number_of_bytes
,
6787 &wapi_total_number_of_free_bytes
);
6790 *free_bytes_avail
= wapi_free_bytes_avail
.QuadPart
;
6791 *total_number_of_bytes
= wapi_total_number_of_bytes
.QuadPart
;
6792 *total_number_of_free_bytes
= wapi_total_number_of_free_bytes
.QuadPart
;
6794 *free_bytes_avail
= 0;
6795 *total_number_of_bytes
= 0;
6796 *total_number_of_free_bytes
= 0;
6797 *error
= GetLastError ();
6804 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString
*root_path_name
)
6806 MONO_ARCH_SAVE_REGS
;
6808 return GetDriveType (mono_string_chars (root_path_name
));
6813 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod
*method
)
6815 MONO_ARCH_SAVE_REGS
;
6817 return mono_compile_method (method
);
6821 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6826 MONO_ARCH_SAVE_REGS
;
6828 path
= g_build_path (G_DIR_SEPARATOR_S
, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version
, "machine.config", NULL
);
6830 #if defined (HOST_WIN32)
6831 /* Avoid mixing '/' and '\\' */
6834 for (i
= strlen (path
) - 1; i
>= 0; i
--)
6835 if (path
[i
] == '/')
6839 mcpath
= mono_string_new (mono_domain_get (), path
);
6846 get_bundled_machine_config (void)
6848 const gchar
*machine_config
;
6850 MONO_ARCH_SAVE_REGS
;
6852 machine_config
= mono_get_machine_config ();
6854 if (!machine_config
)
6857 return mono_string_new (mono_domain_get (), machine_config
);
6861 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6866 MONO_ARCH_SAVE_REGS
;
6868 path
= g_path_get_dirname (mono_get_config_dir ());
6870 #if defined (HOST_WIN32)
6871 /* Avoid mixing '/' and '\\' */
6874 for (i
= strlen (path
) - 1; i
>= 0; i
--)
6875 if (path
[i
] == '/')
6879 ipath
= mono_string_new (mono_domain_get (), path
);
6886 ves_icall_get_resources_ptr (MonoReflectionAssembly
*assembly
, gpointer
*result
, gint32
*size
)
6888 MonoPEResourceDataEntry
*entry
;
6891 MONO_ARCH_SAVE_REGS
;
6893 if (!assembly
|| !result
|| !size
)
6898 image
= assembly
->assembly
->image
;
6899 entry
= mono_image_lookup_resource (image
, MONO_PE_RESOURCE_ID_ASPNET_STRING
, 0, NULL
);
6903 *result
= mono_image_rva_map (image
, entry
->rde_data_offset
);
6908 *size
= entry
->rde_size
;
6914 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6916 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6920 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString
*message
)
6922 #if defined (HOST_WIN32)
6923 OutputDebugString (mono_string_chars (message
));
6925 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6929 /* Only used for value types */
6931 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType
*type
)
6936 MONO_ARCH_SAVE_REGS
;
6938 domain
= mono_object_domain (type
);
6939 klass
= mono_class_from_mono_type (type
->type
);
6941 if (mono_class_is_nullable (klass
))
6942 /* No arguments -> null */
6945 return mono_object_new (domain
, klass
);
6948 static MonoReflectionMethod
*
6949 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod
*m
, gboolean definition
)
6951 MonoClass
*klass
, *parent
;
6952 MonoMethod
*method
= m
->method
;
6953 MonoMethod
*result
= NULL
;
6955 MONO_ARCH_SAVE_REGS
;
6957 if (method
->klass
== NULL
)
6960 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
6961 MONO_CLASS_IS_INTERFACE (method
->klass
) ||
6962 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
6965 klass
= method
->klass
;
6966 if (klass
->generic_class
)
6967 klass
= klass
->generic_class
->container_class
;
6970 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6971 for (parent
= klass
->parent
; parent
!= NULL
; parent
= parent
->parent
) {
6972 mono_class_setup_vtable (parent
);
6973 if (parent
->vtable_size
<= method
->slot
)
6978 klass
= klass
->parent
;
6983 if (klass
== method
->klass
)
6986 result
= klass
->vtable
[method
->slot
];
6987 if (result
== NULL
) {
6988 /* It is an abstract method */
6989 gpointer iter
= NULL
;
6990 while ((result
= mono_class_get_methods (klass
, &iter
)))
6991 if (result
->slot
== method
->slot
)
6998 return mono_method_get_object (mono_domain_get (), result
, NULL
);
7002 ves_icall_MonoMethod_get_name (MonoReflectionMethod
*m
)
7004 MonoMethod
*method
= m
->method
;
7006 MONO_OBJECT_SETREF (m
, name
, mono_string_new (mono_object_domain (m
), method
->name
));
7011 mono_ArgIterator_Setup (MonoArgIterator
*iter
, char* argsp
, char* start
)
7013 MONO_ARCH_SAVE_REGS
;
7015 iter
->sig
= *(MonoMethodSignature
**)argsp
;
7017 g_assert (iter
->sig
->sentinelpos
<= iter
->sig
->param_count
);
7018 g_assert (iter
->sig
->call_convention
== MONO_CALL_VARARG
);
7021 /* FIXME: it's not documented what start is exactly... */
7025 iter
->args
= argsp
+ sizeof (gpointer
);
7027 iter
->num_args
= iter
->sig
->param_count
- iter
->sig
->sentinelpos
;
7029 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7033 mono_ArgIterator_IntGetNextArg (MonoArgIterator
*iter
)
7035 guint32 i
, arg_size
;
7038 MONO_ARCH_SAVE_REGS
;
7040 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7042 g_assert (i
< iter
->sig
->param_count
);
7044 res
.type
= iter
->sig
->params
[i
];
7045 res
.klass
= mono_class_from_mono_type (res
.type
);
7046 res
.value
= iter
->args
;
7047 arg_size
= mono_type_stack_size (res
.type
, &align
);
7048 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7049 if (arg_size
<= sizeof (gpointer
)) {
7051 int padding
= arg_size
- mono_type_size (res
.type
, &dummy
);
7052 res
.value
= (guint8
*)res
.value
+ padding
;
7055 iter
->args
= (char*)iter
->args
+ arg_size
;
7058 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7064 mono_ArgIterator_IntGetNextArgT (MonoArgIterator
*iter
, MonoType
*type
)
7066 guint32 i
, arg_size
;
7069 MONO_ARCH_SAVE_REGS
;
7071 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7073 g_assert (i
< iter
->sig
->param_count
);
7075 while (i
< iter
->sig
->param_count
) {
7076 if (!mono_metadata_type_equal (type
, iter
->sig
->params
[i
]))
7078 res
.type
= iter
->sig
->params
[i
];
7079 res
.klass
= mono_class_from_mono_type (res
.type
);
7080 /* FIXME: endianess issue... */
7081 res
.value
= iter
->args
;
7082 arg_size
= mono_type_stack_size (res
.type
, &align
);
7083 iter
->args
= (char*)iter
->args
+ arg_size
;
7085 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7088 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7097 mono_ArgIterator_IntGetNextArgType (MonoArgIterator
*iter
)
7100 MONO_ARCH_SAVE_REGS
;
7102 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7104 g_assert (i
< iter
->sig
->param_count
);
7106 return iter
->sig
->params
[i
];
7110 mono_TypedReference_ToObject (MonoTypedRef tref
)
7112 MONO_ARCH_SAVE_REGS
;
7114 if (MONO_TYPE_IS_REFERENCE (tref
.type
)) {
7115 MonoObject
** objp
= tref
.value
;
7119 return mono_value_box (mono_domain_get (), tref
.klass
, tref
.value
);
7123 mono_TypedReference_ToObjectInternal (MonoType
*type
, gpointer value
, MonoClass
*klass
)
7125 MONO_ARCH_SAVE_REGS
;
7127 if (MONO_TYPE_IS_REFERENCE (type
)) {
7128 MonoObject
** objp
= value
;
7132 return mono_value_box (mono_domain_get (), klass
, value
);
7136 prelink_method (MonoMethod
*method
)
7138 const char *exc_class
, *exc_arg
;
7139 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
7141 mono_lookup_pinvoke_call (method
, &exc_class
, &exc_arg
);
7143 mono_raise_exception(
7144 mono_exception_from_name_msg (mono_defaults
.corlib
, "System", exc_class
, exc_arg
) );
7146 /* create the wrapper, too? */
7150 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod
*method
)
7152 MONO_ARCH_SAVE_REGS
;
7153 prelink_method (method
->method
);
7157 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType
*type
)
7159 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
7161 gpointer iter
= NULL
;
7162 MONO_ARCH_SAVE_REGS
;
7164 while ((m
= mono_class_get_methods (klass
, &iter
)))
7168 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7170 ves_icall_System_NumberFormatter_GetFormatterTables (guint64
const **mantissas
,
7171 gint32
const **exponents
,
7172 gunichar2
const **digitLowerTable
,
7173 gunichar2
const **digitUpperTable
,
7174 gint64
const **tenPowersList
,
7175 gint32
const **decHexDigits
)
7177 *mantissas
= Formatter_MantissaBitsTable
;
7178 *exponents
= Formatter_TensExponentTable
;
7179 *digitLowerTable
= Formatter_DigitLowerTable
;
7180 *digitUpperTable
= Formatter_DigitUpperTable
;
7181 *tenPowersList
= Formatter_TenPowersList
;
7182 *decHexDigits
= Formatter_DecHexDigits
;
7185 /* These parameters are "readonly" in corlib/System/Char.cs */
7187 ves_icall_System_Char_GetDataTablePointers (guint8
const **category_data
,
7188 guint8
const **numeric_data
,
7189 gdouble
const **numeric_data_values
,
7190 guint16
const **to_lower_data_low
,
7191 guint16
const **to_lower_data_high
,
7192 guint16
const **to_upper_data_low
,
7193 guint16
const **to_upper_data_high
)
7195 *category_data
= CategoryData
;
7196 *numeric_data
= NumericData
;
7197 *numeric_data_values
= NumericDataValues
;
7198 *to_lower_data_low
= ToLowerDataLow
;
7199 *to_lower_data_high
= ToLowerDataHigh
;
7200 *to_upper_data_low
= ToUpperDataLow
;
7201 *to_upper_data_high
= ToUpperDataHigh
;
7205 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod
*method
)
7207 return method
->method
->token
;
7211 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7212 * and avoid useless allocations.
7215 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
)
7219 for (i
= 0; i
< type
->num_mods
; ++i
) {
7220 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
))
7225 res
= mono_array_new (mono_domain_get (), mono_defaults
.systemtype_class
, count
);
7227 for (i
= 0; i
< type
->num_mods
; ++i
) {
7228 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
)) {
7229 MonoClass
*klass
= mono_class_get (image
, type
->modifiers
[i
].token
);
7230 mono_array_setref (res
, count
, mono_type_get_object (mono_domain_get (), &klass
->byval_arg
));
7238 param_info_get_type_modifiers (MonoReflectionParameter
*param
, MonoBoolean optional
)
7240 MonoType
*type
= param
->ClassImpl
->type
;
7241 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
7242 MonoMethod
*method
= NULL
;
7245 MonoMethodSignature
*sig
;
7247 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
7248 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
7249 method
= rmethod
->method
;
7250 } else if (member_class
->image
== mono_defaults
.corlib
&& !strcmp ("MonoProperty", member_class
->name
)) {
7251 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
7252 if (!(method
= prop
->property
->get
))
7253 method
= prop
->property
->set
;
7256 char *type_name
= mono_type_get_full_name (member_class
);
7257 char *msg
= g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name
);
7258 MonoException
*ex
= mono_get_exception_not_supported (msg
);
7261 mono_raise_exception (ex
);
7264 image
= method
->klass
->image
;
7265 pos
= param
->PositionImpl
;
7266 sig
= mono_method_signature (method
);
7270 type
= sig
->params
[pos
];
7272 return type_array_from_modifiers (image
, type
, optional
);
7276 get_property_type (MonoProperty
*prop
)
7278 MonoMethodSignature
*sig
;
7280 sig
= mono_method_signature (prop
->get
);
7282 } else if (prop
->set
) {
7283 sig
= mono_method_signature (prop
->set
);
7284 return sig
->params
[sig
->param_count
- 1];
7290 property_info_get_type_modifiers (MonoReflectionProperty
*property
, MonoBoolean optional
)
7292 MonoType
*type
= get_property_type (property
->property
);
7293 MonoImage
*image
= property
->klass
->image
;
7297 return type_array_from_modifiers (image
, type
, optional
);
7301 *Construct a MonoType suited to be used to decode a constant blob object.
7303 * @type is the target type which will be constructed
7304 * @blob_type is the blob type, for example, that comes from the constant table
7305 * @real_type is the expected constructed type.
7308 mono_type_from_blob_type (MonoType
*type
, MonoTypeEnum blob_type
, MonoType
*real_type
)
7310 type
->type
= blob_type
;
7311 type
->data
.klass
= NULL
;
7312 if (blob_type
== MONO_TYPE_CLASS
)
7313 type
->data
.klass
= mono_defaults
.object_class
;
7314 else if (real_type
->type
== MONO_TYPE_VALUETYPE
&& real_type
->data
.klass
->enumtype
) {
7315 /* For enums, we need to use the base type */
7316 type
->type
= MONO_TYPE_VALUETYPE
;
7317 type
->data
.klass
= mono_class_from_mono_type (real_type
);
7319 type
->data
.klass
= mono_class_from_mono_type (real_type
);
7323 property_info_get_default_value (MonoReflectionProperty
*property
)
7326 MonoProperty
*prop
= property
->property
;
7327 MonoType
*type
= get_property_type (prop
);
7328 MonoDomain
*domain
= mono_object_domain (property
);
7329 MonoTypeEnum def_type
;
7330 const char *def_value
;
7333 g_assert (!prop
->parent
->image
->dynamic
);
7335 mono_class_init (prop
->parent
);
7337 if (!(prop
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
))
7338 mono_raise_exception (mono_get_exception_invalid_operation (NULL
));
7340 def_value
= mono_class_get_property_default_value (prop
, &def_type
);
7342 mono_type_from_blob_type (&blob_type
, def_type
, type
);
7343 o
= mono_get_object_from_blob (domain
, &blob_type
, def_value
);
7349 custom_attrs_defined_internal (MonoObject
*obj
, MonoReflectionType
*attr_type
)
7351 MonoCustomAttrInfo
*cinfo
;
7354 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
7357 found
= mono_custom_attrs_has_attr (cinfo
, mono_class_from_mono_type (attr_type
->type
));
7359 mono_custom_attrs_free (cinfo
);
7364 custom_attrs_get_by_type (MonoObject
*obj
, MonoReflectionType
*attr_type
)
7366 MonoArray
*res
= mono_reflection_get_custom_attrs_by_type (obj
, attr_type
? mono_class_from_mono_type (attr_type
->type
) : NULL
);
7368 if (mono_loader_get_last_error ()) {
7369 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7370 g_assert_not_reached ();
7379 ves_icall_Mono_Runtime_GetDisplayName (void)
7382 MonoString
*display_name
;
7384 info
= mono_get_runtime_callbacks ()->get_runtime_build_info ();
7385 display_name
= mono_string_new (mono_domain_get (), info
);
7387 return display_name
;
7391 ves_icall_Mono_Runtime_NewObject (MonoType
*t
)
7393 return mono_object_new (mono_domain_get (), mono_class_from_mono_type (t
));
7397 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code
)
7399 MonoString
*message
;
7403 ret
= FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
7404 FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, code
, 0,
7407 message
= mono_string_new (mono_domain_get (), "Error looking up error string");
7409 message
= mono_string_new_utf16 (mono_domain_get (), buf
, ret
);
7417 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7418 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7419 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7420 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7421 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7422 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7423 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7424 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7428 base64_to_byte_array (gunichar2
*start
, gint ilength
, MonoBoolean allowWhitespaceOnly
)
7433 gunichar2 last
, prev_last
, prev2_last
;
7441 last
= prev_last
= 0, prev2_last
= 0;
7442 for (i
= 0; i
< ilength
; i
++) {
7444 if (c
>= sizeof (dbase64
)) {
7445 exc
= mono_exception_from_name_msg (mono_get_corlib (),
7446 "System", "FormatException",
7447 "Invalid character found.");
7448 mono_raise_exception (exc
);
7449 } else if (isspace (c
)) {
7452 prev2_last
= prev_last
;
7458 olength
= ilength
- ignored
;
7460 if (allowWhitespaceOnly
&& olength
== 0) {
7461 return mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, 0);
7464 if ((olength
& 3) != 0 || olength
<= 0) {
7465 exc
= mono_exception_from_name_msg (mono_get_corlib (), "System",
7466 "FormatException", "Invalid length.");
7467 mono_raise_exception (exc
);
7470 if (prev2_last
== '=') {
7471 exc
= mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7472 mono_raise_exception (exc
);
7475 olength
= (olength
* 3) / 4;
7479 if (prev_last
== '=')
7482 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, olength
);
7483 res_ptr
= mono_array_addr (result
, guchar
, 0);
7484 for (i
= 0; i
< ilength
; ) {
7487 for (k
= 0; k
< 4 && i
< ilength
;) {
7493 if (((b
[k
] = dbase64
[c
]) & 0x80) != 0) {
7494 exc
= mono_exception_from_name_msg (mono_get_corlib (),
7495 "System", "FormatException",
7496 "Invalid character found.");
7497 mono_raise_exception (exc
);
7502 *res_ptr
++ = (b
[0] << 2) | (b
[1] >> 4);
7504 *res_ptr
++ = (b
[1] << 4) | (b
[2] >> 2);
7506 *res_ptr
++ = (b
[2] << 6) | b
[3];
7508 while (i
< ilength
&& isspace (start
[i
]))
7516 InternalFromBase64String (MonoString
*str
, MonoBoolean allowWhitespaceOnly
)
7518 MONO_ARCH_SAVE_REGS
;
7520 return base64_to_byte_array (mono_string_chars (str
),
7521 mono_string_length (str
), allowWhitespaceOnly
);
7525 InternalFromBase64CharArray (MonoArray
*input
, gint offset
, gint length
)
7527 MONO_ARCH_SAVE_REGS
;
7529 return base64_to_byte_array (mono_array_addr (input
, gunichar2
, offset
),
7533 #define ICALL_TYPE(id,name,first)
7534 #define ICALL(id,name,func) Icall_ ## id,
7537 #include "metadata/icall-def.h"
7543 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7544 #define ICALL(id,name,func)
7546 #include "metadata/icall-def.h"
7552 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7553 #define ICALL(id,name,func)
7555 guint16 first_icall
;
7558 static const IcallTypeDesc
7559 icall_type_descs
[] = {
7560 #include "metadata/icall-def.h"
7564 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7567 #define ICALL_TYPE(id,name,first)
7570 #ifdef HAVE_ARRAY_ELEM_INIT
7571 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7572 #define MSGSTRFIELD1(line) str##line
7574 static const struct msgstrtn_t
{
7575 #define ICALL(id,name,func)
7577 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7578 #include "metadata/icall-def.h"
7580 } icall_type_names_str
= {
7581 #define ICALL_TYPE(id,name,first) (name),
7582 #include "metadata/icall-def.h"
7585 static const guint16 icall_type_names_idx
[] = {
7586 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7587 #include "metadata/icall-def.h"
7590 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7592 static const struct msgstr_t
{
7594 #define ICALL_TYPE(id,name,first)
7595 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7596 #include "metadata/icall-def.h"
7598 } icall_names_str
= {
7599 #define ICALL(id,name,func) (name),
7600 #include "metadata/icall-def.h"
7603 static const guint16 icall_names_idx
[] = {
7604 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7605 #include "metadata/icall-def.h"
7608 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7614 #define ICALL_TYPE(id,name,first) name,
7615 #define ICALL(id,name,func)
7616 static const char* const
7617 icall_type_names
[] = {
7618 #include "metadata/icall-def.h"
7622 #define icall_type_name_get(id) (icall_type_names [(id)])
7626 #define ICALL_TYPE(id,name,first)
7627 #define ICALL(id,name,func) name,
7628 static const char* const
7630 #include "metadata/icall-def.h"
7633 #define icall_name_get(id) icall_names [(id)]
7635 #endif /* !HAVE_ARRAY_ELEM_INIT */
7639 #define ICALL_TYPE(id,name,first)
7640 #define ICALL(id,name,func) func,
7641 static const gconstpointer
7642 icall_functions
[] = {
7643 #include "metadata/icall-def.h"
7647 static GHashTable
*icall_hash
= NULL
;
7648 static GHashTable
*jit_icall_hash_name
= NULL
;
7649 static GHashTable
*jit_icall_hash_addr
= NULL
;
7652 mono_icall_init (void)
7656 /* check that tables are sorted: disable in release */
7659 const char *prev_class
= NULL
;
7660 const char *prev_method
;
7662 for (i
= 0; i
< Icall_type_num
; ++i
) {
7663 const IcallTypeDesc
*desc
;
7666 if (prev_class
&& strcmp (prev_class
, icall_type_name_get (i
)) >= 0)
7667 g_print ("class %s should come before class %s\n", icall_type_name_get (i
), prev_class
);
7668 prev_class
= icall_type_name_get (i
);
7669 desc
= &icall_type_descs
[i
];
7670 num_icalls
= icall_desc_num_icalls (desc
);
7671 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7672 for (j
= 0; j
< num_icalls
; ++j
) {
7673 const char *methodn
= icall_name_get (desc
->first_icall
+ j
);
7674 if (prev_method
&& strcmp (prev_method
, methodn
) >= 0)
7675 g_print ("method %s should come before method %s\n", methodn
, prev_method
);
7676 prev_method
= methodn
;
7681 icall_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
7685 mono_icall_cleanup (void)
7687 g_hash_table_destroy (icall_hash
);
7688 g_hash_table_destroy (jit_icall_hash_name
);
7689 g_hash_table_destroy (jit_icall_hash_addr
);
7693 mono_add_internal_call (const char *name
, gconstpointer method
)
7695 mono_loader_lock ();
7697 g_hash_table_insert (icall_hash
, g_strdup (name
), (gpointer
) method
);
7699 mono_loader_unlock ();
7702 #ifdef HAVE_ARRAY_ELEM_INIT
7704 compare_method_imap (const void *key
, const void *elem
)
7706 const char* method_name
= (const char*)&icall_names_str
+ (*(guint16
*)elem
);
7707 return strcmp (key
, method_name
);
7711 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
7713 const guint16
*nameslot
= bsearch (name
, icall_names_idx
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names_idx
[0]), compare_method_imap
);
7716 return (gpointer
)icall_functions
[(nameslot
- &icall_names_idx
[0])];
7720 compare_class_imap (const void *key
, const void *elem
)
7722 const char* class_name
= (const char*)&icall_type_names_str
+ (*(guint16
*)elem
);
7723 return strcmp (key
, class_name
);
7726 static const IcallTypeDesc
*
7727 find_class_icalls (const char *name
)
7729 const guint16
*nameslot
= bsearch (name
, icall_type_names_idx
, Icall_type_num
, sizeof (icall_type_names_idx
[0]), compare_class_imap
);
7732 return &icall_type_descs
[nameslot
- &icall_type_names_idx
[0]];
7737 compare_method_imap (const void *key
, const void *elem
)
7739 const char** method_name
= (const char**)elem
;
7740 return strcmp (key
, *method_name
);
7744 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
7746 const char **nameslot
= bsearch (name
, icall_names
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names
[0]), compare_method_imap
);
7749 return (gpointer
)icall_functions
[(nameslot
- icall_names
)];
7753 compare_class_imap (const void *key
, const void *elem
)
7755 const char** class_name
= (const char**)elem
;
7756 return strcmp (key
, *class_name
);
7759 static const IcallTypeDesc
*
7760 find_class_icalls (const char *name
)
7762 const char **nameslot
= bsearch (name
, icall_type_names
, Icall_type_num
, sizeof (icall_type_names
[0]), compare_class_imap
);
7765 return &icall_type_descs
[nameslot
- icall_type_names
];
7771 * we should probably export this as an helper (handle nested types).
7772 * Returns the number of chars written in buf.
7775 concat_class_name (char *buf
, int bufsize
, MonoClass
*klass
)
7777 int nspacelen
, cnamelen
;
7778 nspacelen
= strlen (klass
->name_space
);
7779 cnamelen
= strlen (klass
->name
);
7780 if (nspacelen
+ cnamelen
+ 2 > bufsize
)
7783 memcpy (buf
, klass
->name_space
, nspacelen
);
7784 buf
[nspacelen
++] = '.';
7786 memcpy (buf
+ nspacelen
, klass
->name
, cnamelen
);
7787 buf
[nspacelen
+ cnamelen
] = 0;
7788 return nspacelen
+ cnamelen
;
7792 mono_lookup_internal_call (MonoMethod
*method
)
7797 int typelen
= 0, mlen
, siglen
;
7799 const IcallTypeDesc
*imap
;
7801 g_assert (method
!= NULL
);
7803 if (method
->is_inflated
)
7804 method
= ((MonoMethodInflated
*) method
)->declaring
;
7806 if (method
->klass
->nested_in
) {
7807 int pos
= concat_class_name (mname
, sizeof (mname
)-2, method
->klass
->nested_in
);
7811 mname
[pos
++] = '/';
7814 typelen
= concat_class_name (mname
+pos
, sizeof (mname
)-pos
-1, method
->klass
);
7820 typelen
= concat_class_name (mname
, sizeof (mname
), method
->klass
);
7825 imap
= find_class_icalls (mname
);
7827 mname
[typelen
] = ':';
7828 mname
[typelen
+ 1] = ':';
7830 mlen
= strlen (method
->name
);
7831 memcpy (mname
+ typelen
+ 2, method
->name
, mlen
);
7832 sigstart
= mname
+ typelen
+ 2 + mlen
;
7835 tmpsig
= mono_signature_get_desc (mono_method_signature (method
), TRUE
);
7836 siglen
= strlen (tmpsig
);
7837 if (typelen
+ mlen
+ siglen
+ 6 > sizeof (mname
))
7840 memcpy (sigstart
+ 1, tmpsig
, siglen
);
7841 sigstart
[siglen
+ 1] = ')';
7842 sigstart
[siglen
+ 2] = 0;
7845 mono_loader_lock ();
7847 res
= g_hash_table_lookup (icall_hash
, mname
);
7849 mono_loader_unlock ();
7852 /* try without signature */
7854 res
= g_hash_table_lookup (icall_hash
, mname
);
7856 mono_loader_unlock ();
7860 /* it wasn't found in the static call tables */
7862 mono_loader_unlock ();
7865 res
= find_method_icall (imap
, sigstart
- mlen
);
7867 mono_loader_unlock ();
7870 /* try _with_ signature */
7872 res
= find_method_icall (imap
, sigstart
- mlen
);
7874 mono_loader_unlock ();
7878 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname
);
7879 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7880 g_print ("The out of sync library is: %s\n", method
->klass
->image
->name
);
7881 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7882 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");
7883 g_print ("If you see other errors or faults after this message they are probably related\n");
7884 g_print ("and you need to fix your mono install first.\n");
7886 mono_loader_unlock ();
7892 type_from_typename (char *typename
)
7894 MonoClass
*klass
= NULL
; /* assignment to shut GCC warning up */
7896 if (!strcmp (typename
, "int"))
7897 klass
= mono_defaults
.int_class
;
7898 else if (!strcmp (typename
, "ptr"))
7899 klass
= mono_defaults
.int_class
;
7900 else if (!strcmp (typename
, "void"))
7901 klass
= mono_defaults
.void_class
;
7902 else if (!strcmp (typename
, "int32"))
7903 klass
= mono_defaults
.int32_class
;
7904 else if (!strcmp (typename
, "uint32"))
7905 klass
= mono_defaults
.uint32_class
;
7906 else if (!strcmp (typename
, "int8"))
7907 klass
= mono_defaults
.sbyte_class
;
7908 else if (!strcmp (typename
, "uint8"))
7909 klass
= mono_defaults
.byte_class
;
7910 else if (!strcmp (typename
, "int16"))
7911 klass
= mono_defaults
.int16_class
;
7912 else if (!strcmp (typename
, "uint16"))
7913 klass
= mono_defaults
.uint16_class
;
7914 else if (!strcmp (typename
, "long"))
7915 klass
= mono_defaults
.int64_class
;
7916 else if (!strcmp (typename
, "ulong"))
7917 klass
= mono_defaults
.uint64_class
;
7918 else if (!strcmp (typename
, "float"))
7919 klass
= mono_defaults
.single_class
;
7920 else if (!strcmp (typename
, "double"))
7921 klass
= mono_defaults
.double_class
;
7922 else if (!strcmp (typename
, "object"))
7923 klass
= mono_defaults
.object_class
;
7924 else if (!strcmp (typename
, "obj"))
7925 klass
= mono_defaults
.object_class
;
7926 else if (!strcmp (typename
, "string"))
7927 klass
= mono_defaults
.string_class
;
7928 else if (!strcmp (typename
, "bool"))
7929 klass
= mono_defaults
.boolean_class
;
7930 else if (!strcmp (typename
, "boolean"))
7931 klass
= mono_defaults
.boolean_class
;
7933 g_error ("%s", typename
);
7934 g_assert_not_reached ();
7936 return &klass
->byval_arg
;
7939 MonoMethodSignature
*
7940 mono_create_icall_signature (const char *sigstr
)
7945 MonoMethodSignature
*res
;
7947 mono_loader_lock ();
7948 res
= g_hash_table_lookup (mono_defaults
.corlib
->helper_signatures
, sigstr
);
7950 mono_loader_unlock ();
7954 parts
= g_strsplit (sigstr
, " ", 256);
7963 res
= mono_metadata_signature_alloc (mono_defaults
.corlib
, len
- 1);
7968 * Under windows, the default pinvoke calling convention is STDCALL but
7971 res
->call_convention
= MONO_CALL_C
;
7974 res
->ret
= type_from_typename (parts
[0]);
7975 for (i
= 1; i
< len
; ++i
) {
7976 res
->params
[i
- 1] = type_from_typename (parts
[i
]);
7981 g_hash_table_insert (mono_defaults
.corlib
->helper_signatures
, (gpointer
)sigstr
, res
);
7983 mono_loader_unlock ();
7989 mono_find_jit_icall_by_name (const char *name
)
7991 MonoJitICallInfo
*info
;
7992 g_assert (jit_icall_hash_name
);
7994 mono_loader_lock ();
7995 info
= g_hash_table_lookup (jit_icall_hash_name
, name
);
7996 mono_loader_unlock ();
8001 mono_find_jit_icall_by_addr (gconstpointer addr
)
8003 MonoJitICallInfo
*info
;
8004 g_assert (jit_icall_hash_addr
);
8006 mono_loader_lock ();
8007 info
= g_hash_table_lookup (jit_icall_hash_addr
, (gpointer
)addr
);
8008 mono_loader_unlock ();
8014 * mono_get_jit_icall_info:
8016 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8017 * caller should access it while holding the loader lock.
8020 mono_get_jit_icall_info (void)
8022 return jit_icall_hash_name
;
8026 mono_register_jit_icall_wrapper (MonoJitICallInfo
*info
, gconstpointer wrapper
)
8028 mono_loader_lock ();
8029 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)wrapper
, info
);
8030 mono_loader_unlock ();
8034 mono_register_jit_icall (gconstpointer func
, const char *name
, MonoMethodSignature
*sig
, gboolean is_save
)
8036 MonoJitICallInfo
*info
;
8041 mono_loader_lock ();
8043 if (!jit_icall_hash_name
) {
8044 jit_icall_hash_name
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, g_free
);
8045 jit_icall_hash_addr
= g_hash_table_new (NULL
, NULL
);
8048 if (g_hash_table_lookup (jit_icall_hash_name
, name
)) {
8049 g_warning ("jit icall already defined \"%s\"\n", name
);
8050 g_assert_not_reached ();
8053 info
= g_new0 (MonoJitICallInfo
, 1);
8060 info
->wrapper
= func
;
8062 info
->wrapper
= NULL
;
8065 g_hash_table_insert (jit_icall_hash_name
, (gpointer
)info
->name
, info
);
8066 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)func
, info
);
8068 mono_loader_unlock ();