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)
30 #if defined (HAVE_WCHAR_H)
34 #include "mono/utils/mono-membar.h"
35 #include <mono/metadata/object.h>
36 #include <mono/metadata/threads.h>
37 #include <mono/metadata/threads-types.h>
38 #include <mono/metadata/threadpool.h>
39 #include <mono/metadata/monitor.h>
40 #include <mono/metadata/reflection.h>
41 #include <mono/metadata/assembly.h>
42 #include <mono/metadata/tabledefs.h>
43 #include <mono/metadata/exception.h>
44 #include <mono/metadata/file-io.h>
45 #include <mono/metadata/console-io.h>
46 #include <mono/metadata/socket-io.h>
47 #include <mono/metadata/mono-endian.h>
48 #include <mono/metadata/tokentype.h>
49 #include <mono/metadata/domain-internals.h>
50 #include <mono/metadata/metadata-internals.h>
51 #include <mono/metadata/class-internals.h>
52 #include <mono/metadata/marshal.h>
53 #include <mono/metadata/gc-internal.h>
54 #include <mono/metadata/mono-gc.h>
55 #include <mono/metadata/rand.h>
56 #include <mono/metadata/sysmath.h>
57 #include <mono/metadata/string-icalls.h>
58 #include <mono/metadata/debug-helpers.h>
59 #include <mono/metadata/process.h>
60 #include <mono/metadata/environment.h>
61 #include <mono/metadata/profiler-private.h>
62 #include <mono/metadata/locales.h>
63 #include <mono/metadata/filewatcher.h>
64 #include <mono/metadata/char-conversions.h>
65 #include <mono/metadata/security.h>
66 #include <mono/metadata/mono-config.h>
67 #include <mono/metadata/cil-coff.h>
68 #include <mono/metadata/number-formatter.h>
69 #include <mono/metadata/security-manager.h>
70 #include <mono/metadata/security-core-clr.h>
71 #include <mono/metadata/mono-perfcounters.h>
72 #include <mono/metadata/mono-debug.h>
73 #include <mono/metadata/mono-ptr-array.h>
74 #include <mono/metadata/verify-internals.h>
75 #include <mono/io-layer/io-layer.h>
76 #include <mono/utils/strtod.h>
77 #include <mono/utils/monobitset.h>
78 #include <mono/utils/mono-time.h>
79 #include <mono/utils/mono-proclib.h>
80 #include <mono/utils/mono-string.h>
81 #include <mono/utils/mono-error-internals.h>
82 #include <mono/utils/mono-mmap.h>
83 #include <mono/utils/mono-io-portability.h>
85 #if defined (HOST_WIN32)
91 extern MonoString
* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL
;
93 static MonoReflectionAssembly
* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
96 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
);
98 static inline MonoBoolean
99 is_generic_parameter (MonoType
*type
)
101 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
105 mono_class_init_or_throw (MonoClass
*klass
)
107 if (!mono_class_init (klass
))
108 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
112 * We expect a pointer to a char, not a string
115 mono_double_ParseImpl (char *ptr
, double *result
)
117 gchar
*endptr
= NULL
;
124 *result
= strtod (ptr
, &endptr
);
127 /* mono_strtod () is not thread-safe */
128 EnterCriticalSection (&mono_strtod_mutex
);
129 *result
= mono_strtod (ptr
, &endptr
);
130 LeaveCriticalSection (&mono_strtod_mutex
);
134 if (!*ptr
|| (endptr
&& *endptr
))
141 ves_icall_System_Array_GetValueImpl (MonoObject
*this, guint32 pos
)
150 ao
= (MonoArray
*)this;
151 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
153 esize
= mono_array_element_size (ac
);
154 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
156 if (ac
->element_class
->valuetype
)
157 return mono_value_box (this->vtable
->domain
, ac
->element_class
, ea
);
163 ves_icall_System_Array_GetValue (MonoObject
*this, MonoObject
*idxs
)
171 MONO_CHECK_ARG_NULL (idxs
);
173 io
= (MonoArray
*)idxs
;
174 ic
= (MonoClass
*)io
->obj
.vtable
->klass
;
176 ao
= (MonoArray
*)this;
177 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
179 g_assert (ic
->rank
== 1);
180 if (io
->bounds
!= NULL
|| io
->max_length
!= ac
->rank
)
181 mono_raise_exception (mono_get_exception_argument (NULL
, NULL
));
183 ind
= (gint32
*)io
->vector
;
185 if (ao
->bounds
== NULL
) {
186 if (*ind
< 0 || *ind
>= ao
->max_length
)
187 mono_raise_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (this, *ind
);
192 for (i
= 0; i
< ac
->rank
; i
++)
193 if ((ind
[i
] < ao
->bounds
[i
].lower_bound
) ||
194 (ind
[i
] >= (mono_array_lower_bound_t
)ao
->bounds
[i
].length
+ ao
->bounds
[i
].lower_bound
))
195 mono_raise_exception (mono_get_exception_index_out_of_range ());
197 pos
= ind
[0] - ao
->bounds
[0].lower_bound
;
198 for (i
= 1; i
< ac
->rank
; i
++)
199 pos
= pos
*ao
->bounds
[i
].length
+ ind
[i
] -
200 ao
->bounds
[i
].lower_bound
;
202 return ves_icall_System_Array_GetValueImpl (this, pos
);
206 ves_icall_System_Array_SetValueImpl (MonoArray
*this, MonoObject
*value
, guint32 pos
)
208 MonoClass
*ac
, *vc
, *ec
;
220 vc
= value
->vtable
->klass
;
224 ac
= this->obj
.vtable
->klass
;
225 ec
= ac
->element_class
;
227 esize
= mono_array_element_size (ac
);
228 ea
= (gpointer
*)((char*)this->vector
+ (pos
* esize
));
229 va
= (gpointer
*)((char*)value
+ sizeof (MonoObject
));
231 if (mono_class_is_nullable (ec
)) {
232 mono_nullable_init ((guint8
*)ea
, value
, ec
);
237 mono_gc_bzero (ea
, esize
);
241 #define NO_WIDENING_CONVERSION G_STMT_START{\
242 mono_raise_exception (mono_get_exception_argument ( \
243 "value", "not a widening conversion")); \
246 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
247 if (esize < vsize + (extra)) \
248 mono_raise_exception (mono_get_exception_argument ( \
249 "value", "not a widening conversion")); \
252 #define INVALID_CAST G_STMT_START{ \
253 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
254 mono_raise_exception (mono_get_exception_invalid_cast ()); \
257 /* Check element (destination) type. */
258 switch (ec
->byval_arg
.type
) {
259 case MONO_TYPE_STRING
:
260 switch (vc
->byval_arg
.type
) {
261 case MONO_TYPE_STRING
:
267 case MONO_TYPE_BOOLEAN
:
268 switch (vc
->byval_arg
.type
) {
269 case MONO_TYPE_BOOLEAN
:
282 NO_WIDENING_CONVERSION
;
289 if (!ec
->valuetype
) {
290 if (!mono_object_isinst (value
, ec
))
292 mono_gc_wbarrier_set_arrayref (this, ea
, (MonoObject
*)value
);
296 if (mono_object_isinst (value
, ec
)) {
297 if (ec
->has_references
)
298 mono_value_copy (ea
, (char*)value
+ sizeof (MonoObject
), ec
);
300 mono_gc_memmove (ea
, (char *)value
+ sizeof (MonoObject
), esize
);
307 vsize
= mono_class_instance_size (vc
) - sizeof (MonoObject
);
309 et
= ec
->byval_arg
.type
;
310 if (et
== MONO_TYPE_VALUETYPE
&& ec
->byval_arg
.data
.klass
->enumtype
)
311 et
= mono_class_enum_basetype (ec
->byval_arg
.data
.klass
)->type
;
313 vt
= vc
->byval_arg
.type
;
314 if (vt
== MONO_TYPE_VALUETYPE
&& vc
->byval_arg
.data
.klass
->enumtype
)
315 vt
= mono_class_enum_basetype (vc
->byval_arg
.data
.klass
)->type
;
317 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
323 case MONO_TYPE_CHAR: \
324 CHECK_WIDENING_CONVERSION(0); \
325 *(etype *) ea = (etype) u64; \
327 /* You can't assign a signed value to an unsigned array. */ \
332 /* You can't assign a floating point number to an integer array. */ \
335 NO_WIDENING_CONVERSION; \
339 #define ASSIGN_SIGNED(etype) G_STMT_START{\
345 CHECK_WIDENING_CONVERSION(0); \
346 *(etype *) ea = (etype) i64; \
348 /* You can assign an unsigned value to a signed array if the array's */ \
349 /* element size is larger than the value size. */ \
354 case MONO_TYPE_CHAR: \
355 CHECK_WIDENING_CONVERSION(1); \
356 *(etype *) ea = (etype) u64; \
358 /* You can't assign a floating point number to an integer array. */ \
361 NO_WIDENING_CONVERSION; \
365 #define ASSIGN_REAL(etype) G_STMT_START{\
369 CHECK_WIDENING_CONVERSION(0); \
370 *(etype *) ea = (etype) r64; \
372 /* All integer values fit into a floating point array, so we don't */ \
373 /* need to CHECK_WIDENING_CONVERSION here. */ \
378 *(etype *) ea = (etype) i64; \
384 case MONO_TYPE_CHAR: \
385 *(etype *) ea = (etype) u64; \
392 u64
= *(guint8
*) va
;
395 u64
= *(guint16
*) va
;
398 u64
= *(guint32
*) va
;
401 u64
= *(guint64
*) va
;
407 i64
= *(gint16
*) va
;
410 i64
= *(gint32
*) va
;
413 i64
= *(gint64
*) va
;
416 r64
= *(gfloat
*) va
;
419 r64
= *(gdouble
*) va
;
422 u64
= *(guint16
*) va
;
424 case MONO_TYPE_BOOLEAN
:
425 /* Boolean is only compatible with itself. */
438 NO_WIDENING_CONVERSION
;
445 /* If we can't do a direct copy, let's try a widening conversion. */
448 ASSIGN_UNSIGNED (guint16
);
450 ASSIGN_UNSIGNED (guint8
);
452 ASSIGN_UNSIGNED (guint16
);
454 ASSIGN_UNSIGNED (guint32
);
456 ASSIGN_UNSIGNED (guint64
);
458 ASSIGN_SIGNED (gint8
);
460 ASSIGN_SIGNED (gint16
);
462 ASSIGN_SIGNED (gint32
);
464 ASSIGN_SIGNED (gint64
);
466 ASSIGN_REAL (gfloat
);
468 ASSIGN_REAL (gdouble
);
472 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
476 #undef NO_WIDENING_CONVERSION
477 #undef CHECK_WIDENING_CONVERSION
478 #undef ASSIGN_UNSIGNED
484 ves_icall_System_Array_SetValue (MonoArray
*this, MonoObject
*value
,
492 MONO_CHECK_ARG_NULL (idxs
);
494 ic
= idxs
->obj
.vtable
->klass
;
495 ac
= this->obj
.vtable
->klass
;
497 g_assert (ic
->rank
== 1);
498 if (idxs
->bounds
!= NULL
|| idxs
->max_length
!= ac
->rank
)
499 mono_raise_exception (mono_get_exception_argument (NULL
, NULL
));
501 ind
= (gint32
*)idxs
->vector
;
503 if (this->bounds
== NULL
) {
504 if (*ind
< 0 || *ind
>= this->max_length
)
505 mono_raise_exception (mono_get_exception_index_out_of_range ());
507 ves_icall_System_Array_SetValueImpl (this, value
, *ind
);
511 for (i
= 0; i
< ac
->rank
; i
++)
512 if ((ind
[i
] < this->bounds
[i
].lower_bound
) ||
513 (ind
[i
] >= (mono_array_lower_bound_t
)this->bounds
[i
].length
+ this->bounds
[i
].lower_bound
))
514 mono_raise_exception (mono_get_exception_index_out_of_range ());
516 pos
= ind
[0] - this->bounds
[0].lower_bound
;
517 for (i
= 1; i
< ac
->rank
; i
++)
518 pos
= pos
* this->bounds
[i
].length
+ ind
[i
] -
519 this->bounds
[i
].lower_bound
;
521 ves_icall_System_Array_SetValueImpl (this, value
, pos
);
525 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType
*type
, MonoArray
*lengths
, MonoArray
*bounds
)
527 MonoClass
*aklass
, *klass
;
530 gboolean bounded
= FALSE
;
534 MONO_CHECK_ARG_NULL (type
);
535 MONO_CHECK_ARG_NULL (lengths
);
537 MONO_CHECK_ARG (lengths
, mono_array_length (lengths
) > 0);
539 MONO_CHECK_ARG (bounds
, mono_array_length (lengths
) == mono_array_length (bounds
));
541 for (i
= 0; i
< mono_array_length (lengths
); i
++)
542 if (mono_array_get (lengths
, gint32
, i
) < 0)
543 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL
));
545 klass
= mono_class_from_mono_type (type
->type
);
546 mono_class_init_or_throw (klass
);
548 if (bounds
&& (mono_array_length (bounds
) == 1) && (mono_array_get (bounds
, gint32
, 0) != 0))
549 /* vectors are not the same as one dimensional arrays with no-zero bounds */
554 aklass
= mono_bounded_array_class_get (klass
, mono_array_length (lengths
), bounded
);
556 sizes
= alloca (aklass
->rank
* sizeof(intptr_t) * 2);
557 for (i
= 0; i
< aklass
->rank
; ++i
) {
558 sizes
[i
] = mono_array_get (lengths
, guint32
, i
);
560 sizes
[i
+ aklass
->rank
] = mono_array_get (bounds
, guint32
, i
);
562 sizes
[i
+ aklass
->rank
] = 0;
565 array
= mono_array_new_full (mono_object_domain (type
), aklass
, sizes
, (intptr_t*)sizes
+ aklass
->rank
);
571 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType
*type
, MonoArray
*lengths
, MonoArray
*bounds
)
573 MonoClass
*aklass
, *klass
;
576 gboolean bounded
= FALSE
;
580 MONO_CHECK_ARG_NULL (type
);
581 MONO_CHECK_ARG_NULL (lengths
);
583 MONO_CHECK_ARG (lengths
, mono_array_length (lengths
) > 0);
585 MONO_CHECK_ARG (bounds
, mono_array_length (lengths
) == mono_array_length (bounds
));
587 for (i
= 0; i
< mono_array_length (lengths
); i
++)
588 if ((mono_array_get (lengths
, gint64
, i
) < 0) ||
589 (mono_array_get (lengths
, gint64
, i
) > MONO_ARRAY_MAX_INDEX
))
590 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL
));
592 klass
= mono_class_from_mono_type (type
->type
);
593 mono_class_init_or_throw (klass
);
595 if (bounds
&& (mono_array_length (bounds
) == 1) && (mono_array_get (bounds
, gint64
, 0) != 0))
596 /* vectors are not the same as one dimensional arrays with no-zero bounds */
601 aklass
= mono_bounded_array_class_get (klass
, mono_array_length (lengths
), bounded
);
603 sizes
= alloca (aklass
->rank
* sizeof(intptr_t) * 2);
604 for (i
= 0; i
< aklass
->rank
; ++i
) {
605 sizes
[i
] = mono_array_get (lengths
, guint64
, i
);
607 sizes
[i
+ aklass
->rank
] = (mono_array_size_t
) mono_array_get (bounds
, guint64
, i
);
609 sizes
[i
+ aklass
->rank
] = 0;
612 array
= mono_array_new_full (mono_object_domain (type
), aklass
, sizes
, (intptr_t*)sizes
+ aklass
->rank
);
618 ves_icall_System_Array_GetRank (MonoObject
*this)
622 return this->vtable
->klass
->rank
;
626 ves_icall_System_Array_GetLength (MonoArray
*this, gint32 dimension
)
628 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
633 if ((dimension
< 0) || (dimension
>= rank
))
634 mono_raise_exception (mono_get_exception_index_out_of_range ());
636 if (this->bounds
== NULL
)
637 length
= this->max_length
;
639 length
= this->bounds
[dimension
].length
;
641 #ifdef MONO_BIG_ARRAYS
642 if (length
> G_MAXINT32
)
643 mono_raise_exception (mono_get_exception_overflow ());
649 ves_icall_System_Array_GetLongLength (MonoArray
*this, gint32 dimension
)
651 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
655 if ((dimension
< 0) || (dimension
>= rank
))
656 mono_raise_exception (mono_get_exception_index_out_of_range ());
658 if (this->bounds
== NULL
)
659 return this->max_length
;
661 return this->bounds
[dimension
].length
;
665 ves_icall_System_Array_GetLowerBound (MonoArray
*this, gint32 dimension
)
667 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
671 if ((dimension
< 0) || (dimension
>= rank
))
672 mono_raise_exception (mono_get_exception_index_out_of_range ());
674 if (this->bounds
== NULL
)
677 return this->bounds
[dimension
].lower_bound
;
681 ves_icall_System_Array_ClearInternal (MonoArray
*arr
, int idx
, int length
)
683 int sz
= mono_array_element_size (mono_object_class (arr
));
684 mono_gc_bzero (mono_array_addr_with_size (arr
, sz
, idx
), length
* sz
);
688 ves_icall_System_Array_FastCopy (MonoArray
*source
, int source_idx
, MonoArray
* dest
, int dest_idx
, int length
)
693 MonoClass
*src_class
;
694 MonoClass
*dest_class
;
698 if (source
->obj
.vtable
->klass
->rank
!= dest
->obj
.vtable
->klass
->rank
)
701 if (source
->bounds
|| dest
->bounds
)
704 /* there's no integer overflow since mono_array_length returns an unsigned integer */
705 if ((dest_idx
+ length
> mono_array_length (dest
)) ||
706 (source_idx
+ length
> mono_array_length (source
)))
709 src_class
= source
->obj
.vtable
->klass
->element_class
;
710 dest_class
= dest
->obj
.vtable
->klass
->element_class
;
713 * Handle common cases.
716 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
717 if (src_class
== mono_defaults
.object_class
&& dest_class
->valuetype
) {
718 // FIXME: This is racy
722 int has_refs = dest_class->has_references;
723 for (i = source_idx; i < source_idx + length; ++i) {
724 MonoObject *elem = mono_array_get (source, MonoObject*, i);
725 if (elem && !mono_object_isinst (elem, dest_class))
729 element_size = mono_array_element_size (dest->obj.vtable->klass);
730 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
731 for (i = 0; i < length; ++i) {
732 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
733 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
737 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
739 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
745 /* Check if we're copying a char[] <==> (u)short[] */
746 if (src_class
!= dest_class
) {
747 if (dest_class
->valuetype
|| dest_class
->enumtype
|| src_class
->valuetype
|| src_class
->enumtype
)
750 if (mono_class_is_subclass_of (src_class
, dest_class
, FALSE
))
752 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
753 else if (mono_class_is_subclass_of (dest_class
, src_class
, FALSE
)) {
754 // FIXME: This is racy
758 for (i = source_idx; i < source_idx + length; ++i) {
759 MonoObject *elem = mono_array_get (source, MonoObject*, i);
760 if (elem && !mono_object_isinst (elem, dest_class))
768 if (dest_class
->valuetype
) {
769 element_size
= mono_array_element_size (source
->obj
.vtable
->klass
);
770 source_addr
= mono_array_addr_with_size (source
, element_size
, source_idx
);
771 if (dest_class
->has_references
) {
772 mono_value_copy_array (dest
, dest_idx
, source_addr
, length
);
774 dest_addr
= mono_array_addr_with_size (dest
, element_size
, dest_idx
);
775 mono_gc_memmove (dest_addr
, source_addr
, element_size
* length
);
778 mono_array_memcpy_refs (dest
, dest_idx
, source
, source_idx
, length
);
785 ves_icall_System_Array_GetGenericValueImpl (MonoObject
*this, guint32 pos
, gpointer value
)
794 ao
= (MonoArray
*)this;
795 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
797 esize
= mono_array_element_size (ac
);
798 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
800 mono_gc_memmove (value
, ea
, esize
);
804 ves_icall_System_Array_SetGenericValueImpl (MonoObject
*this, guint32 pos
, gpointer value
)
813 ao
= (MonoArray
*)this;
814 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
815 ec
= ac
->element_class
;
817 esize
= mono_array_element_size (ac
);
818 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
820 if (MONO_TYPE_IS_REFERENCE (&ec
->byval_arg
)) {
821 g_assert (esize
== sizeof (gpointer
));
822 mono_gc_wbarrier_generic_store (ea
, *(gpointer
*)value
);
824 g_assert (ec
->inited
);
825 g_assert (esize
== mono_class_value_size (ec
, NULL
));
826 if (ec
->has_references
)
827 mono_gc_wbarrier_value_copy (ea
, value
, 1, ec
);
829 mono_gc_memmove (ea
, value
, esize
);
834 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray
*array
, MonoClassField
*field_handle
)
836 MonoClass
*klass
= array
->obj
.vtable
->klass
;
837 guint32 size
= mono_array_element_size (klass
);
838 MonoType
*type
= mono_type_get_underlying_type (&klass
->element_class
->byval_arg
);
840 const char *field_data
;
842 if (MONO_TYPE_IS_REFERENCE (type
) || type
->type
== MONO_TYPE_VALUETYPE
) {
843 MonoException
*exc
= mono_get_exception_argument("array",
844 "Cannot initialize array of non-primitive type.");
845 mono_raise_exception (exc
);
848 if (!(field_handle
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
)) {
849 MonoException
*exc
= mono_get_exception_argument("field_handle",
850 "Field doesn't have an RVA");
851 mono_raise_exception (exc
);
854 size
*= array
->max_length
;
855 field_data
= mono_field_get_data (field_handle
);
857 if (size
> mono_type_size (field_handle
->type
, &align
)) {
858 MonoException
*exc
= mono_get_exception_argument("field_handle",
859 "Field not large enough to fill array");
860 mono_raise_exception (exc
);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
867 guint ## n *end = (guint ## n *)((char*)src + size); \
869 for (; src < end; data++, src++) { \
870 *data = read ## n (src); \
874 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
876 switch (type
->type
) {
893 memcpy (mono_array_addr (array
, char, 0), field_data
, size
);
897 memcpy (mono_array_addr (array
, char, 0), field_data
, size
);
899 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_R8
) {
902 double *data
= (double*)mono_array_addr (array
, double, 0);
904 for (i
= 0; i
< size
; i
++, data
++) {
914 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
918 return offsetof (MonoString
, chars
);
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject
*obj
)
926 if ((obj
== NULL
) || (! (obj
->vtable
->klass
->valuetype
)))
929 return mono_object_clone (obj
);
933 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType
*handle
)
938 MONO_CHECK_ARG_NULL (handle
);
940 klass
= mono_class_from_mono_type (handle
);
941 MONO_CHECK_ARG (handle
, klass
);
943 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, TRUE
);
945 /* This will call the type constructor */
946 mono_runtime_class_init (vtable
);
950 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage
*image
)
954 mono_image_check_for_module_cctor (image
);
955 if (image
->has_module_cctor
) {
956 MonoClass
*module_klass
= mono_class_get (image
, MONO_TOKEN_TYPE_DEF
| 1);
957 /*It's fine to raise the exception here*/
958 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass
, TRUE
));
963 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
968 /* later make this configurable and per-arch */
969 int min_size
= 4096 * 4 * sizeof (void*);
970 mono_thread_get_stack_bounds (&stack_addr
, &stack_size
);
971 /* if we have no info we are optimistic and assume there is enough room */
974 current
= (guint8
*)&stack_addr
;
975 if (current
> stack_addr
) {
976 if ((current
- stack_addr
) < min_size
)
979 if (current
- (stack_addr
- stack_size
) < min_size
)
986 ves_icall_System_Object_MemberwiseClone (MonoObject
*this)
990 return mono_object_clone (this);
994 ves_icall_System_ValueType_InternalGetHashCode (MonoObject
*this, MonoArray
**fields
)
997 MonoObject
**values
= NULL
;
1001 MonoClassField
* field
;
1004 MONO_ARCH_SAVE_REGS
;
1006 klass
= mono_object_class (this);
1008 if (mono_class_num_fields (klass
) == 0)
1009 return mono_object_hash (this);
1012 * Compute the starting value of the hashcode for fields of primitive
1013 * types, and return the remaining fields in an array to the managed side.
1014 * This way, we can avoid costly reflection operations in managed code.
1017 while ((field
= mono_class_get_fields (klass
, &iter
))) {
1018 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1020 if (mono_field_is_deleted (field
))
1022 /* FIXME: Add more types */
1023 switch (field
->type
->type
) {
1025 result
^= *(gint32
*)((guint8
*)this + field
->offset
);
1027 case MONO_TYPE_STRING
: {
1029 s
= *(MonoString
**)((guint8
*)this + field
->offset
);
1031 result
^= mono_string_hash (s
);
1036 values
= g_newa (MonoObject
*, mono_class_num_fields (klass
));
1037 o
= mono_field_get_value_object (mono_object_domain (this), field
, this);
1038 values
[count
++] = o
;
1044 mono_gc_wbarrier_generic_store (fields
, (MonoObject
*) mono_array_new (mono_domain_get (), mono_defaults
.object_class
, count
));
1045 for (i
= 0; i
< count
; ++i
)
1046 mono_array_setref (*fields
, i
, values
[i
]);
1054 ves_icall_System_ValueType_Equals (MonoObject
*this, MonoObject
*that
, MonoArray
**fields
)
1057 MonoObject
**values
= NULL
;
1059 MonoClassField
* field
;
1063 MONO_ARCH_SAVE_REGS
;
1065 MONO_CHECK_ARG_NULL (that
);
1067 if (this->vtable
!= that
->vtable
)
1070 klass
= mono_object_class (this);
1072 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) && mono_class_enum_basetype (klass
)->type
== MONO_TYPE_I4
)
1073 return (*(gint32
*)((guint8
*)this + sizeof (MonoObject
)) == *(gint32
*)((guint8
*)that
+ sizeof (MonoObject
)));
1076 * Do the comparison for fields of primitive type and return a result if
1077 * possible. Otherwise, return the remaining fields in an array to the
1078 * managed side. This way, we can avoid costly reflection operations in
1083 while ((field
= mono_class_get_fields (klass
, &iter
))) {
1084 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1086 if (mono_field_is_deleted (field
))
1088 /* FIXME: Add more types */
1089 switch (field
->type
->type
) {
1092 case MONO_TYPE_BOOLEAN
:
1093 if (*((guint8
*)this + field
->offset
) != *((guint8
*)that
+ field
->offset
))
1098 case MONO_TYPE_CHAR
:
1099 if (*(gint16
*)((guint8
*)this + field
->offset
) != *(gint16
*)((guint8
*)that
+ field
->offset
))
1104 if (*(gint32
*)((guint8
*)this + field
->offset
) != *(gint32
*)((guint8
*)that
+ field
->offset
))
1109 if (*(gint64
*)((guint8
*)this + field
->offset
) != *(gint64
*)((guint8
*)that
+ field
->offset
))
1113 if (*(float*)((guint8
*)this + field
->offset
) != *(float*)((guint8
*)that
+ field
->offset
))
1117 if (*(double*)((guint8
*)this + field
->offset
) != *(double*)((guint8
*)that
+ field
->offset
))
1122 case MONO_TYPE_STRING
: {
1123 MonoString
*s1
, *s2
;
1124 guint32 s1len
, s2len
;
1125 s1
= *(MonoString
**)((guint8
*)this + field
->offset
);
1126 s2
= *(MonoString
**)((guint8
*)that
+ field
->offset
);
1129 if ((s1
== NULL
) || (s2
== NULL
))
1131 s1len
= mono_string_length (s1
);
1132 s2len
= mono_string_length (s2
);
1136 if (memcmp (mono_string_chars (s1
), mono_string_chars (s2
), s1len
* sizeof (gunichar2
)) != 0)
1142 values
= g_newa (MonoObject
*, mono_class_num_fields (klass
) * 2);
1143 o
= mono_field_get_value_object (mono_object_domain (this), field
, this);
1144 values
[count
++] = o
;
1145 o
= mono_field_get_value_object (mono_object_domain (this), field
, that
);
1146 values
[count
++] = o
;
1149 if (klass
->enumtype
)
1150 /* enums only have one non-static field */
1156 mono_gc_wbarrier_generic_store (fields
, (MonoObject
*) mono_array_new (mono_domain_get (), mono_defaults
.object_class
, count
));
1157 for (i
= 0; i
< count
; ++i
)
1158 mono_array_setref (*fields
, i
, values
[i
]);
1165 static MonoReflectionType
*
1166 ves_icall_System_Object_GetType (MonoObject
*obj
)
1168 MONO_ARCH_SAVE_REGS
;
1170 if (obj
->vtable
->klass
!= mono_defaults
.transparent_proxy_class
)
1171 return mono_type_get_object (mono_object_domain (obj
), &obj
->vtable
->klass
->byval_arg
);
1173 return mono_type_get_object (mono_object_domain (obj
), &((MonoTransparentProxy
*)obj
)->remote_class
->proxy_class
->byval_arg
);
1177 mono_type_type_from_obj (MonoReflectionType
*mtype
, MonoObject
*obj
)
1179 MONO_ARCH_SAVE_REGS
;
1181 mtype
->type
= &obj
->vtable
->klass
->byval_arg
;
1182 g_assert (mtype
->type
->type
);
1186 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder
*mb
, MonoObject
*obj
, gboolean create_open_instance
)
1188 MONO_ARCH_SAVE_REGS
;
1190 MONO_CHECK_ARG_NULL (obj
);
1192 return mono_image_create_token (mb
->dynamic_image
, obj
, create_open_instance
, TRUE
);
1196 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder
*mb
,
1197 MonoReflectionMethod
*method
,
1198 MonoArray
*opt_param_types
)
1200 MONO_ARCH_SAVE_REGS
;
1202 MONO_CHECK_ARG_NULL (method
);
1204 return mono_image_create_method_token (
1205 mb
->dynamic_image
, (MonoObject
*) method
, opt_param_types
);
1209 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
1211 MONO_ARCH_SAVE_REGS
;
1213 mono_image_create_pefile (mb
, file
);
1217 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder
*mb
)
1219 MONO_ARCH_SAVE_REGS
;
1221 mono_image_build_metadata (mb
);
1225 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder
*mb
, MonoObject
*obj
, guint32 token
)
1227 MONO_ARCH_SAVE_REGS
;
1229 mono_image_register_token (mb
->dynamic_image
, token
, obj
);
1233 get_caller (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1235 MonoMethod
**dest
= data
;
1237 /* skip unmanaged frames */
1253 get_executing (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1255 MonoMethod
**dest
= data
;
1257 /* skip unmanaged frames */
1262 if (!strcmp (m
->klass
->name_space
, "System.Reflection"))
1271 get_caller_no_reflection (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1273 MonoMethod
**dest
= data
;
1275 /* skip unmanaged frames */
1279 if (m
->wrapper_type
!= MONO_WRAPPER_NONE
)
1282 if (m
->klass
->image
== mono_defaults
.corlib
&& !strcmp (m
->klass
->name_space
, "System.Reflection"))
1296 static MonoReflectionType
*
1297 type_from_name (const char *str
, MonoBoolean ignoreCase
)
1299 MonoType
*type
= NULL
;
1300 MonoAssembly
*assembly
= NULL
;
1301 MonoTypeNameParse info
;
1302 char *temp_str
= g_strdup (str
);
1303 gboolean type_resolve
= FALSE
;
1305 MONO_ARCH_SAVE_REGS
;
1307 /* mono_reflection_parse_type() mangles the string */
1308 if (!mono_reflection_parse_type (temp_str
, &info
)) {
1309 mono_reflection_free_type_info (&info
);
1314 if (info
.assembly
.name
) {
1315 assembly
= mono_assembly_load (&info
.assembly
, NULL
, NULL
);
1317 MonoMethod
*m
= mono_method_get_last_managed ();
1318 MonoMethod
*dest
= m
;
1320 mono_stack_walk_no_il (get_caller_no_reflection
, &dest
);
1325 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1326 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1327 * to crash. This only seems to happen in some strange remoting
1328 * scenarios and I was unable to figure out what's happening there.
1329 * Dec 10, 2005 - Martin.
1333 assembly
= dest
->klass
->image
->assembly
;
1334 type_resolve
= TRUE
;
1336 g_warning (G_STRLOC
);
1341 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1342 type
= mono_reflection_get_type (assembly
->image
, &info
, ignoreCase
, &type_resolve
);
1345 if (!info
.assembly
.name
&& !type
) /* try mscorlib */
1346 type
= mono_reflection_get_type (NULL
, &info
, ignoreCase
, &type_resolve
);
1348 if (assembly
&& !type
&& type_resolve
) {
1349 type_resolve
= FALSE
; /* This will invoke TypeResolve if not done in the first 'if' */
1350 type
= mono_reflection_get_type (assembly
->image
, &info
, ignoreCase
, &type_resolve
);
1353 mono_reflection_free_type_info (&info
);
1359 return mono_type_get_object (mono_domain_get (), type
);
1363 MonoReflectionType
*
1364 mono_type_get (const char *str
)
1366 char *copy
= g_strdup (str
);
1367 MonoReflectionType
*type
= type_from_name (copy
, FALSE
);
1374 static MonoReflectionType
*
1375 ves_icall_type_from_name (MonoString
*name
,
1376 MonoBoolean throwOnError
,
1377 MonoBoolean ignoreCase
)
1379 char *str
= mono_string_to_utf8 (name
);
1380 MonoReflectionType
*type
;
1382 type
= type_from_name (str
, ignoreCase
);
1385 MonoException
*e
= NULL
;
1388 e
= mono_get_exception_type_load (name
, NULL
);
1390 mono_loader_clear_error ();
1392 mono_raise_exception (e
);
1399 static MonoReflectionType
*
1400 ves_icall_type_from_handle (MonoType
*handle
)
1402 MonoDomain
*domain
= mono_domain_get ();
1404 MONO_ARCH_SAVE_REGS
;
1406 return mono_type_get_object (domain
, handle
);
1410 ves_icall_System_Type_EqualsInternal (MonoReflectionType
*type
, MonoReflectionType
*c
)
1412 MONO_ARCH_SAVE_REGS
;
1414 if (c
&& type
->type
&& c
->type
)
1415 return mono_metadata_type_equal (type
->type
, c
->type
);
1417 return (type
== c
) ? TRUE
: FALSE
;
1420 /* System.TypeCode */
1439 TYPECODE_STRING
= 18
1443 ves_icall_type_GetTypeCodeInternal (MonoReflectionType
*type
)
1445 int t
= type
->type
->type
;
1447 MONO_ARCH_SAVE_REGS
;
1449 if (type
->type
->byref
)
1450 return TYPECODE_OBJECT
;
1454 case MONO_TYPE_VOID
:
1455 return TYPECODE_OBJECT
;
1456 case MONO_TYPE_BOOLEAN
:
1457 return TYPECODE_BOOLEAN
;
1459 return TYPECODE_BYTE
;
1461 return TYPECODE_SBYTE
;
1463 return TYPECODE_UINT16
;
1465 return TYPECODE_INT16
;
1466 case MONO_TYPE_CHAR
:
1467 return TYPECODE_CHAR
;
1471 return TYPECODE_OBJECT
;
1473 return TYPECODE_UINT32
;
1475 return TYPECODE_INT32
;
1477 return TYPECODE_UINT64
;
1479 return TYPECODE_INT64
;
1481 return TYPECODE_SINGLE
;
1483 return TYPECODE_DOUBLE
;
1484 case MONO_TYPE_VALUETYPE
: {
1485 MonoClass
*klass
= type
->type
->data
.klass
;
1487 if (klass
->enumtype
) {
1488 t
= mono_class_enum_basetype (klass
)->type
;
1490 } else if (mono_is_corlib_image (klass
->image
)) {
1491 if (strcmp (klass
->name_space
, "System") == 0) {
1492 if (strcmp (klass
->name
, "Decimal") == 0)
1493 return TYPECODE_DECIMAL
;
1494 else if (strcmp (klass
->name
, "DateTime") == 0)
1495 return TYPECODE_DATETIME
;
1498 return TYPECODE_OBJECT
;
1500 case MONO_TYPE_STRING
:
1501 return TYPECODE_STRING
;
1502 case MONO_TYPE_SZARRAY
:
1503 case MONO_TYPE_ARRAY
:
1504 case MONO_TYPE_OBJECT
:
1506 case MONO_TYPE_MVAR
:
1507 case MONO_TYPE_TYPEDBYREF
:
1508 return TYPECODE_OBJECT
;
1509 case MONO_TYPE_CLASS
:
1511 MonoClass
*klass
= type
->type
->data
.klass
;
1512 if (klass
->image
== mono_defaults
.corlib
&& strcmp (klass
->name_space
, "System") == 0) {
1513 if (strcmp (klass
->name
, "DBNull") == 0)
1514 return TYPECODE_DBNULL
;
1517 return TYPECODE_OBJECT
;
1518 case MONO_TYPE_GENERICINST
:
1519 return TYPECODE_OBJECT
;
1521 g_error ("type 0x%02x not handled in GetTypeCode()", t
);
1527 ves_icall_type_is_subtype_of (MonoReflectionType
*type
, MonoReflectionType
*c
, MonoBoolean check_interfaces
)
1533 MONO_ARCH_SAVE_REGS
;
1535 g_assert (type
!= NULL
);
1537 domain
= ((MonoObject
*)type
)->vtable
->domain
;
1539 if (!c
) /* FIXME: dont know what do do here */
1542 klass
= mono_class_from_mono_type (type
->type
);
1543 klassc
= mono_class_from_mono_type (c
->type
);
1545 /* Interface check requires a more complex setup so we
1546 * only do for them. Otherwise we simply avoid mono_class_init.
1548 if (check_interfaces
) {
1549 mono_class_init_or_throw (klass
);
1550 mono_class_init_or_throw (klassc
);
1551 } else if (!klass
->supertypes
|| !klassc
->supertypes
) {
1552 mono_loader_lock ();
1553 mono_class_setup_supertypes (klass
);
1554 mono_class_setup_supertypes (klassc
);
1555 mono_loader_unlock ();
1558 if (type
->type
->byref
)
1559 return klassc
== mono_defaults
.object_class
;
1561 return mono_class_is_subclass_of (klass
, klassc
, check_interfaces
);
1565 mono_type_is_primitive (MonoType
*type
)
1567 return (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_R8
) ||
1568 type
-> type
== MONO_TYPE_I
|| type
->type
== MONO_TYPE_U
;
1572 mono_type_get_underlying_type_ignore_byref (MonoType
*type
)
1574 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
)
1575 return mono_class_enum_basetype (type
->data
.klass
);
1576 if (type
->type
== MONO_TYPE_GENERICINST
&& type
->data
.generic_class
->container_class
->enumtype
)
1577 return mono_class_enum_basetype (type
->data
.generic_class
->container_class
);
1582 ves_icall_type_is_assignable_from (MonoReflectionType
*type
, MonoReflectionType
*c
)
1588 MONO_ARCH_SAVE_REGS
;
1590 g_assert (type
!= NULL
);
1592 domain
= ((MonoObject
*)type
)->vtable
->domain
;
1594 klass
= mono_class_from_mono_type (type
->type
);
1595 klassc
= mono_class_from_mono_type (c
->type
);
1597 mono_class_init_or_throw (klass
);
1598 mono_class_init_or_throw (klassc
);
1600 if (type
->type
->byref
^ c
->type
->byref
)
1603 if (type
->type
->byref
) {
1604 MonoType
*t
= mono_type_get_underlying_type_ignore_byref (type
->type
);
1605 MonoType
*ot
= mono_type_get_underlying_type_ignore_byref (c
->type
);
1607 klass
= mono_class_from_mono_type (t
);
1608 klassc
= mono_class_from_mono_type (ot
);
1610 if (mono_type_is_primitive (t
)) {
1611 return mono_type_is_primitive (ot
) && klass
->instance_size
== klassc
->instance_size
;
1612 } else if (t
->type
== MONO_TYPE_VAR
|| t
->type
== MONO_TYPE_MVAR
) {
1613 return t
->type
== ot
->type
&& t
->data
.generic_param
->num
== ot
->data
.generic_param
->num
;
1614 } else if (t
->type
== MONO_TYPE_PTR
|| t
->type
== MONO_TYPE_FNPTR
) {
1615 return t
->type
== ot
->type
;
1617 if (ot
->type
== MONO_TYPE_VAR
|| ot
->type
== MONO_TYPE_MVAR
)
1620 if (klass
->valuetype
)
1621 return klass
== klassc
;
1622 return klass
->valuetype
== klassc
->valuetype
;
1625 return mono_class_is_assignable_from (klass
, klassc
);
1629 ves_icall_type_IsInstanceOfType (MonoReflectionType
*type
, MonoObject
*obj
)
1631 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1632 mono_class_init_or_throw (klass
);
1633 return mono_object_isinst (obj
, klass
) != NULL
;
1637 ves_icall_get_attributes (MonoReflectionType
*type
)
1639 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1640 return klass
->flags
;
1643 static MonoReflectionMarshalAsAttribute
*
1644 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField
*field
)
1646 MonoClass
*klass
= field
->field
->parent
;
1647 MonoMarshalType
*info
;
1650 if (klass
->generic_container
||
1651 (klass
->generic_class
&& klass
->generic_class
->context
.class_inst
->is_open
))
1654 info
= mono_marshal_load_type_info (klass
);
1656 for (i
= 0; i
< info
->num_fields
; ++i
) {
1657 if (info
->fields
[i
].field
== field
->field
) {
1658 if (!info
->fields
[i
].mspec
)
1661 return mono_reflection_marshal_as_attribute_from_marshal_spec (field
->object
.vtable
->domain
, klass
, info
->fields
[i
].mspec
);
1668 static MonoReflectionField
*
1669 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField
*handle
, MonoType
*type
)
1671 gboolean found
= FALSE
;
1678 klass
= handle
->parent
;
1680 klass
= mono_class_from_mono_type (type
);
1682 /* Check that the field belongs to the class */
1683 for (k
= klass
; k
; k
= k
->parent
) {
1684 if (k
== handle
->parent
) {
1691 /* The managed code will throw the exception */
1695 return mono_field_get_object (mono_domain_get (), klass
, handle
);
1699 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField
*field
, MonoBoolean optional
)
1702 MonoType
*type
= mono_field_get_type_checked (field
->field
, &error
);
1703 if (!mono_error_ok (&error
))
1704 mono_error_raise_exception (&error
);
1706 return type_array_from_modifiers (field
->field
->parent
->image
, type
, optional
);
1710 vell_icall_get_method_attributes (MonoMethod
*method
)
1712 return method
->flags
;
1716 ves_icall_get_method_info (MonoMethod
*method
, MonoMethodInfo
*info
)
1719 MonoDomain
*domain
= mono_domain_get ();
1720 MonoMethodSignature
* sig
;
1721 MONO_ARCH_SAVE_REGS
;
1723 sig
= mono_method_signature_checked (method
, &error
);
1724 if (!mono_error_ok (&error
))
1725 mono_error_raise_exception (&error
);
1728 MONO_STRUCT_SETREF (info
, parent
, mono_type_get_object (domain
, &method
->klass
->byval_arg
));
1729 MONO_STRUCT_SETREF (info
, ret
, mono_type_get_object (domain
, sig
->ret
));
1730 info
->attrs
= method
->flags
;
1731 info
->implattrs
= method
->iflags
;
1732 if (sig
->call_convention
== MONO_CALL_DEFAULT
)
1733 info
->callconv
= sig
->sentinelpos
>= 0 ? 2 : 1;
1735 if (sig
->call_convention
== MONO_CALL_VARARG
|| sig
->sentinelpos
>= 0)
1740 info
->callconv
|= (sig
->hasthis
<< 5) | (sig
->explicit_this
<< 6);
1744 ves_icall_get_parameter_info (MonoMethod
*method
, MonoReflectionMethod
*member
)
1746 MonoDomain
*domain
= mono_domain_get ();
1748 return mono_param_get_objects_internal (domain
, method
, member
->reftype
? mono_class_from_mono_type (member
->reftype
->type
) : NULL
);
1751 static MonoReflectionMarshalAsAttribute
*
1752 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod
*method
)
1754 MonoDomain
*domain
= mono_domain_get ();
1755 MonoReflectionMarshalAsAttribute
* res
= NULL
;
1756 MonoMarshalSpec
**mspecs
;
1759 mspecs
= g_new (MonoMarshalSpec
*, mono_method_signature (method
)->param_count
+ 1);
1760 mono_method_get_marshal_info (method
, mspecs
);
1763 res
= mono_reflection_marshal_as_attribute_from_marshal_spec (domain
, method
->klass
, mspecs
[0]);
1765 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
1767 mono_metadata_free_marshal_spec (mspecs
[i
]);
1774 ves_icall_MonoField_GetFieldOffset (MonoReflectionField
*field
)
1776 MonoClass
*parent
= field
->field
->parent
;
1777 if (!parent
->size_inited
)
1778 mono_class_init (parent
);
1780 return field
->field
->offset
- sizeof (MonoObject
);
1783 static MonoReflectionType
*
1784 ves_icall_MonoField_GetParentType (MonoReflectionField
*field
, MonoBoolean declaring
)
1787 MONO_ARCH_SAVE_REGS
;
1789 parent
= declaring
? field
->field
->parent
: field
->klass
;
1791 return mono_type_get_object (mono_object_domain (field
), &parent
->byval_arg
);
1795 ves_icall_MonoField_GetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
)
1797 MonoClass
*fklass
= field
->klass
;
1798 MonoClassField
*cf
= field
->field
;
1799 MonoDomain
*domain
= mono_object_domain (field
);
1801 if (fklass
->image
->assembly
->ref_only
)
1802 mono_raise_exception (mono_get_exception_invalid_operation (
1803 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1805 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
1806 mono_security_core_clr_ensure_reflection_access_field (cf
);
1808 return mono_field_get_value_object (domain
, cf
, obj
);
1812 ves_icall_MonoField_SetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
, MonoObject
*value
)
1815 MonoClassField
*cf
= field
->field
;
1819 MONO_ARCH_SAVE_REGS
;
1821 if (field
->klass
->image
->assembly
->ref_only
)
1822 mono_raise_exception (mono_get_exception_invalid_operation (
1823 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1825 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
1826 mono_security_core_clr_ensure_reflection_access_field (cf
);
1828 type
= mono_field_get_type_checked (cf
, &error
);
1829 if (!mono_error_ok (&error
))
1830 mono_error_raise_exception (&error
);
1832 v
= (gchar
*) value
;
1834 switch (type
->type
) {
1837 case MONO_TYPE_BOOLEAN
:
1840 case MONO_TYPE_CHAR
:
1849 case MONO_TYPE_VALUETYPE
:
1852 v
+= sizeof (MonoObject
);
1854 case MONO_TYPE_STRING
:
1855 case MONO_TYPE_OBJECT
:
1856 case MONO_TYPE_CLASS
:
1857 case MONO_TYPE_ARRAY
:
1858 case MONO_TYPE_SZARRAY
:
1861 case MONO_TYPE_GENERICINST
: {
1862 MonoGenericClass
*gclass
= type
->data
.generic_class
;
1863 g_assert (!gclass
->context
.class_inst
->is_open
);
1865 if (mono_class_is_nullable (mono_class_from_mono_type (type
))) {
1866 MonoClass
*nklass
= mono_class_from_mono_type (type
);
1867 MonoObject
*nullable
;
1870 * Convert the boxed vtype into a Nullable structure.
1871 * This is complicated by the fact that Nullables have
1872 * a variable structure.
1874 nullable
= mono_object_new (mono_domain_get (), nklass
);
1876 mono_nullable_init (mono_object_unbox (nullable
), value
, nklass
);
1878 v
= mono_object_unbox (nullable
);
1881 if (gclass
->container_class
->valuetype
&& (v
!= NULL
))
1882 v
+= sizeof (MonoObject
);
1886 g_error ("type 0x%x not handled in "
1887 "ves_icall_FieldInfo_SetValueInternal", type
->type
);
1892 if (type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
1893 MonoVTable
*vtable
= mono_class_vtable_full (mono_object_domain (field
), cf
->parent
, TRUE
);
1894 if (!vtable
->initialized
)
1895 mono_runtime_class_init (vtable
);
1896 mono_field_static_set_value (vtable
, cf
, v
);
1898 mono_field_set_value (obj
, cf
, v
);
1903 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField
*this)
1905 MonoObject
*o
= NULL
;
1906 MonoClassField
*field
= this->field
;
1908 MonoDomain
*domain
= mono_object_domain (this);
1910 MonoTypeEnum def_type
;
1911 const char *def_value
;
1915 MONO_ARCH_SAVE_REGS
;
1917 mono_class_init (field
->parent
);
1919 t
= mono_field_get_type_checked (field
, &error
);
1920 if (!mono_error_ok (&error
))
1921 mono_error_raise_exception (&error
);
1923 if (!(t
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
))
1924 mono_raise_exception (mono_get_exception_invalid_operation (NULL
));
1926 if (field
->parent
->image
->dynamic
) {
1928 g_assert_not_reached ();
1931 def_value
= mono_class_get_field_default_value (field
, &def_type
);
1933 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1937 case MONO_TYPE_BOOLEAN
:
1940 case MONO_TYPE_CHAR
:
1948 case MONO_TYPE_R8
: {
1951 /* boxed value type */
1952 t
= g_new0 (MonoType
, 1);
1954 klass
= mono_class_from_mono_type (t
);
1956 o
= mono_object_new (domain
, klass
);
1957 v
= ((gchar
*) o
) + sizeof (MonoObject
);
1958 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, v
);
1961 case MONO_TYPE_STRING
:
1962 case MONO_TYPE_CLASS
:
1963 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, &o
);
1966 g_assert_not_reached ();
1972 static MonoReflectionType
*
1973 ves_icall_MonoField_ResolveType (MonoReflectionField
*ref_field
)
1976 MonoClassField
*field
= ref_field
->field
;
1977 MonoType
*type
= mono_field_get_type_checked (field
, &error
);
1978 if (!mono_error_ok (&error
))
1979 mono_error_raise_exception (&error
);
1980 return mono_type_get_object (mono_object_domain (ref_field
), type
);
1983 static MonoReflectionType
*
1984 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod
*rmethod
)
1986 MonoMethod
*method
= rmethod
->method
.method
;
1988 return mono_type_get_object (mono_object_domain (rmethod
), &method
->klass
->byval_arg
);
1991 /* From MonoProperty.cs */
1993 PInfo_Attributes
= 1,
1994 PInfo_GetMethod
= 1 << 1,
1995 PInfo_SetMethod
= 1 << 2,
1996 PInfo_ReflectedType
= 1 << 3,
1997 PInfo_DeclaringType
= 1 << 4,
2002 ves_icall_get_property_info (MonoReflectionProperty
*property
, MonoPropertyInfo
*info
, PInfo req_info
)
2004 MonoDomain
*domain
= mono_object_domain (property
);
2006 MONO_ARCH_SAVE_REGS
;
2008 if ((req_info
& PInfo_ReflectedType
) != 0)
2009 MONO_STRUCT_SETREF (info
, parent
, mono_type_get_object (domain
, &property
->klass
->byval_arg
));
2010 if ((req_info
& PInfo_DeclaringType
) != 0)
2011 MONO_STRUCT_SETREF (info
, declaring_type
, mono_type_get_object (domain
, &property
->property
->parent
->byval_arg
));
2013 if ((req_info
& PInfo_Name
) != 0)
2014 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, property
->property
->name
));
2016 if ((req_info
& PInfo_Attributes
) != 0)
2017 info
->attrs
= property
->property
->attrs
;
2019 if ((req_info
& PInfo_GetMethod
) != 0)
2020 MONO_STRUCT_SETREF (info
, get
, property
->property
->get
?
2021 mono_method_get_object (domain
, property
->property
->get
, property
->klass
): NULL
);
2023 if ((req_info
& PInfo_SetMethod
) != 0)
2024 MONO_STRUCT_SETREF (info
, set
, property
->property
->set
?
2025 mono_method_get_object (domain
, property
->property
->set
, property
->klass
): NULL
);
2027 * There may be other methods defined for properties, though, it seems they are not exposed
2028 * in the reflection API
2033 ves_icall_get_event_info (MonoReflectionMonoEvent
*event
, MonoEventInfo
*info
)
2035 MonoDomain
*domain
= mono_object_domain (event
);
2037 MONO_ARCH_SAVE_REGS
;
2039 MONO_STRUCT_SETREF (info
, reflected_type
, mono_type_get_object (domain
, &event
->klass
->byval_arg
));
2040 MONO_STRUCT_SETREF (info
, declaring_type
, mono_type_get_object (domain
, &event
->event
->parent
->byval_arg
));
2042 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, event
->event
->name
));
2043 info
->attrs
= event
->event
->attrs
;
2044 MONO_STRUCT_SETREF (info
, add_method
, event
->event
->add
? mono_method_get_object (domain
, event
->event
->add
, NULL
): NULL
);
2045 MONO_STRUCT_SETREF (info
, remove_method
, event
->event
->remove
? mono_method_get_object (domain
, event
->event
->remove
, NULL
): NULL
);
2046 MONO_STRUCT_SETREF (info
, raise_method
, event
->event
->raise
? mono_method_get_object (domain
, event
->event
->raise
, NULL
): NULL
);
2048 #ifndef MONO_SMALL_CONFIG
2049 if (event
->event
->other
) {
2051 while (event
->event
->other
[n
])
2053 MONO_STRUCT_SETREF (info
, other_methods
, mono_array_new (domain
, mono_defaults
.method_info_class
, n
));
2055 for (i
= 0; i
< n
; i
++)
2056 mono_array_setref (info
->other_methods
, i
, mono_method_get_object (domain
, event
->event
->other
[i
], NULL
));
2062 collect_interfaces (MonoClass
*klass
, GHashTable
*ifaces
, MonoError
*error
)
2067 mono_class_setup_interfaces (klass
, error
);
2068 if (!mono_error_ok (error
))
2071 for (i
= 0; i
< klass
->interface_count
; i
++) {
2072 ic
= klass
->interfaces
[i
];
2073 g_hash_table_insert (ifaces
, ic
, ic
);
2075 collect_interfaces (ic
, ifaces
, error
);
2076 if (!mono_error_ok (error
))
2082 MonoArray
*iface_array
;
2083 MonoGenericContext
*context
;
2087 } FillIfaceArrayData
;
2090 fill_iface_array (gpointer key
, gpointer value
, gpointer user_data
)
2092 FillIfaceArrayData
*data
= user_data
;
2093 MonoClass
*ic
= key
;
2094 MonoType
*ret
= &ic
->byval_arg
, *inflated
= NULL
;
2096 if (!mono_error_ok (data
->error
))
2099 if (data
->context
&& ic
->generic_class
&& ic
->generic_class
->context
.class_inst
->is_open
) {
2100 inflated
= ret
= mono_class_inflate_generic_type_checked (ret
, data
->context
, data
->error
);
2101 if (!mono_error_ok (data
->error
))
2105 mono_array_setref (data
->iface_array
, data
->next_idx
++, mono_type_get_object (data
->domain
, ret
));
2108 mono_metadata_free_type (inflated
);
2112 ves_icall_Type_GetInterfaces (MonoReflectionType
* type
)
2115 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2117 FillIfaceArrayData data
= { 0 };
2120 GHashTable
*iface_hash
= g_hash_table_new (NULL
, NULL
);
2122 if (class->generic_class
&& class->generic_class
->context
.class_inst
->is_open
) {
2123 data
.context
= mono_class_get_context (class);
2124 class = class->generic_class
->container_class
;
2127 for (parent
= class; parent
; parent
= parent
->parent
) {
2128 mono_class_setup_interfaces (parent
, &error
);
2129 if (!mono_error_ok (&error
))
2131 collect_interfaces (parent
, iface_hash
, &error
);
2132 if (!mono_error_ok (&error
))
2136 data
.error
= &error
;
2137 data
.domain
= mono_object_domain (type
);
2139 len
= g_hash_table_size (iface_hash
);
2141 g_hash_table_destroy (iface_hash
);
2142 if (!data
.domain
->empty_types
)
2143 data
.domain
->empty_types
= mono_array_new_cached (data
.domain
, mono_defaults
.monotype_class
, 0);
2144 return data
.domain
->empty_types
;
2147 data
.iface_array
= mono_array_new_cached (data
.domain
, mono_defaults
.monotype_class
, len
);
2148 g_hash_table_foreach (iface_hash
, fill_iface_array
, &data
);
2149 if (!mono_error_ok (&error
))
2152 g_hash_table_destroy (iface_hash
);
2153 return data
.iface_array
;
2156 g_hash_table_destroy (iface_hash
);
2157 mono_error_raise_exception (&error
);
2162 ves_icall_Type_GetInterfaceMapData (MonoReflectionType
*type
, MonoReflectionType
*iface
, MonoArray
**targets
, MonoArray
**methods
)
2164 gboolean variance_used
;
2165 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2166 MonoClass
*iclass
= mono_class_from_mono_type (iface
->type
);
2167 MonoReflectionMethod
*member
;
2170 int i
= 0, len
, ioffset
;
2173 MONO_ARCH_SAVE_REGS
;
2174 mono_class_init_or_throw (class);
2175 mono_class_init_or_throw (iclass
);
2177 mono_class_setup_vtable (class);
2179 ioffset
= mono_class_interface_offset_with_variance (class, iclass
, &variance_used
);
2183 len
= mono_class_num_methods (iclass
);
2184 domain
= mono_object_domain (type
);
2185 mono_gc_wbarrier_generic_store (targets
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.method_info_class
, len
));
2186 mono_gc_wbarrier_generic_store (methods
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.method_info_class
, len
));
2188 while ((method
= mono_class_get_methods (iclass
, &iter
))) {
2189 member
= mono_method_get_object (domain
, method
, iclass
);
2190 mono_array_setref (*methods
, i
, member
);
2191 member
= mono_method_get_object (domain
, class->vtable
[i
+ ioffset
], class);
2192 mono_array_setref (*targets
, i
, member
);
2199 ves_icall_Type_GetPacking (MonoReflectionType
*type
, guint32
*packing
, guint32
*size
)
2201 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2202 mono_class_init_or_throw (klass
);
2204 if (klass
->image
->dynamic
) {
2205 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)type
;
2206 *packing
= tb
->packing_size
;
2207 *size
= tb
->class_size
;
2209 mono_metadata_packing_from_typedef (klass
->image
, klass
->type_token
, packing
, size
);
2213 static MonoReflectionType
*
2214 ves_icall_MonoType_GetElementType (MonoReflectionType
*type
)
2218 MONO_ARCH_SAVE_REGS
;
2220 if (!type
->type
->byref
&& type
->type
->type
== MONO_TYPE_SZARRAY
)
2221 return mono_type_get_object (mono_object_domain (type
), &type
->type
->data
.klass
->byval_arg
);
2223 class = mono_class_from_mono_type (type
->type
);
2224 mono_class_init_or_throw (class);
2226 // GetElementType should only return a type for:
2227 // Array Pointer PassedByRef
2228 if (type
->type
->byref
)
2229 return mono_type_get_object (mono_object_domain (type
), &class->byval_arg
);
2230 else if (class->element_class
&& MONO_CLASS_IS_ARRAY (class))
2231 return mono_type_get_object (mono_object_domain (type
), &class->element_class
->byval_arg
);
2232 else if (class->element_class
&& type
->type
->type
== MONO_TYPE_PTR
)
2233 return mono_type_get_object (mono_object_domain (type
), &class->element_class
->byval_arg
);
2238 static MonoReflectionType
*
2239 ves_icall_get_type_parent (MonoReflectionType
*type
)
2241 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2242 return class->parent
? mono_type_get_object (mono_object_domain (type
), &class->parent
->byval_arg
): NULL
;
2246 ves_icall_type_ispointer (MonoReflectionType
*type
)
2248 MONO_ARCH_SAVE_REGS
;
2250 return type
->type
->type
== MONO_TYPE_PTR
;
2254 ves_icall_type_isprimitive (MonoReflectionType
*type
)
2256 MONO_ARCH_SAVE_REGS
;
2258 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
)));
2262 ves_icall_type_isbyref (MonoReflectionType
*type
)
2264 MONO_ARCH_SAVE_REGS
;
2266 return type
->type
->byref
;
2270 ves_icall_type_iscomobject (MonoReflectionType
*type
)
2272 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2273 mono_class_init_or_throw (klass
);
2275 return (klass
&& klass
->is_com_object
);
2278 static MonoReflectionModule
*
2279 ves_icall_MonoType_get_Module (MonoReflectionType
*type
)
2281 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2282 return mono_module_get_object (mono_object_domain (type
), class->image
);
2285 static MonoReflectionAssembly
*
2286 ves_icall_MonoType_get_Assembly (MonoReflectionType
*type
)
2288 MonoDomain
*domain
= mono_domain_get ();
2289 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2290 return mono_assembly_get_object (domain
, class->image
->assembly
);
2293 static MonoReflectionType
*
2294 ves_icall_MonoType_get_DeclaringType (MonoReflectionType
*type
)
2296 MonoDomain
*domain
= mono_domain_get ();
2299 MONO_ARCH_SAVE_REGS
;
2301 if (type
->type
->byref
)
2303 if (type
->type
->type
== MONO_TYPE_VAR
)
2304 class = mono_type_get_generic_param_owner (type
->type
)->owner
.klass
;
2305 else if (type
->type
->type
== MONO_TYPE_MVAR
)
2306 class = mono_type_get_generic_param_owner (type
->type
)->owner
.method
->klass
;
2308 class = mono_class_from_mono_type (type
->type
)->nested_in
;
2310 return class ? mono_type_get_object (domain
, &class->byval_arg
) : NULL
;
2314 ves_icall_MonoType_get_Name (MonoReflectionType
*type
)
2316 MonoDomain
*domain
= mono_domain_get ();
2317 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2319 if (type
->type
->byref
) {
2320 char *n
= g_strdup_printf ("%s&", class->name
);
2321 MonoString
*res
= mono_string_new (domain
, n
);
2327 return mono_string_new (domain
, class->name
);
2332 ves_icall_MonoType_get_Namespace (MonoReflectionType
*type
)
2334 MonoDomain
*domain
= mono_domain_get ();
2335 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2337 while (class->nested_in
)
2338 class = class->nested_in
;
2340 if (class->name_space
[0] == '\0')
2343 return mono_string_new (domain
, class->name_space
);
2347 ves_icall_MonoType_GetArrayRank (MonoReflectionType
*type
)
2351 if (type
->type
->type
!= MONO_TYPE_ARRAY
&& type
->type
->type
!= MONO_TYPE_SZARRAY
)
2352 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2354 class = mono_class_from_mono_type (type
->type
);
2360 ves_icall_MonoType_GetGenericArguments (MonoReflectionType
*type
)
2363 MonoClass
*klass
, *pklass
;
2364 MonoDomain
*domain
= mono_object_domain (type
);
2365 MonoVTable
*array_vtable
= mono_class_vtable_full (domain
, mono_array_class_get_cached (mono_defaults
.systemtype_class
, 1), TRUE
);
2367 MONO_ARCH_SAVE_REGS
;
2369 klass
= mono_class_from_mono_type (type
->type
);
2371 if (klass
->generic_container
) {
2372 MonoGenericContainer
*container
= klass
->generic_container
;
2373 res
= mono_array_new_specific (array_vtable
, container
->type_argc
);
2374 for (i
= 0; i
< container
->type_argc
; ++i
) {
2375 pklass
= mono_class_from_generic_parameter (mono_generic_container_get_param (container
, i
), klass
->image
, FALSE
);
2376 mono_array_setref (res
, i
, mono_type_get_object (domain
, &pklass
->byval_arg
));
2378 } else if (klass
->generic_class
) {
2379 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
2380 res
= mono_array_new_specific (array_vtable
, inst
->type_argc
);
2381 for (i
= 0; i
< inst
->type_argc
; ++i
)
2382 mono_array_setref (res
, i
, mono_type_get_object (domain
, inst
->type_argv
[i
]));
2384 res
= mono_array_new_specific (array_vtable
, 0);
2390 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType
*type
)
2393 MONO_ARCH_SAVE_REGS
;
2395 if (!IS_MONOTYPE (type
))
2398 if (type
->type
->byref
)
2401 klass
= mono_class_from_mono_type (type
->type
);
2402 return klass
->generic_container
!= NULL
;
2405 static MonoReflectionType
*
2406 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType
*type
)
2409 MONO_ARCH_SAVE_REGS
;
2411 if (type
->type
->byref
)
2414 klass
= mono_class_from_mono_type (type
->type
);
2416 if (klass
->generic_container
) {
2417 return type
; /* check this one */
2419 if (klass
->generic_class
) {
2420 MonoClass
*generic_class
= klass
->generic_class
->container_class
;
2423 tb
= mono_class_get_ref_info (generic_class
);
2425 if (generic_class
->wastypebuilder
&& tb
)
2428 return mono_type_get_object (mono_object_domain (type
), &generic_class
->byval_arg
);
2433 static MonoReflectionType
*
2434 ves_icall_Type_MakeGenericType (MonoReflectionType
*type
, MonoArray
*type_array
)
2437 MonoType
*geninst
, **types
;
2440 g_assert (IS_MONOTYPE (type
));
2441 mono_class_init_or_throw (mono_class_from_mono_type (type
->type
));
2443 count
= mono_array_length (type_array
);
2444 types
= g_new0 (MonoType
*, count
);
2446 for (i
= 0; i
< count
; i
++) {
2447 MonoReflectionType
*t
= mono_array_get (type_array
, gpointer
, i
);
2448 types
[i
] = t
->type
;
2451 geninst
= mono_reflection_bind_generic_parameters (type
, count
, types
);
2456 class = mono_class_from_mono_type (geninst
);
2458 /*we might inflate to the GTD*/
2459 if (class->generic_class
&& !mono_verifier_class_is_valid_generic_instantiation (class))
2460 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2462 return mono_type_get_object (mono_object_domain (type
), geninst
);
2466 ves_icall_Type_get_IsGenericInstance (MonoReflectionType
*type
)
2469 MONO_ARCH_SAVE_REGS
;
2471 if (type
->type
->byref
)
2474 klass
= mono_class_from_mono_type (type
->type
);
2476 return klass
->generic_class
!= NULL
;
2480 ves_icall_Type_get_IsGenericType (MonoReflectionType
*type
)
2483 MONO_ARCH_SAVE_REGS
;
2485 if (!IS_MONOTYPE (type
))
2488 if (type
->type
->byref
)
2491 klass
= mono_class_from_mono_type (type
->type
);
2492 return klass
->generic_class
!= NULL
|| klass
->generic_container
!= NULL
;
2496 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType
*type
)
2498 MONO_ARCH_SAVE_REGS
;
2500 if (!IS_MONOTYPE (type
))
2503 if (is_generic_parameter (type
->type
))
2504 return mono_type_get_generic_param_num (type
->type
);
2508 static GenericParameterAttributes
2509 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType
*type
)
2511 MONO_ARCH_SAVE_REGS
;
2513 g_assert (IS_MONOTYPE (type
));
2514 g_assert (is_generic_parameter (type
->type
));
2515 return mono_generic_param_info (type
->type
->data
.generic_param
)->flags
;
2519 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType
*type
)
2521 MonoGenericParamInfo
*param_info
;
2527 MONO_ARCH_SAVE_REGS
;
2529 g_assert (IS_MONOTYPE (type
));
2531 domain
= mono_object_domain (type
);
2532 param_info
= mono_generic_param_info (type
->type
->data
.generic_param
);
2533 for (count
= 0, ptr
= param_info
->constraints
; ptr
&& *ptr
; ptr
++, count
++)
2536 res
= mono_array_new (domain
, mono_defaults
.monotype_class
, count
);
2537 for (i
= 0; i
< count
; i
++)
2538 mono_array_setref (res
, i
, mono_type_get_object (domain
, ¶m_info
->constraints
[i
]->byval_arg
));
2545 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType
*type
)
2547 MONO_ARCH_SAVE_REGS
;
2548 return is_generic_parameter (type
->type
);
2552 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder
*tb
)
2554 MONO_ARCH_SAVE_REGS
;
2555 return is_generic_parameter (tb
->type
.type
);
2559 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType
*enumtype
,
2560 MonoReflectionType
*t
)
2562 enumtype
->type
= t
->type
;
2565 static MonoReflectionMethod
*
2566 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType
*type
,
2567 MonoReflectionMethod
* generic
)
2574 MONO_ARCH_SAVE_REGS
;
2576 domain
= ((MonoObject
*)type
)->vtable
->domain
;
2578 klass
= mono_class_from_mono_type (type
->type
);
2579 mono_class_init_or_throw (klass
);
2582 while ((method
= mono_class_get_methods (klass
, &iter
))) {
2583 if (method
->token
== generic
->method
->token
)
2584 return mono_method_get_object (domain
, method
, klass
);
2592 static MonoReflectionMethod
*
2593 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType
*ref_type
)
2596 MonoType
*type
= ref_type
->type
;
2598 MONO_ARCH_SAVE_REGS
;
2600 if (type
->byref
|| (type
->type
!= MONO_TYPE_MVAR
&& type
->type
!= MONO_TYPE_VAR
))
2601 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2602 if (type
->type
== MONO_TYPE_VAR
)
2605 method
= mono_type_get_generic_param_owner (type
)->owner
.method
;
2607 return mono_method_get_object (mono_object_domain (ref_type
), method
, method
->klass
);
2610 static MonoReflectionDllImportAttribute
*
2611 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod
*method
)
2613 static MonoClass
*DllImportAttributeClass
= NULL
;
2614 MonoDomain
*domain
= mono_domain_get ();
2615 MonoReflectionDllImportAttribute
*attr
;
2616 MonoImage
*image
= method
->klass
->image
;
2617 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)method
;
2618 MonoTableInfo
*tables
= image
->tables
;
2619 MonoTableInfo
*im
= &tables
[MONO_TABLE_IMPLMAP
];
2620 MonoTableInfo
*mr
= &tables
[MONO_TABLE_MODULEREF
];
2621 guint32 im_cols
[MONO_IMPLMAP_SIZE
];
2622 guint32 scope_token
;
2623 const char *import
= NULL
;
2624 const char *scope
= NULL
;
2627 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
2630 if (!DllImportAttributeClass
) {
2631 DllImportAttributeClass
=
2632 mono_class_from_name (mono_defaults
.corlib
,
2633 "System.Runtime.InteropServices", "DllImportAttribute");
2634 g_assert (DllImportAttributeClass
);
2637 if (method
->klass
->image
->dynamic
) {
2638 MonoReflectionMethodAux
*method_aux
=
2639 g_hash_table_lookup (
2640 ((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
2642 import
= method_aux
->dllentry
;
2643 scope
= method_aux
->dll
;
2646 if (!import
|| !scope
) {
2647 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2652 if (piinfo
->implmap_idx
) {
2653 mono_metadata_decode_row (im
, piinfo
->implmap_idx
- 1, im_cols
, MONO_IMPLMAP_SIZE
);
2655 piinfo
->piflags
= im_cols
[MONO_IMPLMAP_FLAGS
];
2656 import
= mono_metadata_string_heap (image
, im_cols
[MONO_IMPLMAP_NAME
]);
2657 scope_token
= mono_metadata_decode_row_col (mr
, im_cols
[MONO_IMPLMAP_SCOPE
] - 1, MONO_MODULEREF_NAME
);
2658 scope
= mono_metadata_string_heap (image
, scope_token
);
2661 flags
= piinfo
->piflags
;
2663 attr
= (MonoReflectionDllImportAttribute
*)mono_object_new (domain
, DllImportAttributeClass
);
2665 MONO_OBJECT_SETREF (attr
, dll
, mono_string_new (domain
, scope
));
2666 MONO_OBJECT_SETREF (attr
, entry_point
, mono_string_new (domain
, import
));
2667 attr
->call_conv
= (flags
& 0x700) >> 8;
2668 attr
->charset
= ((flags
& 0x6) >> 1) + 1;
2669 if (attr
->charset
== 1)
2671 attr
->exact_spelling
= (flags
& 0x1) != 0;
2672 attr
->set_last_error
= (flags
& 0x40) != 0;
2673 attr
->best_fit_mapping
= (flags
& 0x30) == 0x10;
2674 attr
->throw_on_unmappable
= (flags
& 0x3000) == 0x1000;
2675 attr
->preserve_sig
= FALSE
;
2680 static MonoReflectionMethod
*
2681 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod
*method
)
2683 MonoMethodInflated
*imethod
;
2686 MONO_ARCH_SAVE_REGS
;
2688 if (method
->method
->is_generic
)
2691 if (!method
->method
->is_inflated
)
2694 imethod
= (MonoMethodInflated
*) method
->method
;
2696 result
= imethod
->declaring
;
2697 /* Not a generic method. */
2698 if (!result
->is_generic
)
2701 if (method
->method
->klass
->image
->dynamic
) {
2702 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->method
->klass
->image
;
2703 MonoReflectionMethod
*res
;
2706 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2707 * the dynamic case as well ?
2709 mono_loader_lock ();
2710 res
= mono_g_hash_table_lookup (image
->generic_def_objects
, imethod
);
2711 mono_loader_unlock ();
2717 if (imethod
->context
.class_inst
) {
2718 MonoClass
*klass
= ((MonoMethod
*) imethod
)->klass
;
2719 /*Generic methods gets the context of the GTD.*/
2720 if (mono_class_get_context (klass
))
2721 result
= mono_class_inflate_generic_method_full (result
, klass
, mono_class_get_context (klass
));
2724 return mono_method_get_object (mono_object_domain (method
), result
, NULL
);
2728 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod
*method
)
2730 MONO_ARCH_SAVE_REGS
;
2732 return mono_method_signature (method
->method
)->generic_param_count
!= 0;
2736 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod
*method
)
2738 MONO_ARCH_SAVE_REGS
;
2740 return method
->method
->is_generic
;
2744 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod
*method
)
2749 MONO_ARCH_SAVE_REGS
;
2751 domain
= mono_object_domain (method
);
2753 if (method
->method
->is_inflated
) {
2754 MonoGenericInst
*inst
= mono_method_get_context (method
->method
)->method_inst
;
2757 count
= inst
->type_argc
;
2758 res
= mono_array_new (domain
, mono_defaults
.systemtype_class
, count
);
2760 for (i
= 0; i
< count
; i
++)
2761 mono_array_setref (res
, i
, mono_type_get_object (domain
, inst
->type_argv
[i
]));
2767 count
= mono_method_signature (method
->method
)->generic_param_count
;
2768 res
= mono_array_new (domain
, mono_defaults
.systemtype_class
, count
);
2770 for (i
= 0; i
< count
; i
++) {
2771 MonoGenericContainer
*container
= mono_method_get_generic_container (method
->method
);
2772 MonoGenericParam
*param
= mono_generic_container_get_param (container
, i
);
2773 MonoClass
*pklass
= mono_class_from_generic_parameter (
2774 param
, method
->method
->klass
->image
, TRUE
);
2775 mono_array_setref (res
, i
,
2776 mono_type_get_object (domain
, &pklass
->byval_arg
));
2783 ves_icall_InternalInvoke (MonoReflectionMethod
*method
, MonoObject
*this, MonoArray
*params
, MonoException
**exc
)
2786 * Invoke from reflection is supposed to always be a virtual call (the API
2787 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2788 * greater flexibility.
2790 MonoMethod
*m
= method
->method
;
2794 MONO_ARCH_SAVE_REGS
;
2798 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
2799 mono_security_core_clr_ensure_reflection_access_method (m
);
2801 if (!(m
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
2802 if (!mono_class_vtable_full (mono_object_domain (method
), m
->klass
, FALSE
)) {
2803 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_class_get_exception_for_failure (m
->klass
));
2808 if (!mono_object_isinst (this, m
->klass
)) {
2809 char *this_name
= mono_type_get_full_name (mono_object_get_class (this));
2810 char *target_name
= mono_type_get_full_name (m
->klass
);
2811 char *msg
= g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name
, target_name
);
2812 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", msg
));
2814 g_free (target_name
);
2818 m
= mono_object_get_virtual_method (this, m
);
2819 /* must pass the pointer to the value for valuetype methods */
2820 if (m
->klass
->valuetype
)
2821 obj
= mono_object_unbox (this);
2822 } else if (strcmp (m
->name
, ".ctor") && !m
->wrapper_type
) {
2823 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Non-static method requires a target."));
2828 pcount
= params
? mono_array_length (params
): 0;
2829 if (pcount
!= mono_method_signature (m
)->param_count
) {
2830 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name (mono_defaults
.corlib
, "System.Reflection", "TargetParameterCountException"));
2834 if ((m
->klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
) && !strcmp (m
->name
, ".ctor") && !this) {
2835 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."));
2839 if (m
->klass
->image
->assembly
->ref_only
) {
2840 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."));
2844 if (m
->klass
->rank
&& !strcmp (m
->name
, ".ctor")) {
2847 intptr_t *lower_bounds
;
2848 pcount
= mono_array_length (params
);
2849 lengths
= alloca (sizeof (uintptr_t) * pcount
);
2850 /* Note: the synthetized array .ctors have int32 as argument type */
2851 for (i
= 0; i
< pcount
; ++i
)
2852 lengths
[i
] = *(int32_t*) ((char*)mono_array_get (params
, gpointer
, i
) + sizeof (MonoObject
));
2854 if (m
->klass
->rank
== pcount
) {
2855 /* Only lengths provided. */
2856 lower_bounds
= NULL
;
2858 g_assert (pcount
== (m
->klass
->rank
* 2));
2859 /* lower bounds are first. */
2860 lower_bounds
= (intptr_t*)lengths
;
2861 lengths
+= m
->klass
->rank
;
2864 return (MonoObject
*)mono_array_new_full (mono_object_domain (params
), m
->klass
, lengths
, lower_bounds
);
2866 return mono_runtime_invoke_array (m
, obj
, params
, NULL
);
2870 ves_icall_InternalExecute (MonoReflectionMethod
*method
, MonoObject
*this, MonoArray
*params
, MonoArray
**outArgs
)
2872 MonoDomain
*domain
= mono_object_domain (method
);
2873 MonoMethod
*m
= method
->method
;
2874 MonoMethodSignature
*sig
= mono_method_signature (m
);
2875 MonoArray
*out_args
;
2877 int i
, j
, outarg_count
= 0;
2879 MONO_ARCH_SAVE_REGS
;
2881 if (m
->klass
== mono_defaults
.object_class
) {
2883 if (!strcmp (m
->name
, "FieldGetter")) {
2884 MonoClass
*k
= this->vtable
->klass
;
2888 /* If this is a proxy, then it must be a CBO */
2889 if (k
== mono_defaults
.transparent_proxy_class
) {
2890 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
2891 this = tp
->rp
->unwrapped_server
;
2893 k
= this->vtable
->klass
;
2896 name
= mono_array_get (params
, MonoString
*, 1);
2897 str
= mono_string_to_utf8 (name
);
2900 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
2902 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2903 if (field_klass
->valuetype
)
2904 result
= mono_value_box (domain
, field_klass
, (char *)this + field
->offset
);
2906 result
= *((gpointer
*)((char *)this + field
->offset
));
2908 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 1);
2909 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2910 mono_array_setref (out_args
, 0, result
);
2918 g_assert_not_reached ();
2920 } else if (!strcmp (m
->name
, "FieldSetter")) {
2921 MonoClass
*k
= this->vtable
->klass
;
2927 /* If this is a proxy, then it must be a CBO */
2928 if (k
== mono_defaults
.transparent_proxy_class
) {
2929 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
2930 this = tp
->rp
->unwrapped_server
;
2932 k
= this->vtable
->klass
;
2935 name
= mono_array_get (params
, MonoString
*, 1);
2936 str
= mono_string_to_utf8 (name
);
2939 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
2941 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2942 MonoObject
*val
= mono_array_get (params
, gpointer
, 2);
2944 if (field_klass
->valuetype
) {
2945 size
= mono_type_size (field
->type
, &align
);
2946 g_assert (size
== mono_class_value_size (field_klass
, NULL
));
2947 mono_gc_wbarrier_value_copy ((char *)this + field
->offset
, (char*)val
+ sizeof (MonoObject
), 1, field_klass
);
2949 mono_gc_wbarrier_set_field (this, (char*)this + field
->offset
, val
);
2952 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 0);
2953 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2963 g_assert_not_reached ();
2968 for (i
= 0; i
< mono_array_length (params
); i
++) {
2969 if (sig
->params
[i
]->byref
)
2973 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, outarg_count
);
2975 /* handle constructors only for objects already allocated */
2976 if (!strcmp (method
->method
->name
, ".ctor"))
2979 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2980 g_assert (!method
->method
->klass
->valuetype
);
2981 result
= mono_runtime_invoke_array (method
->method
, this, params
, NULL
);
2983 for (i
= 0, j
= 0; i
< mono_array_length (params
); i
++) {
2984 if (sig
->params
[i
]->byref
) {
2986 arg
= mono_array_get (params
, gpointer
, i
);
2987 mono_array_setref (out_args
, j
, arg
);
2992 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2998 read_enum_value (char *mem
, int type
)
3002 return *(guint8
*)mem
;
3004 return *(gint8
*)mem
;
3006 return *(guint16
*)mem
;
3008 return *(gint16
*)mem
;
3010 return *(guint32
*)mem
;
3012 return *(gint32
*)mem
;
3014 return *(guint64
*)mem
;
3016 return *(gint64
*)mem
;
3018 g_assert_not_reached ();
3024 write_enum_value (char *mem
, int type
, guint64 value
)
3028 case MONO_TYPE_I1
: {
3029 guint8
*p
= (guint8
*)mem
;
3034 case MONO_TYPE_I2
: {
3035 guint16
*p
= (void*)mem
;
3040 case MONO_TYPE_I4
: {
3041 guint32
*p
= (void*)mem
;
3046 case MONO_TYPE_I8
: {
3047 guint64
*p
= (void*)mem
;
3052 g_assert_not_reached ();
3058 ves_icall_System_Enum_ToObject (MonoReflectionType
*enumType
, MonoObject
*value
)
3061 MonoClass
*enumc
, *objc
;
3066 MONO_ARCH_SAVE_REGS
;
3068 MONO_CHECK_ARG_NULL (enumType
);
3069 MONO_CHECK_ARG_NULL (value
);
3071 domain
= mono_object_domain (enumType
);
3072 enumc
= mono_class_from_mono_type (enumType
->type
);
3074 mono_class_init_or_throw (enumc
);
3076 objc
= value
->vtable
->klass
;
3078 if (!enumc
->enumtype
)
3079 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3080 if (!((objc
->enumtype
) || (objc
->byval_arg
.type
>= MONO_TYPE_I1
&& objc
->byval_arg
.type
<= MONO_TYPE_U8
)))
3081 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."));
3083 etype
= mono_class_enum_basetype (enumc
);
3085 /* MS throws this for typebuilders */
3086 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3088 res
= mono_object_new (domain
, enumc
);
3089 val
= read_enum_value ((char *)value
+ sizeof (MonoObject
), objc
->enumtype
? mono_class_enum_basetype (objc
)->type
: objc
->byval_arg
.type
);
3090 write_enum_value ((char *)res
+ sizeof (MonoObject
), etype
->type
, val
);
3096 ves_icall_System_Enum_get_value (MonoObject
*this)
3104 MONO_ARCH_SAVE_REGS
;
3109 g_assert (this->vtable
->klass
->enumtype
);
3111 enumc
= mono_class_from_mono_type (mono_class_enum_basetype (this->vtable
->klass
));
3112 res
= mono_object_new (mono_object_domain (this), enumc
);
3113 dst
= (char *)res
+ sizeof (MonoObject
);
3114 src
= (char *)this + sizeof (MonoObject
);
3115 size
= mono_class_value_size (enumc
, NULL
);
3117 memcpy (dst
, src
, size
);
3122 static MonoReflectionType
*
3123 ves_icall_System_Enum_get_underlying_type (MonoReflectionType
*type
)
3128 MONO_ARCH_SAVE_REGS
;
3130 klass
= mono_class_from_mono_type (type
->type
);
3131 mono_class_init_or_throw (klass
);
3133 etype
= mono_class_enum_basetype (klass
);
3135 /* MS throws this for typebuilders */
3136 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3138 return mono_type_get_object (mono_object_domain (type
), etype
);
3142 ves_icall_System_Enum_compare_value_to (MonoObject
*this, MonoObject
*other
)
3144 gpointer tdata
= (char *)this + sizeof (MonoObject
);
3145 gpointer odata
= (char *)other
+ sizeof (MonoObject
);
3146 MonoType
*basetype
= mono_class_enum_basetype (this->vtable
->klass
);
3147 g_assert (basetype
);
3149 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3150 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3151 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3154 return me > other ? 1 : -1; \
3157 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3158 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3159 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3162 return me - other; \
3165 switch (basetype
->type
) {
3167 COMPARE_ENUM_VALUES (guint8
);
3169 COMPARE_ENUM_VALUES (gint8
);
3170 case MONO_TYPE_CHAR
:
3172 COMPARE_ENUM_VALUES_RANGE (guint16
);
3174 COMPARE_ENUM_VALUES (gint16
);
3176 COMPARE_ENUM_VALUES (guint32
);
3178 COMPARE_ENUM_VALUES (gint32
);
3180 COMPARE_ENUM_VALUES (guint64
);
3182 COMPARE_ENUM_VALUES (gint64
);
3184 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3186 #undef COMPARE_ENUM_VALUES_RANGE
3187 #undef COMPARE_ENUM_VALUES
3192 ves_icall_System_Enum_get_hashcode (MonoObject
*this)
3194 gpointer data
= (char *)this + sizeof (MonoObject
);
3195 MonoType
*basetype
= mono_class_enum_basetype (this->vtable
->klass
);
3196 g_assert (basetype
);
3198 switch (basetype
->type
) {
3200 return *((gint8
*)data
);
3202 return *((guint8
*)data
);
3203 case MONO_TYPE_CHAR
:
3205 return *((guint16
*)data
);
3208 return *((gint16
*)data
);
3210 return *((guint32
*)data
);
3212 return *((gint32
*)data
);
3214 case MONO_TYPE_I8
: {
3215 gint64 value
= *((gint64
*)data
);
3216 return (gint
)(value
& 0xffffffff) ^ (int)(value
>> 32);
3219 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3225 ves_icall_get_enum_info (MonoReflectionType
*type
, MonoEnumInfo
*info
)
3227 MonoDomain
*domain
= mono_object_domain (type
);
3228 MonoClass
*enumc
= mono_class_from_mono_type (type
->type
);
3229 guint j
= 0, nvalues
, crow
;
3231 MonoClassField
*field
;
3233 MONO_ARCH_SAVE_REGS
;
3235 mono_class_init_or_throw (enumc
);
3237 MONO_STRUCT_SETREF (info
, utype
, mono_type_get_object (domain
, mono_class_enum_basetype (enumc
)));
3238 nvalues
= mono_class_num_fields (enumc
) ? mono_class_num_fields (enumc
) - 1 : 0;
3239 MONO_STRUCT_SETREF (info
, names
, mono_array_new (domain
, mono_defaults
.string_class
, nvalues
));
3240 MONO_STRUCT_SETREF (info
, values
, mono_array_new (domain
, enumc
, nvalues
));
3244 while ((field
= mono_class_get_fields (enumc
, &iter
))) {
3247 MonoTypeEnum def_type
;
3249 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
))
3251 if (strcmp ("value__", mono_field_get_name (field
)) == 0)
3253 if (mono_field_is_deleted (field
))
3255 mono_array_setref (info
->names
, j
, mono_string_new (domain
, mono_field_get_name (field
)));
3257 p
= mono_class_get_field_default_value (field
, &def_type
);
3258 len
= mono_metadata_decode_blob_size (p
, &p
);
3259 switch (mono_class_enum_basetype (enumc
)->type
) {
3262 mono_array_set (info
->values
, gchar
, j
, *p
);
3264 case MONO_TYPE_CHAR
:
3267 mono_array_set (info
->values
, gint16
, j
, read16 (p
));
3271 mono_array_set (info
->values
, gint32
, j
, read32 (p
));
3275 mono_array_set (info
->values
, gint64
, j
, read64 (p
));
3278 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc
)->type
);
3285 BFLAGS_IgnoreCase
= 1,
3286 BFLAGS_DeclaredOnly
= 2,
3287 BFLAGS_Instance
= 4,
3289 BFLAGS_Public
= 0x10,
3290 BFLAGS_NonPublic
= 0x20,
3291 BFLAGS_FlattenHierarchy
= 0x40,
3292 BFLAGS_InvokeMethod
= 0x100,
3293 BFLAGS_CreateInstance
= 0x200,
3294 BFLAGS_GetField
= 0x400,
3295 BFLAGS_SetField
= 0x800,
3296 BFLAGS_GetProperty
= 0x1000,
3297 BFLAGS_SetProperty
= 0x2000,
3298 BFLAGS_ExactBinding
= 0x10000,
3299 BFLAGS_SuppressChangeType
= 0x20000,
3300 BFLAGS_OptionalParamBinding
= 0x40000
3303 static MonoReflectionField
*
3304 ves_icall_Type_GetField (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3307 MonoClass
*startklass
, *klass
;
3309 MonoClassField
*field
;
3312 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3313 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3314 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3317 mono_raise_exception (mono_get_exception_argument_null ("name"));
3318 if (type
->type
->byref
)
3321 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
3324 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3325 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3328 while ((field
= mono_class_get_fields_lazy (klass
, &iter
))) {
3329 guint32 flags
= mono_field_get_flags (field
);
3332 if (mono_field_is_deleted_with_flags (field
, flags
))
3334 if ((flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3335 if (bflags
& BFLAGS_Public
)
3337 } else if ((klass
== startklass
) || (flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3338 if (bflags
& BFLAGS_NonPublic
) {
3345 if (flags
& FIELD_ATTRIBUTE_STATIC
) {
3346 if (bflags
& BFLAGS_Static
)
3347 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3350 if (bflags
& BFLAGS_Instance
)
3357 utf8_name
= mono_string_to_utf8 (name
);
3359 if (compare_func (mono_field_get_name (field
), utf8_name
)) {
3365 return mono_field_get_object (domain
, klass
, field
);
3367 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3374 ves_icall_Type_GetFields_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3377 MonoClass
*startklass
, *klass
, *refklass
;
3382 MonoClassField
*field
;
3383 MonoPtrArray tmp_array
;
3385 MONO_ARCH_SAVE_REGS
;
3387 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3388 if (type
->type
->byref
)
3389 return mono_array_new (domain
, mono_defaults
.field_info_class
, 0);
3390 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3391 refklass
= mono_class_from_mono_type (reftype
->type
);
3393 mono_ptr_array_init (tmp_array
, 2);
3396 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3397 mono_ptr_array_destroy (tmp_array
);
3398 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3402 while ((field
= mono_class_get_fields_lazy (klass
, &iter
))) {
3403 guint32 flags
= mono_field_get_flags (field
);
3405 if (mono_field_is_deleted_with_flags (field
, flags
))
3407 if ((flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3408 if (bflags
& BFLAGS_Public
)
3410 } else if ((klass
== startklass
) || (flags
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3411 if (bflags
& BFLAGS_NonPublic
) {
3418 if (flags
& FIELD_ATTRIBUTE_STATIC
) {
3419 if (bflags
& BFLAGS_Static
)
3420 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3423 if (bflags
& BFLAGS_Instance
)
3429 member
= (MonoObject
*)mono_field_get_object (domain
, refklass
, field
);
3430 mono_ptr_array_append (tmp_array
, member
);
3432 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3435 res
= mono_array_new_cached (domain
, mono_defaults
.field_info_class
, mono_ptr_array_size (tmp_array
));
3437 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3438 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3440 mono_ptr_array_destroy (tmp_array
);
3446 method_nonpublic (MonoMethod
* method
, gboolean start_klass
)
3448 switch (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) {
3449 case METHOD_ATTRIBUTE_ASSEM
:
3450 return (start_klass
|| mono_defaults
.generic_ilist_class
);
3451 case METHOD_ATTRIBUTE_PRIVATE
:
3453 case METHOD_ATTRIBUTE_PUBLIC
:
3461 ves_icall_Type_GetMethodsByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3463 static MonoClass
*MethodInfo_array
;
3465 MonoClass
*startklass
, *klass
, *refklass
;
3470 int i
, len
, match
, nslots
;
3471 /*FIXME, use MonoBitSet*/
3472 guint32 method_slots_default
[8];
3473 guint32
*method_slots
= NULL
;
3474 gchar
*mname
= NULL
;
3475 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3476 MonoVTable
*array_vtable
;
3478 MonoPtrArray tmp_array
;
3480 mono_ptr_array_init (tmp_array
, 4);
3482 if (!MethodInfo_array
) {
3483 MonoClass
*klass
= mono_array_class_get (mono_defaults
.method_info_class
, 1);
3484 mono_memory_barrier ();
3485 MethodInfo_array
= klass
;
3488 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3489 array_vtable
= mono_class_vtable_full (domain
, MethodInfo_array
, TRUE
);
3490 if (type
->type
->byref
)
3491 return mono_array_new_specific (array_vtable
, 0);
3492 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3493 refklass
= mono_class_from_mono_type (reftype
->type
);
3497 mname
= mono_string_to_utf8 (name
);
3498 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3501 /* An optimization for calls made from Delegate:CreateDelegate () */
3502 if (klass
->delegate
&& mname
&& !strcmp (mname
, "Invoke") && (bflags
== (BFLAGS_Public
| BFLAGS_Static
| BFLAGS_Instance
))) {
3503 method
= mono_get_delegate_invoke (klass
);
3504 if (mono_loader_get_last_error ())
3507 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3509 res
= mono_array_new_specific (array_vtable
, 1);
3510 mono_array_setref (res
, 0, member
);
3515 mono_class_setup_vtable (klass
);
3516 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3519 if (is_generic_parameter (type
->type
))
3520 nslots
= mono_class_get_vtable_size (klass
->parent
);
3522 nslots
= MONO_CLASS_IS_INTERFACE (klass
) ? mono_class_num_methods (klass
) : mono_class_get_vtable_size (klass
);
3523 if (nslots
>= sizeof (method_slots_default
) * 8) {
3524 method_slots
= g_new0 (guint32
, nslots
/ 32 + 1);
3526 method_slots
= method_slots_default
;
3527 memset (method_slots
, 0, sizeof (method_slots_default
));
3530 mono_class_setup_vtable (klass
);
3531 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3535 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3537 if (method
->slot
!= -1) {
3538 g_assert (method
->slot
< nslots
);
3539 if (method_slots
[method
->slot
>> 5] & (1 << (method
->slot
& 0x1f)))
3541 if (!(method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
))
3542 method_slots
[method
->slot
>> 5] |= 1 << (method
->slot
& 0x1f);
3545 if (method
->name
[0] == '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0))
3547 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3548 if (bflags
& BFLAGS_Public
)
3550 } else if ((bflags
& BFLAGS_NonPublic
) && method_nonpublic (method
, (klass
== startklass
))) {
3556 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3557 if (bflags
& BFLAGS_Static
)
3558 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3561 if (bflags
& BFLAGS_Instance
)
3569 if (compare_func (mname
, method
->name
))
3575 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3577 mono_ptr_array_append (tmp_array
, member
);
3579 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3583 if (method_slots
!= method_slots_default
)
3584 g_free (method_slots
);
3586 res
= mono_array_new_specific (array_vtable
, mono_ptr_array_size (tmp_array
));
3588 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3589 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3591 mono_ptr_array_destroy (tmp_array
);
3596 if (method_slots
!= method_slots_default
)
3597 g_free (method_slots
);
3598 mono_ptr_array_destroy (tmp_array
);
3599 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3600 ex
= mono_class_get_exception_for_failure (klass
);
3602 ex
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3603 mono_loader_clear_error ();
3605 mono_raise_exception (ex
);
3610 ves_icall_Type_GetConstructors_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3613 static MonoClass
*System_Reflection_ConstructorInfo
;
3614 MonoClass
*startklass
, *klass
, *refklass
;
3619 gpointer iter
= NULL
;
3620 MonoPtrArray tmp_array
;
3622 MONO_ARCH_SAVE_REGS
;
3624 mono_ptr_array_init (tmp_array
, 4); /*FIXME, guestimating*/
3626 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3627 if (type
->type
->byref
)
3628 return mono_array_new_cached (domain
, mono_defaults
.method_info_class
, 0);
3629 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3630 refklass
= mono_class_from_mono_type (reftype
->type
);
3632 if (!System_Reflection_ConstructorInfo
)
3633 System_Reflection_ConstructorInfo
= mono_class_from_name (
3634 mono_defaults
.corlib
, "System.Reflection", "ConstructorInfo");
3637 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3639 if (strcmp (method
->name
, ".ctor") && strcmp (method
->name
, ".cctor"))
3641 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3642 if (bflags
& BFLAGS_Public
)
3645 if (bflags
& BFLAGS_NonPublic
)
3651 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3652 if (bflags
& BFLAGS_Static
)
3653 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3656 if (bflags
& BFLAGS_Instance
)
3662 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3664 mono_ptr_array_append (tmp_array
, member
);
3667 res
= mono_array_new_cached (domain
, System_Reflection_ConstructorInfo
, mono_ptr_array_size (tmp_array
));
3669 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3670 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3672 mono_ptr_array_destroy (tmp_array
);
3678 property_hash (gconstpointer data
)
3680 MonoProperty
*prop
= (MonoProperty
*)data
;
3682 return g_str_hash (prop
->name
);
3686 property_equal (MonoProperty
*prop1
, MonoProperty
*prop2
)
3688 // Properties are hide-by-name-and-signature
3689 if (!g_str_equal (prop1
->name
, prop2
->name
))
3692 if (prop1
->get
&& prop2
->get
&& !mono_metadata_signature_equal (mono_method_signature (prop1
->get
), mono_method_signature (prop2
->get
)))
3694 if (prop1
->set
&& prop2
->set
&& !mono_metadata_signature_equal (mono_method_signature (prop1
->set
), mono_method_signature (prop2
->set
)))
3700 property_accessor_nonpublic (MonoMethod
* accessor
, gboolean start_klass
)
3705 return method_nonpublic (accessor
, start_klass
);
3709 ves_icall_Type_GetPropertiesByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3713 static MonoClass
*System_Reflection_PropertyInfo
;
3714 MonoClass
*startklass
, *klass
;
3720 gchar
*propname
= NULL
;
3721 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3723 GHashTable
*properties
= NULL
;
3724 MonoPtrArray tmp_array
;
3726 MONO_ARCH_SAVE_REGS
;
3728 mono_ptr_array_init (tmp_array
, 8); /*This the average for ASP.NET types*/
3730 if (!System_Reflection_PropertyInfo
)
3731 System_Reflection_PropertyInfo
= mono_class_from_name (
3732 mono_defaults
.corlib
, "System.Reflection", "PropertyInfo");
3734 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3735 if (type
->type
->byref
)
3736 return mono_array_new_cached (domain
, System_Reflection_PropertyInfo
, 0);
3737 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3740 propname
= mono_string_to_utf8 (name
);
3741 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3744 properties
= g_hash_table_new (property_hash
, (GEqualFunc
)property_equal
);
3746 mono_class_setup_vtable (klass
);
3747 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3751 while ((prop
= mono_class_get_properties (klass
, &iter
))) {
3757 flags
= method
->flags
;
3760 if ((prop
->get
&& ((prop
->get
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
)) ||
3761 (prop
->set
&& ((prop
->set
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
))) {
3762 if (bflags
& BFLAGS_Public
)
3764 } else if (bflags
& BFLAGS_NonPublic
) {
3765 if (property_accessor_nonpublic(prop
->get
, startklass
== klass
) ||
3766 property_accessor_nonpublic(prop
->set
, startklass
== klass
)) {
3773 if (flags
& METHOD_ATTRIBUTE_STATIC
) {
3774 if (bflags
& BFLAGS_Static
)
3775 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3778 if (bflags
& BFLAGS_Instance
)
3787 if (compare_func (propname
, prop
->name
))
3791 if (g_hash_table_lookup (properties
, prop
))
3794 mono_ptr_array_append (tmp_array
, mono_property_get_object (domain
, startklass
, prop
));
3796 g_hash_table_insert (properties
, prop
, prop
);
3798 if ((!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
)))
3801 g_hash_table_destroy (properties
);
3804 res
= mono_array_new_cached (domain
, System_Reflection_PropertyInfo
, mono_ptr_array_size (tmp_array
));
3805 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3806 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3808 mono_ptr_array_destroy (tmp_array
);
3814 g_hash_table_destroy (properties
);
3817 mono_ptr_array_destroy (tmp_array
);
3819 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3820 ex
= mono_class_get_exception_for_failure (klass
);
3822 ex
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3823 mono_loader_clear_error ();
3825 mono_raise_exception (ex
);
3829 static MonoReflectionEvent
*
3830 ves_icall_MonoType_GetEvent (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3833 MonoClass
*klass
, *startklass
;
3838 int (*compare_func
) (const char *s1
, const char *s2
);
3840 MONO_ARCH_SAVE_REGS
;
3842 event_name
= mono_string_to_utf8 (name
);
3843 if (type
->type
->byref
)
3845 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3846 domain
= mono_object_domain (type
);
3848 mono_class_init_or_throw (klass
);
3850 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
3852 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3853 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3856 while ((event
= mono_class_get_events (klass
, &iter
))) {
3857 if (compare_func (event
->name
, event_name
))
3860 method
= event
->add
;
3862 method
= event
->remove
;
3864 method
= event
->raise
;
3866 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3867 if (!(bflags
& BFLAGS_Public
))
3870 if (!(bflags
& BFLAGS_NonPublic
))
3872 if ((klass
!= startklass
) && (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PRIVATE
)
3876 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3877 if (!(bflags
& BFLAGS_Static
))
3879 if (!(bflags
& BFLAGS_FlattenHierarchy
) && (klass
!= startklass
))
3882 if (!(bflags
& BFLAGS_Instance
))
3886 if (!(bflags
& BFLAGS_NonPublic
))
3889 g_free (event_name
);
3890 return mono_event_get_object (domain
, startklass
, event
);
3893 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3896 g_free (event_name
);
3901 ves_icall_Type_GetEvents_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3905 static MonoClass
*System_Reflection_EventInfo
;
3906 MonoClass
*startklass
, *klass
;
3913 MonoPtrArray tmp_array
;
3915 MONO_ARCH_SAVE_REGS
;
3917 mono_ptr_array_init (tmp_array
, 4);
3919 if (!System_Reflection_EventInfo
)
3920 System_Reflection_EventInfo
= mono_class_from_name (
3921 mono_defaults
.corlib
, "System.Reflection", "EventInfo");
3923 domain
= mono_object_domain (type
);
3924 if (type
->type
->byref
)
3925 return mono_array_new_cached (domain
, System_Reflection_EventInfo
, 0);
3926 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3929 mono_class_setup_vtable (klass
);
3930 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3934 while ((event
= mono_class_get_events (klass
, &iter
))) {
3936 method
= event
->add
;
3938 method
= event
->remove
;
3940 method
= event
->raise
;
3942 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3943 if (bflags
& BFLAGS_Public
)
3945 } else if ((klass
== startklass
) || (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) {
3946 if (bflags
& BFLAGS_NonPublic
)
3951 if (bflags
& BFLAGS_NonPublic
)
3957 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3958 if (bflags
& BFLAGS_Static
)
3959 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3962 if (bflags
& BFLAGS_Instance
)
3967 if (bflags
& BFLAGS_Instance
)
3971 mono_ptr_array_append (tmp_array
, mono_event_get_object (domain
, startklass
, event
));
3973 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3976 res
= mono_array_new_cached (domain
, System_Reflection_EventInfo
, mono_ptr_array_size (tmp_array
));
3978 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3979 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3981 mono_ptr_array_destroy (tmp_array
);
3986 mono_ptr_array_destroy (tmp_array
);
3987 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3988 ex
= mono_class_get_exception_for_failure (klass
);
3990 ex
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3991 mono_loader_clear_error ();
3993 mono_raise_exception (ex
);
3997 static MonoReflectionType
*
3998 ves_icall_Type_GetNestedType (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
4006 MONO_ARCH_SAVE_REGS
;
4009 mono_raise_exception (mono_get_exception_argument_null ("name"));
4011 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4012 if (type
->type
->byref
)
4014 klass
= mono_class_from_mono_type (type
->type
);
4016 str
= mono_string_to_utf8 (name
);
4019 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
4020 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
4023 * If a nested type is generic, return its generic type definition.
4024 * Note that this means that the return value is essentially a
4025 * nested type of the generic type definition of @klass.
4027 * A note in MSDN claims that a generic type definition can have
4028 * nested types that aren't generic. In any case, the container of that
4029 * nested type would be the generic type definition.
4031 if (klass
->generic_class
)
4032 klass
= klass
->generic_class
->container_class
;
4035 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
4037 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
4038 if (bflags
& BFLAGS_Public
)
4041 if (bflags
& BFLAGS_NonPublic
)
4046 if (strcmp (nested
->name
, str
) == 0){
4048 return mono_type_get_object (domain
, &nested
->byval_arg
);
4051 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
4058 ves_icall_Type_GetNestedTypes (MonoReflectionType
*type
, guint32 bflags
)
4067 MonoPtrArray tmp_array
;
4069 MONO_ARCH_SAVE_REGS
;
4071 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4072 if (type
->type
->byref
)
4073 return mono_array_new (domain
, mono_defaults
.monotype_class
, 0);
4074 klass
= mono_class_from_mono_type (type
->type
);
4077 * If a nested type is generic, return its generic type definition.
4078 * Note that this means that the return value is essentially the set
4079 * of nested types of the generic type definition of @klass.
4081 * A note in MSDN claims that a generic type definition can have
4082 * nested types that aren't generic. In any case, the container of that
4083 * nested type would be the generic type definition.
4085 if (klass
->generic_class
)
4086 klass
= klass
->generic_class
->container_class
;
4088 mono_ptr_array_init (tmp_array
, 1);
4090 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
4092 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
4093 if (bflags
& BFLAGS_Public
)
4096 if (bflags
& BFLAGS_NonPublic
)
4101 member
= (MonoObject
*)mono_type_get_object (domain
, &nested
->byval_arg
);
4102 mono_ptr_array_append (tmp_array
, member
);
4105 res
= mono_array_new_cached (domain
, mono_defaults
.monotype_class
, mono_ptr_array_size (tmp_array
));
4107 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4108 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4110 mono_ptr_array_destroy (tmp_array
);
4115 static MonoReflectionType
*
4116 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly
*assembly
, MonoReflectionModule
*module
, MonoString
*name
, MonoBoolean throwOnError
, MonoBoolean ignoreCase
)
4119 MonoType
*type
= NULL
;
4120 MonoTypeNameParse info
;
4121 gboolean type_resolve
;
4123 MONO_ARCH_SAVE_REGS
;
4125 /* On MS.NET, this does not fire a TypeResolve event */
4126 type_resolve
= TRUE
;
4127 str
= mono_string_to_utf8 (name
);
4128 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4129 if (!mono_reflection_parse_type (str
, &info
)) {
4131 mono_reflection_free_type_info (&info
);
4132 if (throwOnError
) /* uhm: this is a parse error, though... */
4133 mono_raise_exception (mono_get_exception_type_load (name
, NULL
));
4134 /*g_print ("failed parse\n");*/
4138 if (info
.assembly
.name
) {
4140 mono_reflection_free_type_info (&info
);
4142 /* 1.0 and 2.0 throw different exceptions */
4143 if (mono_defaults
.generic_ilist_class
)
4144 mono_raise_exception (mono_get_exception_argument (NULL
, "Type names passed to Assembly.GetType() must not specify an assembly."));
4146 mono_raise_exception (mono_get_exception_type_load (name
, NULL
));
4151 if (module
!= NULL
) {
4153 type
= mono_reflection_get_type (module
->image
, &info
, ignoreCase
, &type_resolve
);
4158 if (assembly
->assembly
->dynamic
) {
4159 /* Enumerate all modules */
4160 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)assembly
;
4164 if (abuilder
->modules
) {
4165 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
4166 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
4167 type
= mono_reflection_get_type (&mb
->dynamic_image
->image
, &info
, ignoreCase
, &type_resolve
);
4173 if (!type
&& abuilder
->loaded_modules
) {
4174 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
4175 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
4176 type
= mono_reflection_get_type (mod
->image
, &info
, ignoreCase
, &type_resolve
);
4183 type
= mono_reflection_get_type (assembly
->assembly
->image
, &info
, ignoreCase
, &type_resolve
);
4185 mono_reflection_free_type_info (&info
);
4187 MonoException
*e
= NULL
;
4190 e
= mono_get_exception_type_load (name
, NULL
);
4192 if (mono_loader_get_last_error () && mono_defaults
.generic_ilist_class
)
4193 e
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4195 mono_loader_clear_error ();
4198 mono_raise_exception (e
);
4201 } else if (mono_loader_get_last_error ()) {
4203 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4204 mono_loader_clear_error ();
4207 if (type
->type
== MONO_TYPE_CLASS
) {
4208 MonoClass
*klass
= mono_type_get_class (type
);
4210 if (mono_is_security_manager_active () && !klass
->exception_type
)
4211 /* Some security problems are detected during generic vtable construction */
4212 mono_class_setup_vtable (klass
);
4213 /* need to report exceptions ? */
4214 if (throwOnError
&& klass
->exception_type
) {
4215 /* report SecurityException (or others) that occured when loading the assembly */
4216 MonoException
*exc
= mono_class_get_exception_for_failure (klass
);
4217 mono_loader_clear_error ();
4218 mono_raise_exception (exc
);
4219 } else if (klass
->exception_type
== MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND
) {
4224 /* g_print ("got it\n"); */
4225 return mono_type_get_object (mono_object_domain (assembly
), type
);
4229 replace_shadow_path (MonoDomain
*domain
, gchar
*dirname
, gchar
**filename
)
4232 gchar
*shadow_ini_file
;
4235 /* Check for shadow-copied assembly */
4236 if (mono_is_shadow_copy_enabled (domain
, dirname
)) {
4237 shadow_ini_file
= g_build_filename (dirname
, "__AssemblyInfo__.ini", NULL
);
4239 if (!g_file_get_contents (shadow_ini_file
, &content
, &len
, NULL
) ||
4240 !g_file_test (content
, G_FILE_TEST_IS_REGULAR
)) {
4246 g_free (shadow_ini_file
);
4247 if (content
!= NULL
) {
4250 *filename
= content
;
4258 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly
*assembly
, MonoBoolean escaped
)
4260 MonoDomain
*domain
= mono_object_domain (assembly
);
4261 MonoAssembly
*mass
= assembly
->assembly
;
4262 MonoString
*res
= NULL
;
4267 MONO_ARCH_SAVE_REGS
;
4269 if (g_path_is_absolute (mass
->image
->name
)) {
4270 absolute
= g_strdup (mass
->image
->name
);
4271 dirname
= g_path_get_dirname (absolute
);
4273 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
4274 dirname
= g_strdup (mass
->basedir
);
4277 replace_shadow_path (domain
, dirname
, &absolute
);
4282 for (i
= strlen (absolute
) - 1; i
>= 0; i
--)
4283 if (absolute
[i
] == '\\')
4288 uri
= g_filename_to_uri (absolute
, NULL
, NULL
);
4290 const char *prepend
= "file://";
4292 if (*absolute
== '/' && *(absolute
+ 1) == '/') {
4295 prepend
= "file:///";
4298 uri
= g_strconcat (prepend
, absolute
, NULL
);
4302 res
= mono_string_new (domain
, uri
);
4310 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly
*assembly
)
4312 MonoAssembly
*mass
= assembly
->assembly
;
4314 MONO_ARCH_SAVE_REGS
;
4316 return mass
->in_gac
;
4319 static MonoReflectionAssembly
*
4320 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString
*mname
, MonoObject
*evidence
)
4324 MonoImageOpenStatus status
;
4326 MONO_ARCH_SAVE_REGS
;
4328 name
= mono_string_to_utf8 (mname
);
4329 res
= mono_assembly_load_with_partial_name (name
, &status
);
4335 return mono_assembly_get_object (mono_domain_get (), res
);
4339 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly
*assembly
)
4341 MonoDomain
*domain
= mono_object_domain (assembly
);
4344 MONO_ARCH_SAVE_REGS
;
4346 res
= mono_string_new (domain
, mono_image_get_filename (assembly
->assembly
->image
));
4352 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly
*assembly
)
4354 MONO_ARCH_SAVE_REGS
;
4356 return assembly
->assembly
->ref_only
;
4360 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly
*assembly
)
4362 MonoDomain
*domain
= mono_object_domain (assembly
);
4364 MONO_ARCH_SAVE_REGS
;
4366 return mono_string_new (domain
, assembly
->assembly
->image
->version
);
4369 static MonoReflectionMethod
*
4370 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly
*assembly
)
4372 guint32 token
= mono_image_get_entry_point (assembly
->assembly
->image
);
4374 MONO_ARCH_SAVE_REGS
;
4378 return mono_method_get_object (mono_object_domain (assembly
), mono_get_method (assembly
->assembly
->image
, token
, NULL
), NULL
);
4381 static MonoReflectionModule
*
4382 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly
*assembly
)
4384 return mono_module_get_object (mono_object_domain (assembly
), assembly
->assembly
->image
);
4388 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly
*assembly
)
4390 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4391 MonoArray
*result
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, table
->rows
);
4395 MONO_ARCH_SAVE_REGS
;
4397 for (i
= 0; i
< table
->rows
; ++i
) {
4398 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_MANIFEST_NAME
));
4399 mono_array_setref (result
, i
, mono_string_new (mono_object_domain (assembly
), val
));
4405 create_version (MonoDomain
*domain
, guint32 major
, guint32 minor
, guint32 build
, guint32 revision
)
4407 static MonoClass
*System_Version
= NULL
;
4408 static MonoMethod
*create_version
= NULL
;
4412 if (!System_Version
) {
4413 System_Version
= mono_class_from_name (mono_defaults
.corlib
, "System", "Version");
4414 g_assert (System_Version
);
4417 if (!create_version
) {
4418 MonoMethodDesc
*desc
= mono_method_desc_new (":.ctor(int,int,int,int)", FALSE
);
4419 create_version
= mono_method_desc_search_in_class (desc
, System_Version
);
4420 g_assert (create_version
);
4421 mono_method_desc_free (desc
);
4427 args
[3] = &revision
;
4428 result
= mono_object_new (domain
, System_Version
);
4429 mono_runtime_invoke (create_version
, result
, args
, NULL
);
4435 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly
*assembly
)
4437 static MonoClass
*System_Reflection_AssemblyName
;
4439 MonoDomain
*domain
= mono_object_domain (assembly
);
4441 static MonoMethod
*create_culture
= NULL
;
4442 MonoImage
*image
= assembly
->assembly
->image
;
4445 MONO_ARCH_SAVE_REGS
;
4447 if (!System_Reflection_AssemblyName
)
4448 System_Reflection_AssemblyName
= mono_class_from_name (
4449 mono_defaults
.corlib
, "System.Reflection", "AssemblyName");
4451 t
= &assembly
->assembly
->image
->tables
[MONO_TABLE_ASSEMBLYREF
];
4454 result
= mono_array_new (domain
, System_Reflection_AssemblyName
, count
);
4456 if (count
> 0 && !create_culture
) {
4457 MonoMethodDesc
*desc
= mono_method_desc_new (
4458 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4459 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4460 g_assert (create_culture
);
4461 mono_method_desc_free (desc
);
4464 for (i
= 0; i
< count
; i
++) {
4465 MonoReflectionAssemblyName
*aname
;
4466 guint32 cols
[MONO_ASSEMBLYREF_SIZE
];
4468 mono_metadata_decode_row (t
, i
, cols
, MONO_ASSEMBLYREF_SIZE
);
4470 aname
= (MonoReflectionAssemblyName
*) mono_object_new (
4471 domain
, System_Reflection_AssemblyName
);
4473 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_NAME
])));
4475 aname
->major
= cols
[MONO_ASSEMBLYREF_MAJOR_VERSION
];
4476 aname
->minor
= cols
[MONO_ASSEMBLYREF_MINOR_VERSION
];
4477 aname
->build
= cols
[MONO_ASSEMBLYREF_BUILD_NUMBER
];
4478 aname
->revision
= cols
[MONO_ASSEMBLYREF_REV_NUMBER
];
4479 aname
->flags
= cols
[MONO_ASSEMBLYREF_FLAGS
];
4480 aname
->versioncompat
= 1; /* SameMachine (default) */
4481 aname
->hashalg
= ASSEMBLY_HASH_SHA1
; /* SHA1 (default) */
4482 MONO_OBJECT_SETREF (aname
, version
, create_version (domain
, aname
->major
, aname
->minor
, aname
->build
, aname
->revision
));
4484 if (create_culture
) {
4486 MonoBoolean assembly_ref
= 1;
4487 args
[0] = mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_CULTURE
]));
4488 args
[1] = &assembly_ref
;
4489 MONO_OBJECT_SETREF (aname
, cultureInfo
, mono_runtime_invoke (create_culture
, NULL
, args
, NULL
));
4492 if (cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]) {
4493 const gchar
*pkey_ptr
= mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]);
4494 guint32 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
4496 if ((cols
[MONO_ASSEMBLYREF_FLAGS
] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
)) {
4497 /* public key token isn't copied - the class library will
4498 automatically generate it from the public key if required */
4499 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4500 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
4502 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4503 memcpy (mono_array_addr (aname
->keyToken
, guint8
, 0), pkey_ptr
, pkey_len
);
4506 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
4509 /* note: this function doesn't return the codebase on purpose (i.e. it can
4510 be used under partial trust as path information isn't present). */
4512 mono_array_setref (result
, i
, aname
);
4523 foreach_namespace (const char* key
, gconstpointer val
, NameSpaceInfo
*info
)
4525 MonoString
*name
= mono_string_new (mono_object_domain (info
->res
), key
);
4527 mono_array_setref (info
->res
, info
->idx
, name
);
4532 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly
*assembly
)
4534 MonoImage
*img
= assembly
->assembly
->image
;
4539 MONO_ARCH_SAVE_REGS
;
4541 mono_image_lock (img
);
4542 mono_image_init_name_cache (img
);
4545 len
= g_hash_table_size (img
->name_cache
);
4546 mono_image_unlock (img
);
4548 /*we can't create objects holding the image lock */
4549 res
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, len
);
4551 mono_image_lock (img
);
4552 /*len might have changed, create a new array*/
4553 if (len
!= g_hash_table_size (img
->name_cache
))
4558 g_hash_table_foreach (img
->name_cache
, (GHFunc
)foreach_namespace
, &info
);
4559 mono_image_unlock (img
);
4564 /* move this in some file in mono/util/ */
4566 g_concat_dir_and_file (const char *dir
, const char *file
)
4568 g_return_val_if_fail (dir
!= NULL
, NULL
);
4569 g_return_val_if_fail (file
!= NULL
, NULL
);
4572 * If the directory name doesn't have a / on the end, we need
4573 * to add one so we get a proper path to the file
4575 if (dir
[strlen(dir
) - 1] != G_DIR_SEPARATOR
)
4576 return g_strconcat (dir
, G_DIR_SEPARATOR_S
, file
, NULL
);
4578 return g_strconcat (dir
, file
, NULL
);
4582 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, gint32
*size
, MonoReflectionModule
**ref_module
)
4584 char *n
= mono_string_to_utf8 (name
);
4585 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4587 guint32 cols
[MONO_MANIFEST_SIZE
];
4588 guint32 impl
, file_idx
;
4592 MONO_ARCH_SAVE_REGS
;
4594 for (i
= 0; i
< table
->rows
; ++i
) {
4595 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
4596 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
4597 if (strcmp (val
, n
) == 0)
4601 if (i
== table
->rows
)
4604 impl
= cols
[MONO_MANIFEST_IMPLEMENTATION
];
4607 * this code should only be called after obtaining the
4608 * ResourceInfo and handling the other cases.
4610 g_assert ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
);
4611 file_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
4613 module
= mono_image_load_file_for_image (assembly
->assembly
->image
, file_idx
);
4618 module
= assembly
->assembly
->image
;
4620 mono_gc_wbarrier_generic_store (ref_module
, (MonoObject
*) mono_module_get_object (mono_domain_get (), module
));
4622 return (void*)mono_image_get_resource (module
, cols
[MONO_MANIFEST_OFFSET
], (guint32
*)size
);
4626 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoManifestResourceInfo
*info
)
4628 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4630 guint32 cols
[MONO_MANIFEST_SIZE
];
4631 guint32 file_cols
[MONO_FILE_SIZE
];
4635 MONO_ARCH_SAVE_REGS
;
4637 n
= mono_string_to_utf8 (name
);
4638 for (i
= 0; i
< table
->rows
; ++i
) {
4639 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
4640 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
4641 if (strcmp (val
, n
) == 0)
4645 if (i
== table
->rows
)
4648 if (!cols
[MONO_MANIFEST_IMPLEMENTATION
]) {
4649 info
->location
= RESOURCE_LOCATION_EMBEDDED
| RESOURCE_LOCATION_IN_MANIFEST
;
4652 switch (cols
[MONO_MANIFEST_IMPLEMENTATION
] & MONO_IMPLEMENTATION_MASK
) {
4653 case MONO_IMPLEMENTATION_FILE
:
4654 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
4655 table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
4656 mono_metadata_decode_row (table
, i
- 1, file_cols
, MONO_FILE_SIZE
);
4657 val
= mono_metadata_string_heap (assembly
->assembly
->image
, file_cols
[MONO_FILE_NAME
]);
4658 MONO_OBJECT_SETREF (info
, filename
, mono_string_new (mono_object_domain (assembly
), val
));
4659 if (file_cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
4662 info
->location
= RESOURCE_LOCATION_EMBEDDED
;
4665 case MONO_IMPLEMENTATION_ASSEMBLYREF
:
4666 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
4667 mono_assembly_load_reference (assembly
->assembly
->image
, i
- 1);
4668 if (assembly
->assembly
->image
->references
[i
- 1] == (gpointer
)-1) {
4669 char *msg
= g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i
- 1, assembly
->assembly
->image
->name
);
4670 MonoException
*ex
= mono_get_exception_file_not_found2 (msg
, NULL
);
4672 mono_raise_exception (ex
);
4674 MONO_OBJECT_SETREF (info
, assembly
, mono_assembly_get_object (mono_domain_get (), assembly
->assembly
->image
->references
[i
- 1]));
4676 /* Obtain info recursively */
4677 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info
->assembly
, name
, info
);
4678 info
->location
|= RESOURCE_LOCATION_ANOTHER_ASSEMBLY
;
4681 case MONO_IMPLEMENTATION_EXP_TYPE
:
4682 g_assert_not_reached ();
4691 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoBoolean resource_modules
)
4693 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
4694 MonoArray
*result
= NULL
;
4699 MONO_ARCH_SAVE_REGS
;
4701 /* check hash if needed */
4703 n
= mono_string_to_utf8 (name
);
4704 for (i
= 0; i
< table
->rows
; ++i
) {
4705 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
4706 if (strcmp (val
, n
) == 0) {
4709 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
4710 fn
= mono_string_new (mono_object_domain (assembly
), n
);
4712 return (MonoObject
*)fn
;
4720 for (i
= 0; i
< table
->rows
; ++i
) {
4721 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
))
4725 result
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, count
);
4728 for (i
= 0; i
< table
->rows
; ++i
) {
4729 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
4730 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
4731 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
4732 mono_array_setref (result
, count
, mono_string_new (mono_object_domain (assembly
), n
));
4737 return (MonoObject
*)result
;
4741 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly
*assembly
)
4743 MonoDomain
*domain
= mono_domain_get();
4746 int i
, j
, file_count
= 0;
4747 MonoImage
**modules
;
4748 guint32 module_count
, real_module_count
;
4749 MonoTableInfo
*table
;
4750 guint32 cols
[MONO_FILE_SIZE
];
4751 MonoImage
*image
= assembly
->assembly
->image
;
4753 g_assert (image
!= NULL
);
4754 g_assert (!assembly
->assembly
->dynamic
);
4756 table
= &image
->tables
[MONO_TABLE_FILE
];
4757 file_count
= table
->rows
;
4759 modules
= image
->modules
;
4760 module_count
= image
->module_count
;
4762 real_module_count
= 0;
4763 for (i
= 0; i
< module_count
; ++i
)
4765 real_module_count
++;
4767 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Module");
4768 res
= mono_array_new (domain
, klass
, 1 + real_module_count
+ file_count
);
4770 mono_array_setref (res
, 0, mono_module_get_object (domain
, image
));
4772 for (i
= 0; i
< module_count
; ++i
)
4774 mono_array_setref (res
, j
, mono_module_get_object (domain
, modules
[i
]));
4778 for (i
= 0; i
< file_count
; ++i
, ++j
) {
4779 mono_metadata_decode_row (table
, i
, cols
, MONO_FILE_SIZE
);
4780 if (cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
4781 mono_array_setref (res
, j
, mono_module_file_get_object (domain
, image
, i
));
4783 MonoImage
*m
= mono_image_load_file_for_image (image
, i
+ 1);
4785 MonoString
*fname
= mono_string_new (mono_domain_get (), mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]));
4786 mono_raise_exception (mono_get_exception_file_not_found2 (NULL
, fname
));
4788 mono_array_setref (res
, j
, mono_module_get_object (domain
, m
));
4795 static MonoReflectionMethod
*
4796 ves_icall_GetCurrentMethod (void)
4798 MonoMethod
*m
= mono_method_get_last_managed ();
4800 while (m
->is_inflated
)
4801 m
= ((MonoMethodInflated
*)m
)->declaring
;
4803 return mono_method_get_object (mono_domain_get (), m
, NULL
);
4808 mono_method_get_equivalent_method (MonoMethod
*method
, MonoClass
*klass
)
4811 if (method
->is_inflated
&& ((MonoMethodInflated
*)method
)->context
.method_inst
) {
4812 MonoMethodInflated
*inflated
= (MonoMethodInflated
*)method
;
4813 //method is inflated, we should inflate it on the other class
4814 MonoGenericContext ctx
;
4815 ctx
.method_inst
= inflated
->context
.method_inst
;
4816 ctx
.class_inst
= inflated
->context
.class_inst
;
4817 if (klass
->generic_class
)
4818 ctx
.class_inst
= klass
->generic_class
->context
.class_inst
;
4819 else if (klass
->generic_container
)
4820 ctx
.class_inst
= klass
->generic_container
->context
.class_inst
;
4821 return mono_class_inflate_generic_method_full (inflated
->declaring
, klass
, &ctx
);
4824 mono_class_setup_methods (method
->klass
);
4825 if (method
->klass
->exception_type
)
4827 for (i
= 0; i
< method
->klass
->method
.count
; ++i
) {
4828 if (method
->klass
->methods
[i
] == method
) {
4833 mono_class_setup_methods (klass
);
4834 if (klass
->exception_type
)
4836 g_assert (offset
>= 0 && offset
< klass
->method
.count
);
4837 return klass
->methods
[offset
];
4840 static MonoReflectionMethod
*
4841 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod
*method
, MonoType
*type
)
4845 klass
= mono_class_from_mono_type (type
);
4846 if (mono_class_get_generic_type_definition (method
->klass
) != mono_class_get_generic_type_definition (klass
))
4848 if (method
->klass
!= klass
) {
4849 method
= mono_method_get_equivalent_method (method
, klass
);
4854 klass
= method
->klass
;
4855 return mono_method_get_object (mono_domain_get (), method
, klass
);
4858 static MonoReflectionMethod
*
4859 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod
*method
)
4861 return mono_method_get_object (mono_domain_get (), method
, NULL
);
4864 static MonoReflectionMethodBody
*
4865 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod
*method
)
4867 return mono_method_body_get_object (mono_domain_get (), method
);
4870 static MonoReflectionAssembly
*
4871 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4873 MonoMethod
*dest
= NULL
;
4875 MONO_ARCH_SAVE_REGS
;
4877 mono_stack_walk_no_il (get_executing
, &dest
);
4878 return mono_assembly_get_object (mono_domain_get (), dest
->klass
->image
->assembly
);
4882 static MonoReflectionAssembly
*
4883 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4885 MonoDomain
* domain
= mono_domain_get ();
4887 MONO_ARCH_SAVE_REGS
;
4889 if (!domain
->entry_assembly
)
4892 return mono_assembly_get_object (domain
, domain
->entry_assembly
);
4895 static MonoReflectionAssembly
*
4896 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4901 MONO_ARCH_SAVE_REGS
;
4904 mono_stack_walk_no_il (get_executing
, &dest
);
4906 mono_stack_walk_no_il (get_caller
, &dest
);
4909 return mono_assembly_get_object (mono_domain_get (), dest
->klass
->image
->assembly
);
4913 ves_icall_System_MonoType_getFullName (MonoReflectionType
*object
, gboolean full_name
,
4914 gboolean assembly_qualified
)
4916 MonoDomain
*domain
= mono_object_domain (object
);
4917 MonoTypeNameFormat format
;
4922 format
= assembly_qualified
?
4923 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
:
4924 MONO_TYPE_NAME_FORMAT_FULL_NAME
;
4926 format
= MONO_TYPE_NAME_FORMAT_REFLECTION
;
4928 name
= mono_type_get_name_full (object
->type
, format
);
4932 if (full_name
&& (object
->type
->type
== MONO_TYPE_VAR
|| object
->type
->type
== MONO_TYPE_MVAR
)) {
4937 res
= mono_string_new (domain
, name
);
4944 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType
*this)
4946 MonoClass
*klass
= mono_class_from_mono_type (this->type
);
4947 mono_class_init_or_throw (klass
);
4948 return mono_security_core_clr_class_level (klass
);
4952 fill_reflection_assembly_name (MonoDomain
*domain
, MonoReflectionAssemblyName
*aname
, MonoAssemblyName
*name
, const char *absolute
, gboolean by_default_version
, gboolean default_publickey
, gboolean default_token
)
4954 static MonoMethod
*create_culture
= NULL
;
4957 const char *pkey_ptr
;
4959 MonoBoolean assembly_ref
= 0;
4961 MONO_ARCH_SAVE_REGS
;
4963 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, name
->name
));
4964 aname
->major
= name
->major
;
4965 aname
->minor
= name
->minor
;
4966 aname
->build
= name
->build
;
4967 aname
->flags
= name
->flags
;
4968 aname
->revision
= name
->revision
;
4969 aname
->hashalg
= name
->hash_alg
;
4970 aname
->versioncompat
= 1; /* SameMachine (default) */
4971 aname
->processor_architecture
= name
->arch
;
4973 if (by_default_version
)
4974 MONO_OBJECT_SETREF (aname
, version
, create_version (domain
, name
->major
, name
->minor
, name
->build
, name
->revision
));
4977 if (absolute
!= NULL
&& *absolute
!= '\0') {
4978 const gchar
*prepend
= "file://";
4981 codebase
= g_strdup (absolute
);
4986 for (i
= strlen (codebase
) - 1; i
>= 0; i
--)
4987 if (codebase
[i
] == '\\')
4990 if (*codebase
== '/' && *(codebase
+ 1) == '/') {
4993 prepend
= "file:///";
4997 result
= g_strconcat (prepend
, codebase
, NULL
);
5003 MONO_OBJECT_SETREF (aname
, codebase
, mono_string_new (domain
, codebase
));
5007 if (!create_culture
) {
5008 MonoMethodDesc
*desc
= mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
5009 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
5010 g_assert (create_culture
);
5011 mono_method_desc_free (desc
);
5014 if (name
->culture
) {
5015 args
[0] = mono_string_new (domain
, name
->culture
);
5016 args
[1] = &assembly_ref
;
5017 MONO_OBJECT_SETREF (aname
, cultureInfo
, mono_runtime_invoke (create_culture
, NULL
, args
, NULL
));
5020 if (name
->public_key
) {
5021 pkey_ptr
= (char*)name
->public_key
;
5022 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
5024 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
5025 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
5026 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
5027 } else if (default_publickey
) {
5028 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
5029 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
5032 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5033 if (name
->public_key_token
[0]) {
5037 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 8));
5038 p
= mono_array_addr (aname
->keyToken
, char, 0);
5040 for (i
= 0, j
= 0; i
< 8; i
++) {
5041 *p
= g_ascii_xdigit_value (name
->public_key_token
[j
++]) << 4;
5042 *p
|= g_ascii_xdigit_value (name
->public_key_token
[j
++]);
5045 } else if (default_token
) {
5046 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
5051 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly
*assembly
)
5053 MonoDomain
*domain
= mono_object_domain (assembly
);
5054 MonoAssembly
*mass
= assembly
->assembly
;
5058 name
= mono_stringify_assembly_name (&mass
->aname
);
5059 res
= mono_string_new (domain
, name
);
5066 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly
*assembly
, MonoReflectionAssemblyName
*aname
)
5069 MonoAssembly
*mass
= assembly
->assembly
;
5071 MONO_ARCH_SAVE_REGS
;
5073 if (g_path_is_absolute (mass
->image
->name
)) {
5074 fill_reflection_assembly_name (mono_object_domain (assembly
),
5075 aname
, &mass
->aname
, mass
->image
->name
, TRUE
,
5079 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
5081 fill_reflection_assembly_name (mono_object_domain (assembly
),
5082 aname
, &mass
->aname
, absolute
, TRUE
, TRUE
,
5089 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString
*fname
, MonoReflectionAssemblyName
*aname
)
5092 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
5095 MonoAssemblyName name
;
5098 MONO_ARCH_SAVE_REGS
;
5100 filename
= mono_string_to_utf8 (fname
);
5102 dirname
= g_path_get_dirname (filename
);
5103 replace_shadow_path (mono_domain_get (), dirname
, &filename
);
5106 image
= mono_image_open (filename
, &status
);
5112 if (status
== MONO_IMAGE_IMAGE_INVALID
)
5113 exc
= mono_get_exception_bad_image_format2 (NULL
, fname
);
5115 exc
= mono_get_exception_file_not_found2 (NULL
, fname
);
5116 mono_raise_exception (exc
);
5119 res
= mono_assembly_fill_assembly_name (image
, &name
);
5121 mono_image_close (image
);
5123 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5126 fill_reflection_assembly_name (mono_domain_get (), aname
, &name
, filename
,
5130 mono_image_close (image
);
5134 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly
*assembly
,
5135 char **minimum
, guint32
*minLength
, char **optional
, guint32
*optLength
, char **refused
, guint32
*refLength
)
5137 MonoBoolean result
= FALSE
;
5138 MonoDeclSecurityEntry entry
;
5140 /* SecurityAction.RequestMinimum */
5141 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQMIN
, &entry
)) {
5142 *minimum
= entry
.blob
;
5143 *minLength
= entry
.size
;
5146 /* SecurityAction.RequestOptional */
5147 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQOPT
, &entry
)) {
5148 *optional
= entry
.blob
;
5149 *optLength
= entry
.size
;
5152 /* SecurityAction.RequestRefuse */
5153 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQREFUSE
, &entry
)) {
5154 *refused
= entry
.blob
;
5155 *refLength
= entry
.size
;
5163 mono_module_get_types (MonoDomain
*domain
, MonoImage
*image
, MonoArray
**exceptions
, MonoBoolean exportedOnly
)
5167 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_TYPEDEF
];
5169 guint32 attrs
, visibility
;
5171 /* we start the count from 1 because we skip the special type <Module> */
5174 for (i
= 1; i
< tdef
->rows
; ++i
) {
5175 attrs
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEDEF_FLAGS
);
5176 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5177 if (visibility
== TYPE_ATTRIBUTE_PUBLIC
|| visibility
== TYPE_ATTRIBUTE_NESTED_PUBLIC
)
5181 count
= tdef
->rows
- 1;
5183 res
= mono_array_new (domain
, mono_defaults
.monotype_class
, count
);
5184 *exceptions
= mono_array_new (domain
, mono_defaults
.exception_class
, count
);
5186 for (i
= 1; i
< tdef
->rows
; ++i
) {
5187 attrs
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEDEF_FLAGS
);
5188 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5189 if (!exportedOnly
|| (visibility
== TYPE_ATTRIBUTE_PUBLIC
|| visibility
== TYPE_ATTRIBUTE_NESTED_PUBLIC
)) {
5190 klass
= mono_class_get (image
, (i
+ 1) | MONO_TOKEN_TYPE_DEF
);
5192 mono_array_setref (res
, count
, mono_type_get_object (domain
, &klass
->byval_arg
));
5194 MonoLoaderError
*error
;
5197 error
= mono_loader_get_last_error ();
5198 g_assert (error
!= NULL
);
5200 ex
= mono_loader_error_prepare_exception (error
);
5201 mono_array_setref (*exceptions
, count
, ex
);
5203 if (mono_loader_get_last_error ())
5204 mono_loader_clear_error ();
5213 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly
*assembly
, MonoBoolean exportedOnly
)
5215 MonoArray
*res
= NULL
;
5216 MonoArray
*exceptions
= NULL
;
5217 MonoImage
*image
= NULL
;
5218 MonoTableInfo
*table
= NULL
;
5221 int i
, len
, ex_count
;
5223 MONO_ARCH_SAVE_REGS
;
5225 domain
= mono_object_domain (assembly
);
5227 g_assert (!assembly
->assembly
->dynamic
);
5228 image
= assembly
->assembly
->image
;
5229 table
= &image
->tables
[MONO_TABLE_FILE
];
5230 res
= mono_module_get_types (domain
, image
, &exceptions
, exportedOnly
);
5232 /* Append data from all modules in the assembly */
5233 for (i
= 0; i
< table
->rows
; ++i
) {
5234 if (!(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
5235 MonoImage
*loaded_image
= mono_assembly_load_module (image
->assembly
, i
+ 1);
5238 MonoArray
*res2
= mono_module_get_types (domain
, loaded_image
, &ex2
, exportedOnly
);
5239 /* Append the new types to the end of the array */
5240 if (mono_array_length (res2
) > 0) {
5242 MonoArray
*res3
, *ex3
;
5244 len1
= mono_array_length (res
);
5245 len2
= mono_array_length (res2
);
5247 res3
= mono_array_new (domain
, mono_defaults
.monotype_class
, len1
+ len2
);
5248 mono_array_memcpy_refs (res3
, 0, res
, 0, len1
);
5249 mono_array_memcpy_refs (res3
, len1
, res2
, 0, len2
);
5252 ex3
= mono_array_new (domain
, mono_defaults
.monotype_class
, len1
+ len2
);
5253 mono_array_memcpy_refs (ex3
, 0, exceptions
, 0, len1
);
5254 mono_array_memcpy_refs (ex3
, len1
, ex2
, 0, len2
);
5261 /* the ReflectionTypeLoadException must have all the types (Types property),
5262 * NULL replacing types which throws an exception. The LoaderException must
5263 * contain all exceptions for NULL items.
5266 len
= mono_array_length (res
);
5269 for (i
= 0; i
< len
; i
++) {
5270 MonoReflectionType
*t
= mono_array_get (res
, gpointer
, i
);
5274 klass
= mono_type_get_class (t
->type
);
5275 if ((klass
!= NULL
) && klass
->exception_type
) {
5276 /* keep the class in the list */
5277 list
= g_list_append (list
, klass
);
5278 /* and replace Type with NULL */
5279 mono_array_setref (res
, i
, NULL
);
5286 if (list
|| ex_count
) {
5288 MonoException
*exc
= NULL
;
5289 MonoArray
*exl
= NULL
;
5290 int j
, length
= g_list_length (list
) + ex_count
;
5292 mono_loader_clear_error ();
5294 exl
= mono_array_new (domain
, mono_defaults
.exception_class
, length
);
5295 /* Types for which mono_class_get () succeeded */
5296 for (i
= 0, tmp
= list
; tmp
; i
++, tmp
= tmp
->next
) {
5297 MonoException
*exc
= mono_class_get_exception_for_failure (tmp
->data
);
5298 mono_array_setref (exl
, i
, exc
);
5300 /* Types for which it don't */
5301 for (j
= 0; j
< mono_array_length (exceptions
); ++j
) {
5302 MonoException
*exc
= mono_array_get (exceptions
, MonoException
*, j
);
5304 g_assert (i
< length
);
5305 mono_array_setref (exl
, i
, exc
);
5312 exc
= mono_get_exception_reflection_type_load (res
, exl
);
5313 mono_loader_clear_error ();
5314 mono_raise_exception (exc
);
5321 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName
*name
, MonoString
*assname
)
5323 MonoAssemblyName aname
;
5324 MonoDomain
*domain
= mono_object_domain (name
);
5326 gboolean is_version_defined
;
5327 gboolean is_token_defined
;
5329 aname
.public_key
= NULL
;
5330 val
= mono_string_to_utf8 (assname
);
5331 if (!mono_assembly_name_parse_full (val
, &aname
, TRUE
, &is_version_defined
, &is_token_defined
)) {
5332 g_free ((guint8
*) aname
.public_key
);
5337 fill_reflection_assembly_name (domain
, name
, &aname
, "", is_version_defined
,
5338 FALSE
, is_token_defined
);
5340 mono_assembly_name_free (&aname
);
5341 g_free ((guint8
*) aname
.public_key
);
5347 static MonoReflectionType
*
5348 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule
*module
)
5350 MonoDomain
*domain
= mono_object_domain (module
);
5353 MONO_ARCH_SAVE_REGS
;
5355 g_assert (module
->image
);
5357 if (module
->image
->dynamic
&& ((MonoDynamicImage
*)(module
->image
))->initial_image
)
5358 /* These images do not have a global type */
5361 klass
= mono_class_get (module
->image
, 1 | MONO_TOKEN_TYPE_DEF
);
5362 return mono_type_get_object (domain
, &klass
->byval_arg
);
5366 ves_icall_System_Reflection_Module_Close (MonoReflectionModule
*module
)
5368 /*if (module->image)
5369 mono_image_close (module->image);*/
5373 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule
*module
)
5375 MonoDomain
*domain
= mono_object_domain (module
);
5377 MONO_ARCH_SAVE_REGS
;
5379 g_assert (module
->image
);
5380 return mono_string_new (domain
, module
->image
->guid
);
5384 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule
*module
)
5387 if (module
->image
&& module
->image
->is_module_handle
)
5388 return module
->image
->raw_data
;
5391 return (gpointer
) (-1);
5395 ves_icall_System_Reflection_Module_GetPEKind (MonoImage
*image
, gint32
*pe_kind
, gint32
*machine
)
5397 if (image
->dynamic
) {
5398 MonoDynamicImage
*dyn
= (MonoDynamicImage
*)image
;
5399 *pe_kind
= dyn
->pe_kind
;
5400 *machine
= dyn
->machine
;
5403 *pe_kind
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_cli_header
.ch_flags
& 0x3;
5404 *machine
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_header
.coff
.coff_machine
;
5409 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage
*image
)
5411 return (image
->md_version_major
<< 16) | (image
->md_version_minor
);
5415 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule
*module
)
5417 MonoArray
*exceptions
;
5420 MONO_ARCH_SAVE_REGS
;
5423 return mono_array_new (mono_object_domain (module
), mono_defaults
.monotype_class
, 0);
5425 MonoArray
*res
= mono_module_get_types (mono_object_domain (module
), module
->image
, &exceptions
, FALSE
);
5426 for (i
= 0; i
< mono_array_length (exceptions
); ++i
) {
5427 MonoException
*ex
= mono_array_get (exceptions
, MonoException
*, i
);
5429 mono_raise_exception (ex
);
5436 mono_memberref_is_method (MonoImage
*image
, guint32 token
)
5438 if (!image
->dynamic
) {
5439 guint32 cols
[MONO_MEMBERREF_SIZE
];
5441 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
5442 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
5443 mono_metadata_decode_blob_size (sig
, &sig
);
5444 return (*sig
!= 0x6);
5446 MonoClass
*handle_class
;
5448 if (!mono_lookup_dynamic_token_class (image
, token
, FALSE
, &handle_class
, NULL
))
5451 return mono_defaults
.methodhandle_class
== handle_class
;
5456 init_generic_context_from_args (MonoGenericContext
*context
, MonoArray
*type_args
, MonoArray
*method_args
)
5459 context
->class_inst
= mono_metadata_get_generic_inst (mono_array_length (type_args
),
5460 mono_array_addr (type_args
, MonoType
*, 0));
5462 context
->class_inst
= NULL
;
5464 context
->method_inst
= mono_metadata_get_generic_inst (mono_array_length (method_args
),
5465 mono_array_addr (method_args
, MonoType
*, 0));
5467 context
->method_inst
= NULL
;
5471 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5474 int table
= mono_metadata_token_table (token
);
5475 int index
= mono_metadata_token_index (token
);
5476 MonoGenericContext context
;
5478 *error
= ResolveTokenError_Other
;
5480 /* Validate token */
5481 if ((table
!= MONO_TABLE_TYPEDEF
) && (table
!= MONO_TABLE_TYPEREF
) &&
5482 (table
!= MONO_TABLE_TYPESPEC
)) {
5483 *error
= ResolveTokenError_BadTable
;
5487 if (image
->dynamic
) {
5488 if ((table
== MONO_TABLE_TYPEDEF
) || (table
== MONO_TABLE_TYPEREF
)) {
5489 klass
= mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5490 return klass
? &klass
->byval_arg
: NULL
;
5493 init_generic_context_from_args (&context
, type_args
, method_args
);
5494 klass
= mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
);
5495 return klass
? &klass
->byval_arg
: NULL
;
5498 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5499 *error
= ResolveTokenError_OutOfRange
;
5503 init_generic_context_from_args (&context
, type_args
, method_args
);
5504 klass
= mono_class_get_full (image
, token
, &context
);
5506 if (mono_loader_get_last_error ())
5507 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5510 return &klass
->byval_arg
;
5516 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5518 int table
= mono_metadata_token_table (token
);
5519 int index
= mono_metadata_token_index (token
);
5520 MonoGenericContext context
;
5523 *error
= ResolveTokenError_Other
;
5525 /* Validate token */
5526 if ((table
!= MONO_TABLE_METHOD
) && (table
!= MONO_TABLE_METHODSPEC
) &&
5527 (table
!= MONO_TABLE_MEMBERREF
)) {
5528 *error
= ResolveTokenError_BadTable
;
5532 if (image
->dynamic
) {
5533 if (table
== MONO_TABLE_METHOD
)
5534 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5536 if ((table
== MONO_TABLE_MEMBERREF
) && !(mono_memberref_is_method (image
, token
))) {
5537 *error
= ResolveTokenError_BadTable
;
5541 init_generic_context_from_args (&context
, type_args
, method_args
);
5542 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
);
5545 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5546 *error
= ResolveTokenError_OutOfRange
;
5549 if ((table
== MONO_TABLE_MEMBERREF
) && (!mono_memberref_is_method (image
, token
))) {
5550 *error
= ResolveTokenError_BadTable
;
5554 init_generic_context_from_args (&context
, type_args
, method_args
);
5555 method
= mono_get_method_full (image
, token
, NULL
, &context
);
5557 if (mono_loader_get_last_error ())
5558 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5564 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*error
)
5566 int index
= mono_metadata_token_index (token
);
5568 *error
= ResolveTokenError_Other
;
5570 /* Validate token */
5571 if (mono_metadata_token_code (token
) != MONO_TOKEN_STRING
) {
5572 *error
= ResolveTokenError_BadTable
;
5577 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5579 if ((index
<= 0) || (index
>= image
->heap_us
.size
)) {
5580 *error
= ResolveTokenError_OutOfRange
;
5584 /* FIXME: What to do if the index points into the middle of a string ? */
5586 return mono_ldstr (mono_domain_get (), image
, index
);
5589 static MonoClassField
*
5590 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5593 int table
= mono_metadata_token_table (token
);
5594 int index
= mono_metadata_token_index (token
);
5595 MonoGenericContext context
;
5596 MonoClassField
*field
;
5598 *error
= ResolveTokenError_Other
;
5600 /* Validate token */
5601 if ((table
!= MONO_TABLE_FIELD
) && (table
!= MONO_TABLE_MEMBERREF
)) {
5602 *error
= ResolveTokenError_BadTable
;
5606 if (image
->dynamic
) {
5607 if (table
== MONO_TABLE_FIELD
)
5608 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5610 if (mono_memberref_is_method (image
, token
)) {
5611 *error
= ResolveTokenError_BadTable
;
5615 init_generic_context_from_args (&context
, type_args
, method_args
);
5616 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, &context
);
5619 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5620 *error
= ResolveTokenError_OutOfRange
;
5623 if ((table
== MONO_TABLE_MEMBERREF
) && (mono_memberref_is_method (image
, token
))) {
5624 *error
= ResolveTokenError_BadTable
;
5628 init_generic_context_from_args (&context
, type_args
, method_args
);
5629 field
= mono_field_from_token (image
, token
, &klass
, &context
);
5631 if (mono_loader_get_last_error ())
5632 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5639 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5641 int table
= mono_metadata_token_table (token
);
5643 *error
= ResolveTokenError_Other
;
5646 case MONO_TABLE_TYPEDEF
:
5647 case MONO_TABLE_TYPEREF
:
5648 case MONO_TABLE_TYPESPEC
: {
5649 MonoType
*t
= ves_icall_System_Reflection_Module_ResolveTypeToken (image
, token
, type_args
, method_args
, error
);
5651 return (MonoObject
*)mono_type_get_object (mono_domain_get (), t
);
5655 case MONO_TABLE_METHOD
:
5656 case MONO_TABLE_METHODSPEC
: {
5657 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
5659 return (MonoObject
*)mono_method_get_object (mono_domain_get (), m
, m
->klass
);
5663 case MONO_TABLE_FIELD
: {
5664 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
5666 return (MonoObject
*)mono_field_get_object (mono_domain_get (), f
->parent
, f
);
5670 case MONO_TABLE_MEMBERREF
:
5671 if (mono_memberref_is_method (image
, token
)) {
5672 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
5674 return (MonoObject
*)mono_method_get_object (mono_domain_get (), m
, m
->klass
);
5679 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
5681 return (MonoObject
*)mono_field_get_object (mono_domain_get (), f
->parent
, f
);
5688 *error
= ResolveTokenError_BadTable
;
5695 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*error
)
5697 int table
= mono_metadata_token_table (token
);
5698 int idx
= mono_metadata_token_index (token
);
5699 MonoTableInfo
*tables
= image
->tables
;
5704 *error
= ResolveTokenError_OutOfRange
;
5706 /* FIXME: Support other tables ? */
5707 if (table
!= MONO_TABLE_STANDALONESIG
)
5713 if ((idx
== 0) || (idx
> tables
[MONO_TABLE_STANDALONESIG
].rows
))
5716 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
5718 ptr
= mono_metadata_blob_heap (image
, sig
);
5719 len
= mono_metadata_decode_blob_size (ptr
, &ptr
);
5721 res
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, len
);
5722 memcpy (mono_array_addr (res
, guint8
, 0), ptr
, len
);
5726 static MonoReflectionType
*
5727 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder
*tb
, MonoString
*smodifiers
)
5730 int isbyref
= 0, rank
;
5731 char *str
= mono_string_to_utf8 (smodifiers
);
5734 MONO_ARCH_SAVE_REGS
;
5736 klass
= mono_class_from_mono_type (tb
->type
.type
);
5738 /* logic taken from mono_reflection_parse_type(): keep in sync */
5742 if (isbyref
) { /* only one level allowed by the spec */
5749 return mono_type_get_object (mono_object_domain (tb
), &klass
->this_arg
);
5752 klass
= mono_ptr_class_get (&klass
->byval_arg
);
5753 mono_class_init (klass
);
5764 else if (*p
!= '*') { /* '*' means unknown lower bound */
5775 klass
= mono_array_class_get (klass
, rank
);
5776 mono_class_init (klass
);
5783 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
5787 ves_icall_Type_IsArrayImpl (MonoReflectionType
*t
)
5792 MONO_ARCH_SAVE_REGS
;
5795 res
= !type
->byref
&& (type
->type
== MONO_TYPE_ARRAY
|| type
->type
== MONO_TYPE_SZARRAY
);
5801 check_for_invalid_type (MonoClass
*klass
)
5805 if (klass
->byval_arg
.type
!= MONO_TYPE_TYPEDBYREF
)
5808 name
= mono_type_get_full_name (klass
);
5809 str
= mono_string_new (mono_domain_get (), name
);
5811 mono_raise_exception ((MonoException
*)mono_get_exception_type_load (str
, NULL
));
5814 static MonoReflectionType
*
5815 ves_icall_Type_make_array_type (MonoReflectionType
*type
, int rank
)
5817 MonoClass
*klass
, *aklass
;
5819 MONO_ARCH_SAVE_REGS
;
5821 klass
= mono_class_from_mono_type (type
->type
);
5822 check_for_invalid_type (klass
);
5824 if (rank
== 0) //single dimentional array
5825 aklass
= mono_array_class_get (klass
, 1);
5827 aklass
= mono_bounded_array_class_get (klass
, rank
, TRUE
);
5829 return mono_type_get_object (mono_object_domain (type
), &aklass
->byval_arg
);
5832 static MonoReflectionType
*
5833 ves_icall_Type_make_byref_type (MonoReflectionType
*type
)
5837 MONO_ARCH_SAVE_REGS
;
5839 klass
= mono_class_from_mono_type (type
->type
);
5840 mono_class_init_or_throw (klass
);
5841 check_for_invalid_type (klass
);
5843 return mono_type_get_object (mono_object_domain (type
), &klass
->this_arg
);
5846 static MonoReflectionType
*
5847 ves_icall_Type_MakePointerType (MonoReflectionType
*type
)
5849 MonoClass
*klass
, *pklass
;
5851 klass
= mono_class_from_mono_type (type
->type
);
5852 mono_class_init_or_throw (klass
);
5853 check_for_invalid_type (klass
);
5855 pklass
= mono_ptr_class_get (type
->type
);
5857 return mono_type_get_object (mono_object_domain (type
), &pklass
->byval_arg
);
5861 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType
*type
, MonoObject
*target
,
5862 MonoReflectionMethod
*info
, MonoBoolean throwOnBindFailure
)
5864 MonoClass
*delegate_class
= mono_class_from_mono_type (type
->type
);
5865 MonoObject
*delegate
;
5867 MonoMethod
*method
= info
->method
;
5869 MONO_ARCH_SAVE_REGS
;
5871 mono_class_init_or_throw (delegate_class
);
5873 mono_assert (delegate_class
->parent
== mono_defaults
.multicastdelegate_class
);
5875 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
) {
5876 if (!mono_security_core_clr_ensure_delegate_creation (method
, throwOnBindFailure
))
5880 delegate
= mono_object_new (mono_object_domain (type
), delegate_class
);
5882 if (method
->dynamic
) {
5883 /* Creating a trampoline would leak memory */
5884 func
= mono_compile_method (method
);
5886 if (target
&& method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
&& method
->klass
!= mono_object_class (target
))
5887 method
= mono_object_get_virtual_method (target
, method
);
5888 func
= mono_create_ftnptr (mono_domain_get (),
5889 mono_runtime_create_jump_trampoline (mono_domain_get (), method
, TRUE
));
5892 mono_delegate_ctor_with_method (delegate
, target
, func
, method
);
5898 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate
*this)
5900 /* Reset the invoke impl to the default one */
5901 this->invoke_impl
= mono_runtime_create_delegate_trampoline (this->object
.vtable
->klass
);
5905 * Magic number to convert a time which is relative to
5906 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5908 #define EPOCH_ADJUST ((guint64)62135596800LL)
5911 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5913 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5916 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5918 convert_to_absolute_date(SYSTEMTIME
*date
)
5920 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5921 static int days_in_month
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5922 static int leap_days_in_month
[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5923 /* from the calendar FAQ */
5924 int a
= (14 - date
->wMonth
) / 12;
5925 int y
= date
->wYear
- a
;
5926 int m
= date
->wMonth
+ 12 * a
- 2;
5927 int d
= (1 + y
+ y
/4 - y
/100 + y
/400 + (31*m
)/12) % 7;
5929 /* d is now the day of the week for the first of the month (0 == Sunday) */
5931 int day_of_week
= date
->wDayOfWeek
;
5933 /* set day_in_month to the first day in the month which falls on day_of_week */
5934 int day_in_month
= 1 + (day_of_week
- d
);
5935 if (day_in_month
<= 0)
5938 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5939 date
->wDay
= day_in_month
+ (date
->wDay
- 1) * 7;
5940 if (date
->wDay
> (IS_LEAP(date
->wYear
) ? leap_days_in_month
[date
->wMonth
- 1] : days_in_month
[date
->wMonth
- 1]))
5947 * Return's the offset from GMT of a local time.
5949 * tm is a local time
5950 * t is the same local time as seconds.
5953 gmt_offset(struct tm
*tm
, time_t t
)
5955 #if defined (HAVE_TM_GMTOFF)
5956 return tm
->tm_gmtoff
;
5961 g
.tm_isdst
= tm
->tm_isdst
;
5963 return (int)difftime(t
, t2
);
5968 * This is heavily based on zdump.c from glibc 2.2.
5970 * * data[0]: start of daylight saving time (in DateTime ticks).
5971 * * data[1]: end of daylight saving time (in DateTime ticks).
5972 * * data[2]: utcoffset (in TimeSpan ticks).
5973 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5974 * * name[0]: name of this timezone when not daylight saving.
5975 * * name[1]: name of this timezone when daylight saving.
5977 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5978 * the class library allows years between 1 and 9999.
5980 * Returns true on success and zero on failure.
5983 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year
, MonoArray
**data
, MonoArray
**names
)
5986 MonoDomain
*domain
= mono_domain_get ();
5987 struct tm start
, tt
;
5991 int is_daylight
= 0, day
;
5994 MONO_ARCH_SAVE_REGS
;
5996 MONO_CHECK_ARG_NULL (data
);
5997 MONO_CHECK_ARG_NULL (names
);
5999 mono_gc_wbarrier_generic_store (data
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.int64_class
, 4));
6000 mono_gc_wbarrier_generic_store (names
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.string_class
, 2));
6003 * no info is better than crashing: we'll need our own tz data
6004 * to make this work properly, anyway. The range is probably
6005 * reduced to 1970 .. 2037 because that is what mktime is
6006 * guaranteed to support (we get into an infinite loop
6010 memset (&start
, 0, sizeof (start
));
6013 start
.tm_year
= year
-1900;
6015 t
= mktime (&start
);
6017 if ((year
< 1970) || (year
> 2037) || (t
== -1)) {
6019 tt
= *localtime (&t
);
6020 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
6021 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
6022 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
6026 gmtoff
= gmt_offset (&start
, t
);
6028 /* For each day of the year, calculate the tm_gmtoff. */
6029 for (day
= 0; day
< 365; day
++) {
6032 tt
= *localtime (&t
);
6034 /* Daylight saving starts or ends here. */
6035 if (gmt_offset (&tt
, t
) != gmtoff
) {
6039 /* Try to find the exact hour when daylight saving starts/ends. */
6043 tt1
= *localtime (&t1
);
6044 } while (gmt_offset (&tt1
, t1
) != gmtoff
);
6046 /* Try to find the exact minute when daylight saving starts/ends. */
6049 tt1
= *localtime (&t1
);
6050 } while (gmt_offset (&tt1
, t1
) == gmtoff
);
6052 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
6054 /* Write data, if we're already in daylight saving, we're done. */
6056 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
6057 mono_array_set ((*data
), gint64
, 1, ((gint64
)t1
+ EPOCH_ADJUST
) * 10000000L);
6063 memset (&end
, 0, sizeof (end
));
6064 end
.tm_year
= year
-1900 + 1;
6069 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
6070 mono_array_set ((*data
), gint64
, 0, ((gint64
)t1
+ EPOCH_ADJUST
) * 10000000L);
6071 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
6072 mono_array_set ((*data
), gint64
, 1, ((gint64
)te
+ EPOCH_ADJUST
) * 10000000L);
6076 /* This is only set once when we enter daylight saving. */
6077 mono_array_set ((*data
), gint64
, 2, (gint64
)gmtoff
* 10000000L);
6078 mono_array_set ((*data
), gint64
, 3, (gint64
)(gmt_offset (&tt
, t
) - gmtoff
) * 10000000L);
6080 gmtoff
= gmt_offset (&tt
, t
);
6085 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
6086 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
6087 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
6088 mono_array_set ((*data
), gint64
, 0, 0);
6089 mono_array_set ((*data
), gint64
, 1, 0);
6090 mono_array_set ((*data
), gint64
, 2, (gint64
) gmtoff
* 10000000L);
6091 mono_array_set ((*data
), gint64
, 3, 0);
6096 MonoDomain
*domain
= mono_domain_get ();
6097 TIME_ZONE_INFORMATION tz_info
;
6102 tz_id
= GetTimeZoneInformation (&tz_info
);
6103 if (tz_id
== TIME_ZONE_ID_INVALID
)
6106 MONO_CHECK_ARG_NULL (data
);
6107 MONO_CHECK_ARG_NULL (names
);
6109 mono_gc_wbarrier_generic_store (data
, mono_array_new (domain
, mono_defaults
.int64_class
, 4));
6110 mono_gc_wbarrier_generic_store (names
, mono_array_new (domain
, mono_defaults
.string_class
, 2));
6112 for (i
= 0; i
< 32; ++i
)
6113 if (!tz_info
.DaylightName
[i
])
6115 mono_array_setref ((*names
), 1, mono_string_new_utf16 (domain
, tz_info
.DaylightName
, i
));
6116 for (i
= 0; i
< 32; ++i
)
6117 if (!tz_info
.StandardName
[i
])
6119 mono_array_setref ((*names
), 0, mono_string_new_utf16 (domain
, tz_info
.StandardName
, i
));
6121 if ((year
<= 1601) || (year
> 30827)) {
6123 * According to MSDN, the MS time functions can't handle dates outside
6129 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6130 if (tz_id
!= TIME_ZONE_ID_UNKNOWN
) {
6131 tz_info
.StandardDate
.wYear
= year
;
6132 convert_to_absolute_date(&tz_info
.StandardDate
);
6133 err
= SystemTimeToFileTime (&tz_info
.StandardDate
, &ft
);
6138 mono_array_set ((*data
), gint64
, 1, FILETIME_ADJUST
+ (((guint64
)ft
.dwHighDateTime
<<32) | ft
.dwLowDateTime
));
6139 tz_info
.DaylightDate
.wYear
= year
;
6140 convert_to_absolute_date(&tz_info
.DaylightDate
);
6141 err
= SystemTimeToFileTime (&tz_info
.DaylightDate
, &ft
);
6146 mono_array_set ((*data
), gint64
, 0, FILETIME_ADJUST
+ (((guint64
)ft
.dwHighDateTime
<<32) | ft
.dwLowDateTime
));
6148 mono_array_set ((*data
), gint64
, 2, (tz_info
.Bias
+ tz_info
.StandardBias
) * -600000000LL);
6149 mono_array_set ((*data
), gint64
, 3, (tz_info
.DaylightBias
- tz_info
.StandardBias
) * -600000000LL);
6156 ves_icall_System_Object_obj_address (MonoObject
*this)
6158 MONO_ARCH_SAVE_REGS
;
6165 static inline gint32
6166 mono_array_get_byte_length (MonoArray
*array
)
6172 klass
= array
->obj
.vtable
->klass
;
6174 if (array
->bounds
== NULL
)
6175 length
= array
->max_length
;
6178 for (i
= 0; i
< klass
->rank
; ++ i
)
6179 length
*= array
->bounds
[i
].length
;
6182 switch (klass
->element_class
->byval_arg
.type
) {
6185 case MONO_TYPE_BOOLEAN
:
6189 case MONO_TYPE_CHAR
:
6197 return length
* sizeof (gpointer
);
6208 ves_icall_System_Buffer_ByteLengthInternal (MonoArray
*array
)
6210 MONO_ARCH_SAVE_REGS
;
6212 return mono_array_get_byte_length (array
);
6216 ves_icall_System_Buffer_GetByteInternal (MonoArray
*array
, gint32 idx
)
6218 MONO_ARCH_SAVE_REGS
;
6220 return mono_array_get (array
, gint8
, idx
);
6224 ves_icall_System_Buffer_SetByteInternal (MonoArray
*array
, gint32 idx
, gint8 value
)
6226 MONO_ARCH_SAVE_REGS
;
6228 mono_array_set (array
, gint8
, idx
, value
);
6232 ves_icall_System_Buffer_BlockCopyInternal (MonoArray
*src
, gint32 src_offset
, MonoArray
*dest
, gint32 dest_offset
, gint32 count
)
6234 guint8
*src_buf
, *dest_buf
;
6236 MONO_ARCH_SAVE_REGS
;
6238 /* This is called directly from the class libraries without going through the managed wrapper */
6239 MONO_CHECK_ARG_NULL (src
);
6240 MONO_CHECK_ARG_NULL (dest
);
6242 /* watch out for integer overflow */
6243 if ((src_offset
> mono_array_get_byte_length (src
) - count
) || (dest_offset
> mono_array_get_byte_length (dest
) - count
))
6246 src_buf
= (guint8
*)src
->vector
+ src_offset
;
6247 dest_buf
= (guint8
*)dest
->vector
+ dest_offset
;
6250 memcpy (dest_buf
, src_buf
, count
);
6252 mono_gc_memmove (dest_buf
, src_buf
, count
); /* Source and dest are the same array */
6258 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject
*this, MonoString
*class_name
)
6260 MonoDomain
*domain
= mono_object_domain (this);
6262 MonoRealProxy
*rp
= ((MonoRealProxy
*)this);
6263 MonoTransparentProxy
*tp
;
6267 MONO_ARCH_SAVE_REGS
;
6269 res
= mono_object_new (domain
, mono_defaults
.transparent_proxy_class
);
6270 tp
= (MonoTransparentProxy
*) res
;
6272 MONO_OBJECT_SETREF (tp
, rp
, rp
);
6273 type
= ((MonoReflectionType
*)rp
->class_to_proxy
)->type
;
6274 klass
= mono_class_from_mono_type (type
);
6276 tp
->custom_type_info
= (mono_object_isinst (this, mono_defaults
.iremotingtypeinfo_class
) != NULL
);
6277 tp
->remote_class
= mono_remote_class (domain
, class_name
, klass
);
6279 res
->vtable
= mono_remote_class_vtable (domain
, tp
->remote_class
, rp
);
6283 static MonoReflectionType
*
6284 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy
*tp
)
6286 return mono_type_get_object (mono_object_domain (tp
), &tp
->remote_class
->proxy_class
->byval_arg
);
6289 /* System.Environment */
6292 ves_icall_System_Environment_get_UserName (void)
6294 MONO_ARCH_SAVE_REGS
;
6296 /* using glib is more portable */
6297 return mono_string_new (mono_domain_get (), g_get_user_name ());
6302 ves_icall_System_Environment_get_MachineName (void)
6304 #if defined (HOST_WIN32)
6309 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
6310 buf
= g_new (gunichar2
, len
);
6313 if (GetComputerName (buf
, (PDWORD
) &len
))
6314 result
= mono_string_new_utf16 (mono_domain_get (), buf
, len
);
6318 #elif !defined(DISABLE_SOCKETS)
6322 if (gethostname (buf
, sizeof (buf
)) == 0)
6323 result
= mono_string_new (mono_domain_get (), buf
);
6329 return mono_string_new (mono_domain_get (), "mono");
6334 ves_icall_System_Environment_get_Platform (void)
6336 #if defined (TARGET_WIN32)
6339 #elif defined(__MACH__)
6342 // Notice that the value is hidden from user code, and only exposed
6343 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6344 // define and making assumptions based on Unix/128/4 values before there
6345 // was a MacOS define. Lots of code would assume that not-Unix meant
6346 // Windows, but in this case, it would be OSX.
6356 ves_icall_System_Environment_get_NewLine (void)
6358 MONO_ARCH_SAVE_REGS
;
6360 #if defined (HOST_WIN32)
6361 return mono_string_new (mono_domain_get (), "\r\n");
6363 return mono_string_new (mono_domain_get (), "\n");
6368 ves_icall_System_Environment_GetEnvironmentVariable (MonoString
*name
)
6373 MONO_ARCH_SAVE_REGS
;
6378 utf8_name
= mono_string_to_utf8 (name
); /* FIXME: this should be ascii */
6379 value
= g_getenv (utf8_name
);
6386 return mono_string_new (mono_domain_get (), value
);
6390 * There is no standard way to get at environ.
6393 #ifndef __MINGW32_VERSION
6394 #if defined(__APPLE__) && !defined (__arm__)
6395 /* Apple defines this in crt_externs.h but doesn't provide that header for
6396 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6397 * in fact exist on all implementations (so far)
6399 gchar
***_NSGetEnviron(void);
6400 #define environ (*_NSGetEnviron())
6409 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6420 env_strings
= GetEnvironmentStrings();
6423 env_string
= env_strings
;
6424 while (*env_string
!= '\0') {
6425 /* weird case that MS seems to skip */
6426 if (*env_string
!= '=')
6428 while (*env_string
!= '\0')
6434 domain
= mono_domain_get ();
6435 names
= mono_array_new (domain
, mono_defaults
.string_class
, n
);
6439 env_string
= env_strings
;
6440 while (*env_string
!= '\0') {
6441 /* weird case that MS seems to skip */
6442 if (*env_string
!= '=') {
6443 equal_str
= wcschr(env_string
, '=');
6444 g_assert(equal_str
);
6445 str
= mono_string_new_utf16 (domain
, env_string
, equal_str
-env_string
);
6446 mono_array_setref (names
, n
, str
);
6449 while (*env_string
!= '\0')
6454 FreeEnvironmentStrings (env_strings
);
6466 MONO_ARCH_SAVE_REGS
;
6469 for (e
= environ
; *e
!= 0; ++ e
)
6472 domain
= mono_domain_get ();
6473 names
= mono_array_new (domain
, mono_defaults
.string_class
, n
);
6476 for (e
= environ
; *e
!= 0; ++ e
) {
6477 parts
= g_strsplit (*e
, "=", 2);
6479 str
= mono_string_new (domain
, *parts
);
6480 mono_array_setref (names
, n
, str
);
6493 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6495 #if !GLIB_CHECK_VERSION(2,4,0)
6496 #define g_setenv(a,b,c) setenv(a,b,c)
6497 #define g_unsetenv(a) unsetenv(a)
6501 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString
*name
, MonoString
*value
)
6506 gunichar2
*utf16_name
, *utf16_value
;
6508 gchar
*utf8_name
, *utf8_value
;
6511 MONO_ARCH_SAVE_REGS
;
6514 utf16_name
= mono_string_to_utf16 (name
);
6515 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
6516 SetEnvironmentVariable (utf16_name
, NULL
);
6517 g_free (utf16_name
);
6521 utf16_value
= mono_string_to_utf16 (value
);
6523 SetEnvironmentVariable (utf16_name
, utf16_value
);
6525 g_free (utf16_name
);
6526 g_free (utf16_value
);
6528 utf8_name
= mono_string_to_utf8 (name
); /* FIXME: this should be ascii */
6530 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
6531 g_unsetenv (utf8_name
);
6536 utf8_value
= mono_string_to_utf8_checked (value
, &error
);
6537 if (!mono_error_ok (&error
)) {
6539 mono_error_raise_exception (&error
);
6541 g_setenv (utf8_name
, utf8_value
, TRUE
);
6544 g_free (utf8_value
);
6549 ves_icall_System_Environment_Exit (int result
)
6551 MONO_ARCH_SAVE_REGS
;
6553 mono_threads_set_shutting_down ();
6555 mono_runtime_set_shutting_down ();
6557 /* This will kill the tp threads which cannot be suspended */
6558 mono_thread_pool_cleanup ();
6560 /* Suspend all managed threads since the runtime is going away */
6561 mono_thread_suspend_all_other_threads ();
6563 mono_runtime_quit ();
6565 /* we may need to do some cleanup here... */
6570 ves_icall_System_Environment_GetGacPath (void)
6572 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6576 ves_icall_System_Environment_GetWindowsFolderPath (int folder
)
6578 #if defined (HOST_WIN32)
6579 #ifndef CSIDL_FLAG_CREATE
6580 #define CSIDL_FLAG_CREATE 0x8000
6583 WCHAR path
[MAX_PATH
];
6584 /* Create directory if no existing */
6585 if (SUCCEEDED (SHGetFolderPathW (NULL
, folder
| CSIDL_FLAG_CREATE
, NULL
, 0, path
))) {
6589 return mono_string_new_utf16 (mono_domain_get (), path
, len
);
6592 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6594 return mono_string_new (mono_domain_get (), "");
6598 ves_icall_System_Environment_GetLogicalDrives (void)
6600 gunichar2 buf
[256], *ptr
, *dname
;
6602 guint initial_size
= 127, size
= 128;
6605 MonoString
*drivestr
;
6606 MonoDomain
*domain
= mono_domain_get ();
6609 MONO_ARCH_SAVE_REGS
;
6614 while (size
> initial_size
) {
6615 size
= (guint
) GetLogicalDriveStrings (initial_size
, ptr
);
6616 if (size
> initial_size
) {
6619 ptr
= g_malloc0 ((size
+ 1) * sizeof (gunichar2
));
6620 initial_size
= size
;
6634 result
= mono_array_new (domain
, mono_defaults
.string_class
, ndrives
);
6639 while (*u16
) { u16
++; len
++; }
6640 drivestr
= mono_string_new_utf16 (domain
, dname
, len
);
6641 mono_array_setref (result
, ndrives
++, drivestr
);
6652 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString
*path
)
6654 gunichar2 volume_name
[MAX_PATH
+ 1];
6656 if (GetVolumeInformation (mono_string_chars (path
), NULL
, 0, NULL
, NULL
, NULL
, volume_name
, MAX_PATH
+ 1) == FALSE
)
6658 /* Not sure using wcslen here is safe */
6659 return mono_string_from_utf16 (volume_name
);
6663 ves_icall_System_Environment_InternalGetHome (void)
6665 MONO_ARCH_SAVE_REGS
;
6667 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6670 static const char *encodings
[] = {
6672 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6673 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6674 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6676 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6677 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6678 "x_unicode_2_0_utf_7",
6680 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6681 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6683 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6686 "unicodefffe", "utf_16be",
6693 * Returns the internal codepage, if the value of "int_code_page" is
6694 * 1 at entry, and we can not compute a suitable code page number,
6695 * returns the code page as a string
6698 ves_icall_System_Text_Encoding_InternalCodePage (gint32
*int_code_page
)
6703 char *codepage
= NULL
;
6705 int want_name
= *int_code_page
;
6708 *int_code_page
= -1;
6709 MONO_ARCH_SAVE_REGS
;
6711 g_get_charset (&cset
);
6712 c
= codepage
= strdup (cset
);
6713 for (c
= codepage
; *c
; c
++){
6714 if (isascii (*c
) && isalpha (*c
))
6719 /* g_print ("charset: %s\n", cset); */
6721 /* handle some common aliases */
6724 for (i
= 0; p
!= 0; ){
6725 if ((gssize
) p
< 7){
6727 p
= encodings
[++i
];
6730 if (strcmp (p
, codepage
) == 0){
6731 *int_code_page
= code
;
6734 p
= encodings
[++i
];
6737 if (strstr (codepage
, "utf_8") != NULL
)
6738 *int_code_page
|= 0x10000000;
6741 if (want_name
&& *int_code_page
== -1)
6742 return mono_string_new (mono_domain_get (), cset
);
6748 ves_icall_System_Environment_get_HasShutdownStarted (void)
6750 if (mono_runtime_is_shutting_down ())
6753 if (mono_domain_is_unloading (mono_domain_get ()))
6760 ves_icall_System_Environment_BroadcastSettingChange (void)
6763 SendMessageTimeout (HWND_BROADCAST
, WM_SETTINGCHANGE
, NULL
, L
"Environment", SMTO_ABORTIFHUNG
, 2000, 0);
6768 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage
*this,
6769 MonoReflectionMethod
*method
,
6770 MonoArray
*out_args
)
6772 MONO_ARCH_SAVE_REGS
;
6774 mono_message_init (mono_object_domain (this), this, method
, out_args
);
6778 ves_icall_IsTransparentProxy (MonoObject
*proxy
)
6780 MONO_ARCH_SAVE_REGS
;
6785 if (proxy
->vtable
->klass
== mono_defaults
.transparent_proxy_class
)
6791 static MonoReflectionMethod
*
6792 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6793 MonoReflectionType
*rtype
, MonoReflectionMethod
*rmethod
)
6797 MonoMethod
**vtable
;
6798 MonoMethod
*res
= NULL
;
6800 MONO_CHECK_ARG_NULL (rtype
);
6801 MONO_CHECK_ARG_NULL (rmethod
);
6803 method
= rmethod
->method
;
6804 klass
= mono_class_from_mono_type (rtype
->type
);
6805 mono_class_init_or_throw (klass
);
6807 if (MONO_CLASS_IS_INTERFACE (klass
))
6810 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
)
6813 if ((method
->flags
& METHOD_ATTRIBUTE_FINAL
) || !(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
6814 if (klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
))
6820 mono_class_setup_vtable (klass
);
6821 vtable
= klass
->vtable
;
6823 if (method
->klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
6824 gboolean variance_used
= FALSE
;
6825 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6826 int offs
= mono_class_interface_offset_with_variance (klass
, method
->klass
, &variance_used
);
6828 res
= vtable
[offs
+ method
->slot
];
6830 if (!(klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
)))
6833 if (method
->slot
!= -1)
6834 res
= vtable
[method
->slot
];
6840 return mono_method_get_object (mono_domain_get (), res
, NULL
);
6844 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType
*type
, MonoBoolean enable
)
6849 MONO_ARCH_SAVE_REGS
;
6851 klass
= mono_class_from_mono_type (type
->type
);
6852 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, TRUE
);
6854 if (enable
) vtable
->remote
= 1;
6855 else vtable
->remote
= 0;
6859 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType
*type
)
6864 MONO_ARCH_SAVE_REGS
;
6866 domain
= mono_object_domain (type
);
6867 klass
= mono_class_from_mono_type (type
->type
);
6868 mono_class_init_or_throw (klass
);
6870 if (MONO_CLASS_IS_INTERFACE (klass
) || (klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
))
6871 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6873 if (klass
->rank
>= 1) {
6874 g_assert (klass
->rank
== 1);
6875 return (MonoObject
*) mono_array_new (domain
, klass
->element_class
, 0);
6877 /* Bypass remoting object creation check */
6878 return mono_object_new_alloc_specific (mono_class_vtable_full (domain
, klass
, TRUE
));
6883 ves_icall_System_IO_get_temp_path (void)
6885 MONO_ARCH_SAVE_REGS
;
6887 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6890 #ifndef PLATFORM_NO_DRIVEINFO
6892 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString
*path_name
, guint64
*free_bytes_avail
,
6893 guint64
*total_number_of_bytes
, guint64
*total_number_of_free_bytes
,
6897 ULARGE_INTEGER wapi_free_bytes_avail
;
6898 ULARGE_INTEGER wapi_total_number_of_bytes
;
6899 ULARGE_INTEGER wapi_total_number_of_free_bytes
;
6901 MONO_ARCH_SAVE_REGS
;
6903 *error
= ERROR_SUCCESS
;
6904 result
= GetDiskFreeSpaceEx (mono_string_chars (path_name
), &wapi_free_bytes_avail
, &wapi_total_number_of_bytes
,
6905 &wapi_total_number_of_free_bytes
);
6908 *free_bytes_avail
= wapi_free_bytes_avail
.QuadPart
;
6909 *total_number_of_bytes
= wapi_total_number_of_bytes
.QuadPart
;
6910 *total_number_of_free_bytes
= wapi_total_number_of_free_bytes
.QuadPart
;
6912 *free_bytes_avail
= 0;
6913 *total_number_of_bytes
= 0;
6914 *total_number_of_free_bytes
= 0;
6915 *error
= GetLastError ();
6922 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString
*root_path_name
)
6924 MONO_ARCH_SAVE_REGS
;
6926 return GetDriveType (mono_string_chars (root_path_name
));
6931 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod
*method
)
6933 MONO_ARCH_SAVE_REGS
;
6935 return mono_compile_method (method
);
6939 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6944 MONO_ARCH_SAVE_REGS
;
6946 path
= g_build_path (G_DIR_SEPARATOR_S
, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version
, "machine.config", NULL
);
6948 #if defined (HOST_WIN32)
6949 /* Avoid mixing '/' and '\\' */
6952 for (i
= strlen (path
) - 1; i
>= 0; i
--)
6953 if (path
[i
] == '/')
6957 mcpath
= mono_string_new (mono_domain_get (), path
);
6964 get_bundled_app_config (void)
6966 const gchar
*app_config
;
6969 gchar
*config_file_name
, *config_file_path
;
6973 MONO_ARCH_SAVE_REGS
;
6975 domain
= mono_domain_get ();
6976 file
= domain
->setup
->configuration_file
;
6980 // Retrieve config file and remove the extension
6981 config_file_name
= mono_string_to_utf8 (file
);
6982 config_file_path
= mono_portability_find_file (config_file_name
, TRUE
);
6983 if (!config_file_path
)
6984 config_file_path
= config_file_name
;
6985 len
= strlen (config_file_path
) - strlen (".config");
6986 module
= g_malloc0 (len
+ 1);
6987 memcpy (module
, config_file_path
, len
);
6988 // Get the config file from the module name
6989 app_config
= mono_config_string_for_assembly_file (module
);
6992 if (config_file_name
!= config_file_path
)
6993 g_free (config_file_name
);
6994 g_free (config_file_path
);
6999 return mono_string_new (mono_domain_get (), app_config
);
7003 get_bundled_machine_config (void)
7005 const gchar
*machine_config
;
7007 MONO_ARCH_SAVE_REGS
;
7009 machine_config
= mono_get_machine_config ();
7011 if (!machine_config
)
7014 return mono_string_new (mono_domain_get (), machine_config
);
7018 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7023 MONO_ARCH_SAVE_REGS
;
7025 path
= g_path_get_dirname (mono_get_config_dir ());
7027 #if defined (HOST_WIN32)
7028 /* Avoid mixing '/' and '\\' */
7031 for (i
= strlen (path
) - 1; i
>= 0; i
--)
7032 if (path
[i
] == '/')
7036 ipath
= mono_string_new (mono_domain_get (), path
);
7043 ves_icall_get_resources_ptr (MonoReflectionAssembly
*assembly
, gpointer
*result
, gint32
*size
)
7045 MonoPEResourceDataEntry
*entry
;
7048 MONO_ARCH_SAVE_REGS
;
7050 if (!assembly
|| !result
|| !size
)
7055 image
= assembly
->assembly
->image
;
7056 entry
= mono_image_lookup_resource (image
, MONO_PE_RESOURCE_ID_ASPNET_STRING
, 0, NULL
);
7060 *result
= mono_image_rva_map (image
, entry
->rde_data_offset
);
7065 *size
= entry
->rde_size
;
7071 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7073 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7077 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString
*message
)
7079 #if defined (HOST_WIN32)
7080 OutputDebugString (mono_string_chars (message
));
7082 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7086 /* Only used for value types */
7088 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType
*type
)
7093 MONO_ARCH_SAVE_REGS
;
7095 domain
= mono_object_domain (type
);
7096 klass
= mono_class_from_mono_type (type
->type
);
7097 mono_class_init_or_throw (klass
);
7099 if (mono_class_is_nullable (klass
))
7100 /* No arguments -> null */
7103 return mono_object_new (domain
, klass
);
7106 static MonoReflectionMethod
*
7107 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod
*m
, gboolean definition
)
7109 MonoClass
*klass
, *parent
;
7110 MonoMethod
*method
= m
->method
;
7111 MonoMethod
*result
= NULL
;
7114 MONO_ARCH_SAVE_REGS
;
7116 if (method
->klass
== NULL
)
7119 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
7120 MONO_CLASS_IS_INTERFACE (method
->klass
) ||
7121 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
7124 slot
= mono_method_get_vtable_slot (method
);
7128 klass
= method
->klass
;
7129 if (klass
->generic_class
)
7130 klass
= klass
->generic_class
->container_class
;
7133 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7134 for (parent
= klass
->parent
; parent
!= NULL
; parent
= parent
->parent
) {
7135 mono_class_setup_vtable (parent
);
7136 if (parent
->vtable_size
<= slot
)
7141 klass
= klass
->parent
;
7146 if (klass
== method
->klass
)
7149 /*This is possible if definition == FALSE.
7150 * Do it here to be really sure we don't read invalid memory.
7152 if (slot
>= klass
->vtable_size
)
7155 mono_class_setup_vtable (klass
);
7157 result
= klass
->vtable
[slot
];
7158 if (result
== NULL
) {
7159 /* It is an abstract method */
7160 gpointer iter
= NULL
;
7161 while ((result
= mono_class_get_methods (klass
, &iter
)))
7162 if (result
->slot
== slot
)
7169 return mono_method_get_object (mono_domain_get (), result
, NULL
);
7173 ves_icall_MonoMethod_get_name (MonoReflectionMethod
*m
)
7175 MonoMethod
*method
= m
->method
;
7177 MONO_OBJECT_SETREF (m
, name
, mono_string_new (mono_object_domain (m
), method
->name
));
7182 mono_ArgIterator_Setup (MonoArgIterator
*iter
, char* argsp
, char* start
)
7184 MONO_ARCH_SAVE_REGS
;
7186 iter
->sig
= *(MonoMethodSignature
**)argsp
;
7188 g_assert (iter
->sig
->sentinelpos
<= iter
->sig
->param_count
);
7189 g_assert (iter
->sig
->call_convention
== MONO_CALL_VARARG
);
7192 /* FIXME: it's not documented what start is exactly... */
7196 iter
->args
= argsp
+ sizeof (gpointer
);
7198 iter
->num_args
= iter
->sig
->param_count
- iter
->sig
->sentinelpos
;
7200 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7204 mono_ArgIterator_IntGetNextArg (MonoArgIterator
*iter
)
7206 guint32 i
, arg_size
;
7209 MONO_ARCH_SAVE_REGS
;
7211 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7213 g_assert (i
< iter
->sig
->param_count
);
7215 res
.type
= iter
->sig
->params
[i
];
7216 res
.klass
= mono_class_from_mono_type (res
.type
);
7217 res
.value
= iter
->args
;
7218 arg_size
= mono_type_stack_size (res
.type
, &align
);
7219 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7220 if (arg_size
<= sizeof (gpointer
)) {
7222 int padding
= arg_size
- mono_type_size (res
.type
, &dummy
);
7223 res
.value
= (guint8
*)res
.value
+ padding
;
7226 iter
->args
= (char*)iter
->args
+ arg_size
;
7229 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7235 mono_ArgIterator_IntGetNextArgT (MonoArgIterator
*iter
, MonoType
*type
)
7237 guint32 i
, arg_size
;
7240 MONO_ARCH_SAVE_REGS
;
7242 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7244 g_assert (i
< iter
->sig
->param_count
);
7246 while (i
< iter
->sig
->param_count
) {
7247 if (!mono_metadata_type_equal (type
, iter
->sig
->params
[i
]))
7249 res
.type
= iter
->sig
->params
[i
];
7250 res
.klass
= mono_class_from_mono_type (res
.type
);
7251 /* FIXME: endianess issue... */
7252 res
.value
= iter
->args
;
7253 arg_size
= mono_type_stack_size (res
.type
, &align
);
7254 iter
->args
= (char*)iter
->args
+ arg_size
;
7256 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7259 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7268 mono_ArgIterator_IntGetNextArgType (MonoArgIterator
*iter
)
7271 MONO_ARCH_SAVE_REGS
;
7273 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7275 g_assert (i
< iter
->sig
->param_count
);
7277 return iter
->sig
->params
[i
];
7281 mono_TypedReference_ToObject (MonoTypedRef tref
)
7283 MONO_ARCH_SAVE_REGS
;
7285 if (MONO_TYPE_IS_REFERENCE (tref
.type
)) {
7286 MonoObject
** objp
= tref
.value
;
7290 return mono_value_box (mono_domain_get (), tref
.klass
, tref
.value
);
7294 mono_TypedReference_ToObjectInternal (MonoType
*type
, gpointer value
, MonoClass
*klass
)
7296 MONO_ARCH_SAVE_REGS
;
7298 if (MONO_TYPE_IS_REFERENCE (type
)) {
7299 MonoObject
** objp
= value
;
7303 return mono_value_box (mono_domain_get (), klass
, value
);
7307 prelink_method (MonoMethod
*method
)
7309 const char *exc_class
, *exc_arg
;
7310 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
7312 mono_lookup_pinvoke_call (method
, &exc_class
, &exc_arg
);
7314 mono_raise_exception(
7315 mono_exception_from_name_msg (mono_defaults
.corlib
, "System", exc_class
, exc_arg
) );
7317 /* create the wrapper, too? */
7321 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod
*method
)
7323 MONO_ARCH_SAVE_REGS
;
7324 prelink_method (method
->method
);
7328 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType
*type
)
7330 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
7332 gpointer iter
= NULL
;
7333 MONO_ARCH_SAVE_REGS
;
7335 mono_class_init_or_throw (klass
);
7337 while ((m
= mono_class_get_methods (klass
, &iter
)))
7341 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7343 ves_icall_System_NumberFormatter_GetFormatterTables (guint64
const **mantissas
,
7344 gint32
const **exponents
,
7345 gunichar2
const **digitLowerTable
,
7346 gunichar2
const **digitUpperTable
,
7347 gint64
const **tenPowersList
,
7348 gint32
const **decHexDigits
)
7350 *mantissas
= Formatter_MantissaBitsTable
;
7351 *exponents
= Formatter_TensExponentTable
;
7352 *digitLowerTable
= Formatter_DigitLowerTable
;
7353 *digitUpperTable
= Formatter_DigitUpperTable
;
7354 *tenPowersList
= Formatter_TenPowersList
;
7355 *decHexDigits
= Formatter_DecHexDigits
;
7358 /* These parameters are "readonly" in corlib/System/Char.cs */
7360 ves_icall_System_Char_GetDataTablePointers (guint8
const **category_data
,
7361 guint8
const **numeric_data
,
7362 gdouble
const **numeric_data_values
,
7363 guint16
const **to_lower_data_low
,
7364 guint16
const **to_lower_data_high
,
7365 guint16
const **to_upper_data_low
,
7366 guint16
const **to_upper_data_high
)
7368 *category_data
= CategoryData
;
7369 *numeric_data
= NumericData
;
7370 *numeric_data_values
= NumericDataValues
;
7371 *to_lower_data_low
= ToLowerDataLow
;
7372 *to_lower_data_high
= ToLowerDataHigh
;
7373 *to_upper_data_low
= ToUpperDataLow
;
7374 *to_upper_data_high
= ToUpperDataHigh
;
7378 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod
*method
)
7380 return method
->method
->token
;
7384 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7385 * and avoid useless allocations.
7388 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
)
7392 for (i
= 0; i
< type
->num_mods
; ++i
) {
7393 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
))
7398 res
= mono_array_new (mono_domain_get (), mono_defaults
.systemtype_class
, count
);
7400 for (i
= 0; i
< type
->num_mods
; ++i
) {
7401 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
)) {
7402 MonoClass
*klass
= mono_class_get (image
, type
->modifiers
[i
].token
);
7403 mono_array_setref (res
, count
, mono_type_get_object (mono_domain_get (), &klass
->byval_arg
));
7411 param_info_get_type_modifiers (MonoReflectionParameter
*param
, MonoBoolean optional
)
7413 MonoType
*type
= param
->ClassImpl
->type
;
7414 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
7415 MonoMethod
*method
= NULL
;
7418 MonoMethodSignature
*sig
;
7420 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
7421 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
7422 method
= rmethod
->method
;
7423 } else if (member_class
->image
== mono_defaults
.corlib
&& !strcmp ("MonoProperty", member_class
->name
)) {
7424 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
7425 if (!(method
= prop
->property
->get
))
7426 method
= prop
->property
->set
;
7429 char *type_name
= mono_type_get_full_name (member_class
);
7430 char *msg
= g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name
);
7431 MonoException
*ex
= mono_get_exception_not_supported (msg
);
7434 mono_raise_exception (ex
);
7437 image
= method
->klass
->image
;
7438 pos
= param
->PositionImpl
;
7439 sig
= mono_method_signature (method
);
7443 type
= sig
->params
[pos
];
7445 return type_array_from_modifiers (image
, type
, optional
);
7449 get_property_type (MonoProperty
*prop
)
7451 MonoMethodSignature
*sig
;
7453 sig
= mono_method_signature (prop
->get
);
7455 } else if (prop
->set
) {
7456 sig
= mono_method_signature (prop
->set
);
7457 return sig
->params
[sig
->param_count
- 1];
7463 property_info_get_type_modifiers (MonoReflectionProperty
*property
, MonoBoolean optional
)
7465 MonoType
*type
= get_property_type (property
->property
);
7466 MonoImage
*image
= property
->klass
->image
;
7470 return type_array_from_modifiers (image
, type
, optional
);
7474 *Construct a MonoType suited to be used to decode a constant blob object.
7476 * @type is the target type which will be constructed
7477 * @blob_type is the blob type, for example, that comes from the constant table
7478 * @real_type is the expected constructed type.
7481 mono_type_from_blob_type (MonoType
*type
, MonoTypeEnum blob_type
, MonoType
*real_type
)
7483 type
->type
= blob_type
;
7484 type
->data
.klass
= NULL
;
7485 if (blob_type
== MONO_TYPE_CLASS
)
7486 type
->data
.klass
= mono_defaults
.object_class
;
7487 else if (real_type
->type
== MONO_TYPE_VALUETYPE
&& real_type
->data
.klass
->enumtype
) {
7488 /* For enums, we need to use the base type */
7489 type
->type
= MONO_TYPE_VALUETYPE
;
7490 type
->data
.klass
= mono_class_from_mono_type (real_type
);
7492 type
->data
.klass
= mono_class_from_mono_type (real_type
);
7496 property_info_get_default_value (MonoReflectionProperty
*property
)
7499 MonoProperty
*prop
= property
->property
;
7500 MonoType
*type
= get_property_type (prop
);
7501 MonoDomain
*domain
= mono_object_domain (property
);
7502 MonoTypeEnum def_type
;
7503 const char *def_value
;
7506 mono_class_init (prop
->parent
);
7508 if (!(prop
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
))
7509 mono_raise_exception (mono_get_exception_invalid_operation (NULL
));
7511 def_value
= mono_class_get_property_default_value (prop
, &def_type
);
7513 mono_type_from_blob_type (&blob_type
, def_type
, type
);
7514 o
= mono_get_object_from_blob (domain
, &blob_type
, def_value
);
7520 custom_attrs_defined_internal (MonoObject
*obj
, MonoReflectionType
*attr_type
)
7522 MonoClass
*attr_class
= mono_class_from_mono_type (attr_type
->type
);
7523 MonoCustomAttrInfo
*cinfo
;
7526 mono_class_init_or_throw (attr_class
);
7528 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
7531 found
= mono_custom_attrs_has_attr (cinfo
, attr_class
);
7533 mono_custom_attrs_free (cinfo
);
7538 custom_attrs_get_by_type (MonoObject
*obj
, MonoReflectionType
*attr_type
)
7540 MonoClass
*attr_class
= attr_type
? mono_class_from_mono_type (attr_type
->type
) : NULL
;
7545 mono_class_init_or_throw (attr_class
);
7547 res
= mono_reflection_get_custom_attrs_by_type (obj
, attr_class
, &error
);
7548 if (!mono_error_ok (&error
))
7549 mono_error_raise_exception (&error
);
7550 if (mono_loader_get_last_error ()) {
7551 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7552 g_assert_not_reached ();
7561 ves_icall_Mono_Runtime_GetDisplayName (void)
7564 MonoString
*display_name
;
7566 info
= mono_get_runtime_callbacks ()->get_runtime_build_info ();
7567 display_name
= mono_string_new (mono_domain_get (), info
);
7569 return display_name
;
7573 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code
)
7575 MonoString
*message
;
7579 ret
= FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
7580 FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, code
, 0,
7583 message
= mono_string_new (mono_domain_get (), "Error looking up error string");
7585 message
= mono_string_new_utf16 (mono_domain_get (), buf
, ret
);
7593 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7594 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7595 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7596 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7597 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7598 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7599 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7600 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7604 base64_to_byte_array (gunichar2
*start
, gint ilength
, MonoBoolean allowWhitespaceOnly
)
7609 gunichar2 last
, prev_last
, prev2_last
;
7617 last
= prev_last
= 0, prev2_last
= 0;
7618 for (i
= 0; i
< ilength
; i
++) {
7620 if (c
>= sizeof (dbase64
)) {
7621 exc
= mono_exception_from_name_msg (mono_get_corlib (),
7622 "System", "FormatException",
7623 "Invalid character found.");
7624 mono_raise_exception (exc
);
7625 } else if (isspace (c
)) {
7628 prev2_last
= prev_last
;
7634 olength
= ilength
- ignored
;
7636 if (allowWhitespaceOnly
&& olength
== 0) {
7637 return mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, 0);
7640 if ((olength
& 3) != 0 || olength
<= 0) {
7641 exc
= mono_exception_from_name_msg (mono_get_corlib (), "System",
7642 "FormatException", "Invalid length.");
7643 mono_raise_exception (exc
);
7646 if (prev2_last
== '=') {
7647 exc
= mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7648 mono_raise_exception (exc
);
7651 olength
= (olength
* 3) / 4;
7655 if (prev_last
== '=')
7658 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, olength
);
7659 res_ptr
= mono_array_addr (result
, guchar
, 0);
7660 for (i
= 0; i
< ilength
; ) {
7663 for (k
= 0; k
< 4 && i
< ilength
;) {
7669 if (((b
[k
] = dbase64
[c
]) & 0x80) != 0) {
7670 exc
= mono_exception_from_name_msg (mono_get_corlib (),
7671 "System", "FormatException",
7672 "Invalid character found.");
7673 mono_raise_exception (exc
);
7678 *res_ptr
++ = (b
[0] << 2) | (b
[1] >> 4);
7680 *res_ptr
++ = (b
[1] << 4) | (b
[2] >> 2);
7682 *res_ptr
++ = (b
[2] << 6) | b
[3];
7684 while (i
< ilength
&& isspace (start
[i
]))
7692 InternalFromBase64String (MonoString
*str
, MonoBoolean allowWhitespaceOnly
)
7694 MONO_ARCH_SAVE_REGS
;
7696 return base64_to_byte_array (mono_string_chars (str
),
7697 mono_string_length (str
), allowWhitespaceOnly
);
7701 InternalFromBase64CharArray (MonoArray
*input
, gint offset
, gint length
)
7703 MONO_ARCH_SAVE_REGS
;
7705 return base64_to_byte_array (mono_array_addr (input
, gunichar2
, offset
),
7709 #define ICALL_TYPE(id,name,first)
7710 #define ICALL(id,name,func) Icall_ ## id,
7713 #include "metadata/icall-def.h"
7719 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7720 #define ICALL(id,name,func)
7722 #include "metadata/icall-def.h"
7728 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7729 #define ICALL(id,name,func)
7731 guint16 first_icall
;
7734 static const IcallTypeDesc
7735 icall_type_descs
[] = {
7736 #include "metadata/icall-def.h"
7740 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7743 #define ICALL_TYPE(id,name,first)
7746 #ifdef HAVE_ARRAY_ELEM_INIT
7747 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7748 #define MSGSTRFIELD1(line) str##line
7750 static const struct msgstrtn_t
{
7751 #define ICALL(id,name,func)
7753 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7754 #include "metadata/icall-def.h"
7756 } icall_type_names_str
= {
7757 #define ICALL_TYPE(id,name,first) (name),
7758 #include "metadata/icall-def.h"
7761 static const guint16 icall_type_names_idx
[] = {
7762 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7763 #include "metadata/icall-def.h"
7766 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7768 static const struct msgstr_t
{
7770 #define ICALL_TYPE(id,name,first)
7771 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7772 #include "metadata/icall-def.h"
7774 } icall_names_str
= {
7775 #define ICALL(id,name,func) (name),
7776 #include "metadata/icall-def.h"
7779 static const guint16 icall_names_idx
[] = {
7780 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7781 #include "metadata/icall-def.h"
7784 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7790 #define ICALL_TYPE(id,name,first) name,
7791 #define ICALL(id,name,func)
7792 static const char* const
7793 icall_type_names
[] = {
7794 #include "metadata/icall-def.h"
7798 #define icall_type_name_get(id) (icall_type_names [(id)])
7802 #define ICALL_TYPE(id,name,first)
7803 #define ICALL(id,name,func) name,
7804 static const char* const
7806 #include "metadata/icall-def.h"
7809 #define icall_name_get(id) icall_names [(id)]
7811 #endif /* !HAVE_ARRAY_ELEM_INIT */
7815 #define ICALL_TYPE(id,name,first)
7816 #define ICALL(id,name,func) func,
7817 static const gconstpointer
7818 icall_functions
[] = {
7819 #include "metadata/icall-def.h"
7823 static GHashTable
*icall_hash
= NULL
;
7824 static GHashTable
*jit_icall_hash_name
= NULL
;
7825 static GHashTable
*jit_icall_hash_addr
= NULL
;
7828 mono_icall_init (void)
7832 /* check that tables are sorted: disable in release */
7835 const char *prev_class
= NULL
;
7836 const char *prev_method
;
7838 for (i
= 0; i
< Icall_type_num
; ++i
) {
7839 const IcallTypeDesc
*desc
;
7842 if (prev_class
&& strcmp (prev_class
, icall_type_name_get (i
)) >= 0)
7843 g_print ("class %s should come before class %s\n", icall_type_name_get (i
), prev_class
);
7844 prev_class
= icall_type_name_get (i
);
7845 desc
= &icall_type_descs
[i
];
7846 num_icalls
= icall_desc_num_icalls (desc
);
7847 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7848 for (j
= 0; j
< num_icalls
; ++j
) {
7849 const char *methodn
= icall_name_get (desc
->first_icall
+ j
);
7850 if (prev_method
&& strcmp (prev_method
, methodn
) >= 0)
7851 g_print ("method %s should come before method %s\n", methodn
, prev_method
);
7852 prev_method
= methodn
;
7857 icall_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
7861 mono_icall_cleanup (void)
7863 g_hash_table_destroy (icall_hash
);
7864 g_hash_table_destroy (jit_icall_hash_name
);
7865 g_hash_table_destroy (jit_icall_hash_addr
);
7869 mono_add_internal_call (const char *name
, gconstpointer method
)
7871 mono_loader_lock ();
7873 g_hash_table_insert (icall_hash
, g_strdup (name
), (gpointer
) method
);
7875 mono_loader_unlock ();
7878 #ifdef HAVE_ARRAY_ELEM_INIT
7880 compare_method_imap (const void *key
, const void *elem
)
7882 const char* method_name
= (const char*)&icall_names_str
+ (*(guint16
*)elem
);
7883 return strcmp (key
, method_name
);
7887 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
7889 const guint16
*nameslot
= bsearch (name
, icall_names_idx
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names_idx
[0]), compare_method_imap
);
7892 return (gpointer
)icall_functions
[(nameslot
- &icall_names_idx
[0])];
7896 compare_class_imap (const void *key
, const void *elem
)
7898 const char* class_name
= (const char*)&icall_type_names_str
+ (*(guint16
*)elem
);
7899 return strcmp (key
, class_name
);
7902 static const IcallTypeDesc
*
7903 find_class_icalls (const char *name
)
7905 const guint16
*nameslot
= bsearch (name
, icall_type_names_idx
, Icall_type_num
, sizeof (icall_type_names_idx
[0]), compare_class_imap
);
7908 return &icall_type_descs
[nameslot
- &icall_type_names_idx
[0]];
7913 compare_method_imap (const void *key
, const void *elem
)
7915 const char** method_name
= (const char**)elem
;
7916 return strcmp (key
, *method_name
);
7920 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
7922 const char **nameslot
= bsearch (name
, icall_names
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names
[0]), compare_method_imap
);
7925 return (gpointer
)icall_functions
[(nameslot
- icall_names
)];
7929 compare_class_imap (const void *key
, const void *elem
)
7931 const char** class_name
= (const char**)elem
;
7932 return strcmp (key
, *class_name
);
7935 static const IcallTypeDesc
*
7936 find_class_icalls (const char *name
)
7938 const char **nameslot
= bsearch (name
, icall_type_names
, Icall_type_num
, sizeof (icall_type_names
[0]), compare_class_imap
);
7941 return &icall_type_descs
[nameslot
- icall_type_names
];
7947 * we should probably export this as an helper (handle nested types).
7948 * Returns the number of chars written in buf.
7951 concat_class_name (char *buf
, int bufsize
, MonoClass
*klass
)
7953 int nspacelen
, cnamelen
;
7954 nspacelen
= strlen (klass
->name_space
);
7955 cnamelen
= strlen (klass
->name
);
7956 if (nspacelen
+ cnamelen
+ 2 > bufsize
)
7959 memcpy (buf
, klass
->name_space
, nspacelen
);
7960 buf
[nspacelen
++] = '.';
7962 memcpy (buf
+ nspacelen
, klass
->name
, cnamelen
);
7963 buf
[nspacelen
+ cnamelen
] = 0;
7964 return nspacelen
+ cnamelen
;
7968 mono_lookup_internal_call (MonoMethod
*method
)
7973 int typelen
= 0, mlen
, siglen
;
7975 const IcallTypeDesc
*imap
;
7977 g_assert (method
!= NULL
);
7979 if (method
->is_inflated
)
7980 method
= ((MonoMethodInflated
*) method
)->declaring
;
7982 if (method
->klass
->nested_in
) {
7983 int pos
= concat_class_name (mname
, sizeof (mname
)-2, method
->klass
->nested_in
);
7987 mname
[pos
++] = '/';
7990 typelen
= concat_class_name (mname
+pos
, sizeof (mname
)-pos
-1, method
->klass
);
7996 typelen
= concat_class_name (mname
, sizeof (mname
), method
->klass
);
8001 imap
= find_class_icalls (mname
);
8003 mname
[typelen
] = ':';
8004 mname
[typelen
+ 1] = ':';
8006 mlen
= strlen (method
->name
);
8007 memcpy (mname
+ typelen
+ 2, method
->name
, mlen
);
8008 sigstart
= mname
+ typelen
+ 2 + mlen
;
8011 tmpsig
= mono_signature_get_desc (mono_method_signature (method
), TRUE
);
8012 siglen
= strlen (tmpsig
);
8013 if (typelen
+ mlen
+ siglen
+ 6 > sizeof (mname
))
8016 memcpy (sigstart
+ 1, tmpsig
, siglen
);
8017 sigstart
[siglen
+ 1] = ')';
8018 sigstart
[siglen
+ 2] = 0;
8021 mono_loader_lock ();
8023 res
= g_hash_table_lookup (icall_hash
, mname
);
8025 mono_loader_unlock ();
8028 /* try without signature */
8030 res
= g_hash_table_lookup (icall_hash
, mname
);
8032 mono_loader_unlock ();
8036 /* it wasn't found in the static call tables */
8038 mono_loader_unlock ();
8041 res
= find_method_icall (imap
, sigstart
- mlen
);
8043 mono_loader_unlock ();
8046 /* try _with_ signature */
8048 res
= find_method_icall (imap
, sigstart
- mlen
);
8050 mono_loader_unlock ();
8054 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname
);
8055 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8056 g_print ("The out of sync library is: %s\n", method
->klass
->image
->name
);
8057 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8058 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");
8059 g_print ("If you see other errors or faults after this message they are probably related\n");
8060 g_print ("and you need to fix your mono install first.\n");
8062 mono_loader_unlock ();
8068 type_from_typename (char *typename
)
8070 MonoClass
*klass
= NULL
; /* assignment to shut GCC warning up */
8072 if (!strcmp (typename
, "int"))
8073 klass
= mono_defaults
.int_class
;
8074 else if (!strcmp (typename
, "ptr"))
8075 klass
= mono_defaults
.int_class
;
8076 else if (!strcmp (typename
, "void"))
8077 klass
= mono_defaults
.void_class
;
8078 else if (!strcmp (typename
, "int32"))
8079 klass
= mono_defaults
.int32_class
;
8080 else if (!strcmp (typename
, "uint32"))
8081 klass
= mono_defaults
.uint32_class
;
8082 else if (!strcmp (typename
, "int8"))
8083 klass
= mono_defaults
.sbyte_class
;
8084 else if (!strcmp (typename
, "uint8"))
8085 klass
= mono_defaults
.byte_class
;
8086 else if (!strcmp (typename
, "int16"))
8087 klass
= mono_defaults
.int16_class
;
8088 else if (!strcmp (typename
, "uint16"))
8089 klass
= mono_defaults
.uint16_class
;
8090 else if (!strcmp (typename
, "long"))
8091 klass
= mono_defaults
.int64_class
;
8092 else if (!strcmp (typename
, "ulong"))
8093 klass
= mono_defaults
.uint64_class
;
8094 else if (!strcmp (typename
, "float"))
8095 klass
= mono_defaults
.single_class
;
8096 else if (!strcmp (typename
, "double"))
8097 klass
= mono_defaults
.double_class
;
8098 else if (!strcmp (typename
, "object"))
8099 klass
= mono_defaults
.object_class
;
8100 else if (!strcmp (typename
, "obj"))
8101 klass
= mono_defaults
.object_class
;
8102 else if (!strcmp (typename
, "string"))
8103 klass
= mono_defaults
.string_class
;
8104 else if (!strcmp (typename
, "bool"))
8105 klass
= mono_defaults
.boolean_class
;
8106 else if (!strcmp (typename
, "boolean"))
8107 klass
= mono_defaults
.boolean_class
;
8109 g_error ("%s", typename
);
8110 g_assert_not_reached ();
8112 return &klass
->byval_arg
;
8115 MonoMethodSignature
*
8116 mono_create_icall_signature (const char *sigstr
)
8121 MonoMethodSignature
*res
;
8123 mono_loader_lock ();
8124 res
= g_hash_table_lookup (mono_defaults
.corlib
->helper_signatures
, sigstr
);
8126 mono_loader_unlock ();
8130 parts
= g_strsplit (sigstr
, " ", 256);
8139 res
= mono_metadata_signature_alloc (mono_defaults
.corlib
, len
- 1);
8144 * Under windows, the default pinvoke calling convention is STDCALL but
8147 res
->call_convention
= MONO_CALL_C
;
8150 res
->ret
= type_from_typename (parts
[0]);
8151 for (i
= 1; i
< len
; ++i
) {
8152 res
->params
[i
- 1] = type_from_typename (parts
[i
]);
8157 g_hash_table_insert (mono_defaults
.corlib
->helper_signatures
, (gpointer
)sigstr
, res
);
8159 mono_loader_unlock ();
8165 mono_find_jit_icall_by_name (const char *name
)
8167 MonoJitICallInfo
*info
;
8168 g_assert (jit_icall_hash_name
);
8170 mono_loader_lock ();
8171 info
= g_hash_table_lookup (jit_icall_hash_name
, name
);
8172 mono_loader_unlock ();
8177 mono_find_jit_icall_by_addr (gconstpointer addr
)
8179 MonoJitICallInfo
*info
;
8180 g_assert (jit_icall_hash_addr
);
8182 mono_loader_lock ();
8183 info
= g_hash_table_lookup (jit_icall_hash_addr
, (gpointer
)addr
);
8184 mono_loader_unlock ();
8190 * mono_get_jit_icall_info:
8192 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8193 * caller should access it while holding the loader lock.
8196 mono_get_jit_icall_info (void)
8198 return jit_icall_hash_name
;
8202 mono_register_jit_icall_wrapper (MonoJitICallInfo
*info
, gconstpointer wrapper
)
8204 mono_loader_lock ();
8205 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)wrapper
, info
);
8206 mono_loader_unlock ();
8210 mono_register_jit_icall (gconstpointer func
, const char *name
, MonoMethodSignature
*sig
, gboolean is_save
)
8212 MonoJitICallInfo
*info
;
8217 mono_loader_lock ();
8219 if (!jit_icall_hash_name
) {
8220 jit_icall_hash_name
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, g_free
);
8221 jit_icall_hash_addr
= g_hash_table_new (NULL
, NULL
);
8224 if (g_hash_table_lookup (jit_icall_hash_name
, name
)) {
8225 g_warning ("jit icall already defined \"%s\"\n", name
);
8226 g_assert_not_reached ();
8229 info
= g_new0 (MonoJitICallInfo
, 1);
8236 info
->wrapper
= func
;
8238 info
->wrapper
= NULL
;
8241 g_hash_table_insert (jit_icall_hash_name
, (gpointer
)info
->name
, info
);
8242 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)func
, info
);
8244 mono_loader_unlock ();