5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
21 #ifdef HAVE_SYS_TIME_H
27 #if defined (HOST_WIN32)
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/metadata/mono-ptr-array.h>
71 #include <mono/io-layer/io-layer.h>
72 #include <mono/utils/strtod.h>
73 #include <mono/utils/monobitset.h>
74 #include <mono/utils/mono-time.h>
75 #include <mono/utils/mono-proclib.h>
76 #include <mono/utils/mono-string.h>
77 #include <mono/utils/mono-error-internals.h>
78 #include <mono/utils/mono-mmap.h>
80 #if defined (HOST_WIN32)
86 extern MonoString
* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL
;
88 static MonoReflectionAssembly
* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
91 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
);
93 static inline MonoBoolean
94 is_generic_parameter (MonoType
*type
)
96 return !type
->byref
&& (type
->type
== MONO_TYPE_VAR
|| type
->type
== MONO_TYPE_MVAR
);
100 mono_class_init_or_throw (MonoClass
*klass
)
102 if (!mono_class_init (klass
))
103 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
107 * We expect a pointer to a char, not a string
110 mono_double_ParseImpl (char *ptr
, double *result
)
112 gchar
*endptr
= NULL
;
119 *result
= strtod (ptr
, &endptr
);
123 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
124 EnterCriticalSection (&mono_strtod_mutex
);
125 *result
= mono_strtod (ptr
, &endptr
);
126 LeaveCriticalSection (&mono_strtod_mutex
);
128 *result
= mono_strtod (ptr
, &endptr
);
133 if (!*ptr
|| (endptr
&& *endptr
))
140 ves_icall_System_Array_GetValueImpl (MonoObject
*this, guint32 pos
)
149 ao
= (MonoArray
*)this;
150 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
152 esize
= mono_array_element_size (ac
);
153 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
155 if (ac
->element_class
->valuetype
)
156 return mono_value_box (this->vtable
->domain
, ac
->element_class
, ea
);
162 ves_icall_System_Array_GetValue (MonoObject
*this, MonoObject
*idxs
)
170 MONO_CHECK_ARG_NULL (idxs
);
172 io
= (MonoArray
*)idxs
;
173 ic
= (MonoClass
*)io
->obj
.vtable
->klass
;
175 ao
= (MonoArray
*)this;
176 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
178 g_assert (ic
->rank
== 1);
179 if (io
->bounds
!= NULL
|| io
->max_length
!= ac
->rank
)
180 mono_raise_exception (mono_get_exception_argument (NULL
, NULL
));
182 ind
= (gint32
*)io
->vector
;
184 if (ao
->bounds
== NULL
) {
185 if (*ind
< 0 || *ind
>= ao
->max_length
)
186 mono_raise_exception (mono_get_exception_index_out_of_range ());
188 return ves_icall_System_Array_GetValueImpl (this, *ind
);
191 for (i
= 0; i
< ac
->rank
; i
++)
192 if ((ind
[i
] < ao
->bounds
[i
].lower_bound
) ||
193 (ind
[i
] >= (mono_array_lower_bound_t
)ao
->bounds
[i
].length
+ ao
->bounds
[i
].lower_bound
))
194 mono_raise_exception (mono_get_exception_index_out_of_range ());
196 pos
= ind
[0] - ao
->bounds
[0].lower_bound
;
197 for (i
= 1; i
< ac
->rank
; i
++)
198 pos
= pos
*ao
->bounds
[i
].length
+ ind
[i
] -
199 ao
->bounds
[i
].lower_bound
;
201 return ves_icall_System_Array_GetValueImpl (this, pos
);
205 ves_icall_System_Array_SetValueImpl (MonoArray
*this, MonoObject
*value
, guint32 pos
)
207 MonoClass
*ac
, *vc
, *ec
;
219 vc
= value
->vtable
->klass
;
223 ac
= this->obj
.vtable
->klass
;
224 ec
= ac
->element_class
;
226 esize
= mono_array_element_size (ac
);
227 ea
= (gpointer
*)((char*)this->vector
+ (pos
* esize
));
228 va
= (gpointer
*)((char*)value
+ sizeof (MonoObject
));
230 if (mono_class_is_nullable (ec
)) {
231 mono_nullable_init ((guint8
*)ea
, value
, ec
);
236 memset (ea
, 0, esize
);
240 #define NO_WIDENING_CONVERSION G_STMT_START{\
241 mono_raise_exception (mono_get_exception_argument ( \
242 "value", "not a widening conversion")); \
245 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
246 if (esize < vsize + (extra)) \
247 mono_raise_exception (mono_get_exception_argument ( \
248 "value", "not a widening conversion")); \
251 #define INVALID_CAST G_STMT_START{\
252 mono_raise_exception (mono_get_exception_invalid_cast ()); \
255 /* Check element (destination) type. */
256 switch (ec
->byval_arg
.type
) {
257 case MONO_TYPE_STRING
:
258 switch (vc
->byval_arg
.type
) {
259 case MONO_TYPE_STRING
:
265 case MONO_TYPE_BOOLEAN
:
266 switch (vc
->byval_arg
.type
) {
267 case MONO_TYPE_BOOLEAN
:
280 NO_WIDENING_CONVERSION
;
287 if (!ec
->valuetype
) {
288 if (!mono_object_isinst (value
, ec
))
290 mono_gc_wbarrier_set_arrayref (this, ea
, (MonoObject
*)value
);
294 if (mono_object_isinst (value
, ec
)) {
295 if (ec
->has_references
)
296 mono_value_copy (ea
, (char*)value
+ sizeof (MonoObject
), ec
);
298 memcpy (ea
, (char *)value
+ sizeof (MonoObject
), esize
);
305 vsize
= mono_class_instance_size (vc
) - sizeof (MonoObject
);
307 et
= ec
->byval_arg
.type
;
308 if (et
== MONO_TYPE_VALUETYPE
&& ec
->byval_arg
.data
.klass
->enumtype
)
309 et
= mono_class_enum_basetype (ec
->byval_arg
.data
.klass
)->type
;
311 vt
= vc
->byval_arg
.type
;
312 if (vt
== MONO_TYPE_VALUETYPE
&& vc
->byval_arg
.data
.klass
->enumtype
)
313 vt
= mono_class_enum_basetype (vc
->byval_arg
.data
.klass
)->type
;
315 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
321 case MONO_TYPE_CHAR: \
322 CHECK_WIDENING_CONVERSION(0); \
323 *(etype *) ea = (etype) u64; \
325 /* You can't assign a signed value to an unsigned array. */ \
330 /* You can't assign a floating point number to an integer array. */ \
333 NO_WIDENING_CONVERSION; \
337 #define ASSIGN_SIGNED(etype) G_STMT_START{\
343 CHECK_WIDENING_CONVERSION(0); \
344 *(etype *) ea = (etype) i64; \
346 /* You can assign an unsigned value to a signed array if the array's */ \
347 /* element size is larger than the value size. */ \
352 case MONO_TYPE_CHAR: \
353 CHECK_WIDENING_CONVERSION(1); \
354 *(etype *) ea = (etype) u64; \
356 /* You can't assign a floating point number to an integer array. */ \
359 NO_WIDENING_CONVERSION; \
363 #define ASSIGN_REAL(etype) G_STMT_START{\
367 CHECK_WIDENING_CONVERSION(0); \
368 *(etype *) ea = (etype) r64; \
370 /* All integer values fit into a floating point array, so we don't */ \
371 /* need to CHECK_WIDENING_CONVERSION here. */ \
376 *(etype *) ea = (etype) i64; \
382 case MONO_TYPE_CHAR: \
383 *(etype *) ea = (etype) u64; \
390 u64
= *(guint8
*) va
;
393 u64
= *(guint16
*) va
;
396 u64
= *(guint32
*) va
;
399 u64
= *(guint64
*) va
;
405 i64
= *(gint16
*) va
;
408 i64
= *(gint32
*) va
;
411 i64
= *(gint64
*) va
;
414 r64
= *(gfloat
*) va
;
417 r64
= *(gdouble
*) va
;
420 u64
= *(guint16
*) va
;
422 case MONO_TYPE_BOOLEAN
:
423 /* Boolean is only compatible with itself. */
436 NO_WIDENING_CONVERSION
;
443 /* If we can't do a direct copy, let's try a widening conversion. */
446 ASSIGN_UNSIGNED (guint16
);
448 ASSIGN_UNSIGNED (guint8
);
450 ASSIGN_UNSIGNED (guint16
);
452 ASSIGN_UNSIGNED (guint32
);
454 ASSIGN_UNSIGNED (guint64
);
456 ASSIGN_SIGNED (gint8
);
458 ASSIGN_SIGNED (gint16
);
460 ASSIGN_SIGNED (gint32
);
462 ASSIGN_SIGNED (gint64
);
464 ASSIGN_REAL (gfloat
);
466 ASSIGN_REAL (gdouble
);
470 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
474 #undef NO_WIDENING_CONVERSION
475 #undef CHECK_WIDENING_CONVERSION
476 #undef ASSIGN_UNSIGNED
482 ves_icall_System_Array_SetValue (MonoArray
*this, MonoObject
*value
,
490 MONO_CHECK_ARG_NULL (idxs
);
492 ic
= idxs
->obj
.vtable
->klass
;
493 ac
= this->obj
.vtable
->klass
;
495 g_assert (ic
->rank
== 1);
496 if (idxs
->bounds
!= NULL
|| idxs
->max_length
!= ac
->rank
)
497 mono_raise_exception (mono_get_exception_argument (NULL
, NULL
));
499 ind
= (gint32
*)idxs
->vector
;
501 if (this->bounds
== NULL
) {
502 if (*ind
< 0 || *ind
>= this->max_length
)
503 mono_raise_exception (mono_get_exception_index_out_of_range ());
505 ves_icall_System_Array_SetValueImpl (this, value
, *ind
);
509 for (i
= 0; i
< ac
->rank
; i
++)
510 if ((ind
[i
] < this->bounds
[i
].lower_bound
) ||
511 (ind
[i
] >= (mono_array_lower_bound_t
)this->bounds
[i
].length
+ this->bounds
[i
].lower_bound
))
512 mono_raise_exception (mono_get_exception_index_out_of_range ());
514 pos
= ind
[0] - this->bounds
[0].lower_bound
;
515 for (i
= 1; i
< ac
->rank
; i
++)
516 pos
= pos
* this->bounds
[i
].length
+ ind
[i
] -
517 this->bounds
[i
].lower_bound
;
519 ves_icall_System_Array_SetValueImpl (this, value
, pos
);
523 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType
*type
, MonoArray
*lengths
, MonoArray
*bounds
)
525 MonoClass
*aklass
, *klass
;
528 gboolean bounded
= FALSE
;
532 MONO_CHECK_ARG_NULL (type
);
533 MONO_CHECK_ARG_NULL (lengths
);
535 MONO_CHECK_ARG (lengths
, mono_array_length (lengths
) > 0);
537 MONO_CHECK_ARG (bounds
, mono_array_length (lengths
) == mono_array_length (bounds
));
539 for (i
= 0; i
< mono_array_length (lengths
); i
++)
540 if (mono_array_get (lengths
, gint32
, i
) < 0)
541 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL
));
543 klass
= mono_class_from_mono_type (type
->type
);
544 mono_class_init_or_throw (klass
);
546 if (bounds
&& (mono_array_length (bounds
) == 1) && (mono_array_get (bounds
, gint32
, 0) != 0))
547 /* vectors are not the same as one dimensional arrays with no-zero bounds */
552 aklass
= mono_bounded_array_class_get (klass
, mono_array_length (lengths
), bounded
);
554 sizes
= alloca (aklass
->rank
* sizeof(intptr_t) * 2);
555 for (i
= 0; i
< aklass
->rank
; ++i
) {
556 sizes
[i
] = mono_array_get (lengths
, guint32
, i
);
558 sizes
[i
+ aklass
->rank
] = mono_array_get (bounds
, guint32
, i
);
560 sizes
[i
+ aklass
->rank
] = 0;
563 array
= mono_array_new_full (mono_object_domain (type
), aklass
, sizes
, (intptr_t*)sizes
+ aklass
->rank
);
569 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType
*type
, MonoArray
*lengths
, MonoArray
*bounds
)
571 MonoClass
*aklass
, *klass
;
574 gboolean bounded
= FALSE
;
578 MONO_CHECK_ARG_NULL (type
);
579 MONO_CHECK_ARG_NULL (lengths
);
581 MONO_CHECK_ARG (lengths
, mono_array_length (lengths
) > 0);
583 MONO_CHECK_ARG (bounds
, mono_array_length (lengths
) == mono_array_length (bounds
));
585 for (i
= 0; i
< mono_array_length (lengths
); i
++)
586 if ((mono_array_get (lengths
, gint64
, i
) < 0) ||
587 (mono_array_get (lengths
, gint64
, i
) > MONO_ARRAY_MAX_INDEX
))
588 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL
));
590 klass
= mono_class_from_mono_type (type
->type
);
591 mono_class_init_or_throw (klass
);
593 if (bounds
&& (mono_array_length (bounds
) == 1) && (mono_array_get (bounds
, gint64
, 0) != 0))
594 /* vectors are not the same as one dimensional arrays with no-zero bounds */
599 aklass
= mono_bounded_array_class_get (klass
, mono_array_length (lengths
), bounded
);
601 sizes
= alloca (aklass
->rank
* sizeof(intptr_t) * 2);
602 for (i
= 0; i
< aklass
->rank
; ++i
) {
603 sizes
[i
] = mono_array_get (lengths
, guint64
, i
);
605 sizes
[i
+ aklass
->rank
] = (mono_array_size_t
) mono_array_get (bounds
, guint64
, i
);
607 sizes
[i
+ aklass
->rank
] = 0;
610 array
= mono_array_new_full (mono_object_domain (type
), aklass
, sizes
, (intptr_t*)sizes
+ aklass
->rank
);
616 ves_icall_System_Array_GetRank (MonoObject
*this)
620 return this->vtable
->klass
->rank
;
624 ves_icall_System_Array_GetLength (MonoArray
*this, gint32 dimension
)
626 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
631 if ((dimension
< 0) || (dimension
>= rank
))
632 mono_raise_exception (mono_get_exception_index_out_of_range ());
634 if (this->bounds
== NULL
)
635 length
= this->max_length
;
637 length
= this->bounds
[dimension
].length
;
639 #ifdef MONO_BIG_ARRAYS
640 if (length
> G_MAXINT32
)
641 mono_raise_exception (mono_get_exception_overflow ());
647 ves_icall_System_Array_GetLongLength (MonoArray
*this, gint32 dimension
)
649 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
653 if ((dimension
< 0) || (dimension
>= rank
))
654 mono_raise_exception (mono_get_exception_index_out_of_range ());
656 if (this->bounds
== NULL
)
657 return this->max_length
;
659 return this->bounds
[dimension
].length
;
663 ves_icall_System_Array_GetLowerBound (MonoArray
*this, gint32 dimension
)
665 gint32 rank
= ((MonoObject
*)this)->vtable
->klass
->rank
;
669 if ((dimension
< 0) || (dimension
>= rank
))
670 mono_raise_exception (mono_get_exception_index_out_of_range ());
672 if (this->bounds
== NULL
)
675 return this->bounds
[dimension
].lower_bound
;
679 ves_icall_System_Array_ClearInternal (MonoArray
*arr
, int idx
, int length
)
681 int sz
= mono_array_element_size (mono_object_class (arr
));
682 memset (mono_array_addr_with_size (arr
, sz
, idx
), 0, length
* sz
);
686 ves_icall_System_Array_FastCopy (MonoArray
*source
, int source_idx
, MonoArray
* dest
, int dest_idx
, int length
)
691 MonoClass
*src_class
;
692 MonoClass
*dest_class
;
697 if (source
->obj
.vtable
->klass
->rank
!= dest
->obj
.vtable
->klass
->rank
)
700 if (source
->bounds
|| dest
->bounds
)
703 /* there's no integer overflow since mono_array_length returns an unsigned integer */
704 if ((dest_idx
+ length
> mono_array_length (dest
)) ||
705 (source_idx
+ length
> mono_array_length (source
)))
708 src_class
= source
->obj
.vtable
->klass
->element_class
;
709 dest_class
= dest
->obj
.vtable
->klass
->element_class
;
712 * Handle common cases.
715 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
716 if (src_class
== mono_defaults
.object_class
&& dest_class
->valuetype
) {
717 int has_refs
= dest_class
->has_references
;
718 for (i
= source_idx
; i
< source_idx
+ length
; ++i
) {
719 MonoObject
*elem
= mono_array_get (source
, MonoObject
*, i
);
720 if (elem
&& !mono_object_isinst (elem
, dest_class
))
724 element_size
= mono_array_element_size (dest
->obj
.vtable
->klass
);
725 memset (mono_array_addr_with_size (dest
, element_size
, dest_idx
), 0, element_size
* length
);
726 for (i
= 0; i
< length
; ++i
) {
727 MonoObject
*elem
= mono_array_get (source
, MonoObject
*, source_idx
+ i
);
728 void *addr
= mono_array_addr_with_size (dest
, element_size
, dest_idx
+ i
);
732 mono_value_copy (addr
, (char *)elem
+ sizeof (MonoObject
), dest_class
);
734 memcpy (addr
, (char *)elem
+ sizeof (MonoObject
), element_size
);
739 /* Check if we're copying a char[] <==> (u)short[] */
740 if (src_class
!= dest_class
) {
741 if (dest_class
->valuetype
|| dest_class
->enumtype
|| src_class
->valuetype
|| src_class
->enumtype
)
744 if (mono_class_is_subclass_of (src_class
, dest_class
, FALSE
))
746 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
747 else if (mono_class_is_subclass_of (dest_class
, src_class
, FALSE
))
748 for (i
= source_idx
; i
< source_idx
+ length
; ++i
) {
749 MonoObject
*elem
= mono_array_get (source
, MonoObject
*, i
);
750 if (elem
&& !mono_object_isinst (elem
, dest_class
))
757 if (dest_class
->valuetype
) {
758 element_size
= mono_array_element_size (source
->obj
.vtable
->klass
);
759 source_addr
= mono_array_addr_with_size (source
, element_size
, source_idx
);
760 if (dest_class
->has_references
) {
761 mono_value_copy_array (dest
, dest_idx
, source_addr
, length
);
763 dest_addr
= mono_array_addr_with_size (dest
, element_size
, dest_idx
);
764 memmove (dest_addr
, source_addr
, element_size
* length
);
767 mono_array_memcpy_refs (dest
, dest_idx
, source
, source_idx
, length
);
774 ves_icall_System_Array_GetGenericValueImpl (MonoObject
*this, guint32 pos
, gpointer value
)
783 ao
= (MonoArray
*)this;
784 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
786 esize
= mono_array_element_size (ac
);
787 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
789 memcpy (value
, ea
, esize
);
793 ves_icall_System_Array_SetGenericValueImpl (MonoObject
*this, guint32 pos
, gpointer value
)
802 ao
= (MonoArray
*)this;
803 ac
= (MonoClass
*)ao
->obj
.vtable
->klass
;
804 ec
= ac
->element_class
;
806 esize
= mono_array_element_size (ac
);
807 ea
= (gpointer
*)((char*)ao
->vector
+ (pos
* esize
));
809 if (MONO_TYPE_IS_REFERENCE (&ec
->byval_arg
)) {
810 g_assert (esize
== sizeof (gpointer
));
811 mono_gc_wbarrier_generic_store (ea
, *(gpointer
*)value
);
813 g_assert (ec
->inited
);
814 g_assert (esize
== mono_class_value_size (ec
, NULL
));
815 if (ec
->has_references
)
816 mono_gc_wbarrier_value_copy (ea
, value
, 1, ec
);
818 memcpy (ea
, value
, esize
);
823 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray
*array
, MonoClassField
*field_handle
)
825 MonoClass
*klass
= array
->obj
.vtable
->klass
;
826 guint32 size
= mono_array_element_size (klass
);
827 MonoType
*type
= mono_type_get_underlying_type (&klass
->element_class
->byval_arg
);
829 const char *field_data
;
831 if (MONO_TYPE_IS_REFERENCE (type
) ||
832 (type
->type
== MONO_TYPE_VALUETYPE
&&
833 (!mono_type_get_class (type
) ||
834 mono_type_get_class (type
)->has_references
))) {
835 MonoException
*exc
= mono_get_exception_argument("array",
836 "Cannot initialize array containing references");
837 mono_raise_exception (exc
);
840 if (!(field_handle
->type
->attrs
& FIELD_ATTRIBUTE_HAS_FIELD_RVA
)) {
841 MonoException
*exc
= mono_get_exception_argument("field_handle",
842 "Field doesn't have an RVA");
843 mono_raise_exception (exc
);
846 size
*= array
->max_length
;
847 field_data
= mono_field_get_data (field_handle
);
849 if (size
> mono_type_size (field_handle
->type
, &align
)) {
850 MonoException
*exc
= mono_get_exception_argument("field_handle",
851 "Field not large enough to fill array");
852 mono_raise_exception (exc
);
855 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
857 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
858 guint ## n *src = (guint ## n *) field_data; \
859 guint ## n *end = (guint ## n *)((char*)src + size); \
861 for (; src < end; data++, src++) { \
862 *data = read ## n (src); \
866 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
868 switch (type
->type
) {
885 memcpy (mono_array_addr (array
, char, 0), field_data
, size
);
889 memcpy (mono_array_addr (array
, char, 0), field_data
, size
);
891 if (klass
->element_class
->byval_arg
.type
== MONO_TYPE_R8
) {
894 double *data
= (double*)mono_array_addr (array
, double, 0);
896 for (i
= 0; i
< size
; i
++, data
++) {
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
910 return offsetof (MonoString
, chars
);
914 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject
*obj
)
918 if ((obj
== NULL
) || (! (obj
->vtable
->klass
->valuetype
)))
921 return mono_object_clone (obj
);
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType
*handle
)
930 MONO_CHECK_ARG_NULL (handle
);
932 klass
= mono_class_from_mono_type (handle
);
933 MONO_CHECK_ARG (handle
, klass
);
935 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, TRUE
);
937 /* This will call the type constructor */
938 mono_runtime_class_init (vtable
);
942 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage
*image
)
946 mono_image_check_for_module_cctor (image
);
947 if (image
->has_module_cctor
) {
948 MonoClass
*module_klass
= mono_class_get (image
, MONO_TOKEN_TYPE_DEF
| 1);
949 /*It's fine to raise the exception here*/
950 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass
, TRUE
));
955 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
960 /* later make this configurable and per-arch */
961 int min_size
= 4096 * 4 * sizeof (void*);
962 mono_thread_get_stack_bounds (&stack_addr
, &stack_size
);
963 /* if we have no info we are optimistic and assume there is enough room */
966 current
= (guint8
*)&stack_addr
;
967 if (current
> stack_addr
) {
968 if ((current
- stack_addr
) < min_size
)
971 if (current
- (stack_addr
- stack_size
) < min_size
)
978 ves_icall_System_Object_MemberwiseClone (MonoObject
*this)
982 return mono_object_clone (this);
986 ves_icall_System_ValueType_InternalGetHashCode (MonoObject
*this, MonoArray
**fields
)
989 MonoObject
**values
= NULL
;
993 MonoClassField
* field
;
998 klass
= mono_object_class (this);
1000 if (mono_class_num_fields (klass
) == 0)
1001 return mono_object_hash (this);
1004 * Compute the starting value of the hashcode for fields of primitive
1005 * types, and return the remaining fields in an array to the managed side.
1006 * This way, we can avoid costly reflection operations in managed code.
1009 while ((field
= mono_class_get_fields (klass
, &iter
))) {
1010 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1012 if (mono_field_is_deleted (field
))
1014 /* FIXME: Add more types */
1015 switch (field
->type
->type
) {
1017 result
^= *(gint32
*)((guint8
*)this + field
->offset
);
1019 case MONO_TYPE_STRING
: {
1021 s
= *(MonoString
**)((guint8
*)this + field
->offset
);
1023 result
^= mono_string_hash (s
);
1028 values
= g_newa (MonoObject
*, mono_class_num_fields (klass
));
1029 o
= mono_field_get_value_object (mono_object_domain (this), field
, this);
1030 values
[count
++] = o
;
1036 mono_gc_wbarrier_generic_store (fields
, (MonoObject
*) mono_array_new (mono_domain_get (), mono_defaults
.object_class
, count
));
1037 for (i
= 0; i
< count
; ++i
)
1038 mono_array_setref (*fields
, i
, values
[i
]);
1046 ves_icall_System_ValueType_Equals (MonoObject
*this, MonoObject
*that
, MonoArray
**fields
)
1049 MonoObject
**values
= NULL
;
1051 MonoClassField
* field
;
1055 MONO_ARCH_SAVE_REGS
;
1057 MONO_CHECK_ARG_NULL (that
);
1059 if (this->vtable
!= that
->vtable
)
1062 klass
= mono_object_class (this);
1064 if (klass
->enumtype
&& mono_class_enum_basetype (klass
) && mono_class_enum_basetype (klass
)->type
== MONO_TYPE_I4
)
1065 return (*(gint32
*)((guint8
*)this + sizeof (MonoObject
)) == *(gint32
*)((guint8
*)that
+ sizeof (MonoObject
)));
1068 * Do the comparison for fields of primitive type and return a result if
1069 * possible. Otherwise, return the remaining fields in an array to the
1070 * managed side. This way, we can avoid costly reflection operations in
1075 while ((field
= mono_class_get_fields (klass
, &iter
))) {
1076 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
1078 if (mono_field_is_deleted (field
))
1080 /* FIXME: Add more types */
1081 switch (field
->type
->type
) {
1084 case MONO_TYPE_BOOLEAN
:
1085 if (*((guint8
*)this + field
->offset
) != *((guint8
*)that
+ field
->offset
))
1090 case MONO_TYPE_CHAR
:
1091 if (*(gint16
*)((guint8
*)this + field
->offset
) != *(gint16
*)((guint8
*)that
+ field
->offset
))
1096 if (*(gint32
*)((guint8
*)this + field
->offset
) != *(gint32
*)((guint8
*)that
+ field
->offset
))
1101 if (*(gint64
*)((guint8
*)this + field
->offset
) != *(gint64
*)((guint8
*)that
+ field
->offset
))
1105 if (*(float*)((guint8
*)this + field
->offset
) != *(float*)((guint8
*)that
+ field
->offset
))
1109 if (*(double*)((guint8
*)this + field
->offset
) != *(double*)((guint8
*)that
+ field
->offset
))
1114 case MONO_TYPE_STRING
: {
1115 MonoString
*s1
, *s2
;
1116 guint32 s1len
, s2len
;
1117 s1
= *(MonoString
**)((guint8
*)this + field
->offset
);
1118 s2
= *(MonoString
**)((guint8
*)that
+ field
->offset
);
1121 if ((s1
== NULL
) || (s2
== NULL
))
1123 s1len
= mono_string_length (s1
);
1124 s2len
= mono_string_length (s2
);
1128 if (memcmp (mono_string_chars (s1
), mono_string_chars (s2
), s1len
* sizeof (gunichar2
)) != 0)
1134 values
= g_newa (MonoObject
*, mono_class_num_fields (klass
) * 2);
1135 o
= mono_field_get_value_object (mono_object_domain (this), field
, this);
1136 values
[count
++] = o
;
1137 o
= mono_field_get_value_object (mono_object_domain (this), field
, that
);
1138 values
[count
++] = o
;
1141 if (klass
->enumtype
)
1142 /* enums only have one non-static field */
1148 mono_gc_wbarrier_generic_store (fields
, (MonoObject
*) mono_array_new (mono_domain_get (), mono_defaults
.object_class
, count
));
1149 for (i
= 0; i
< count
; ++i
)
1150 mono_array_setref (*fields
, i
, values
[i
]);
1157 static MonoReflectionType
*
1158 ves_icall_System_Object_GetType (MonoObject
*obj
)
1160 MONO_ARCH_SAVE_REGS
;
1162 if (obj
->vtable
->klass
!= mono_defaults
.transparent_proxy_class
)
1163 return mono_type_get_object (mono_object_domain (obj
), &obj
->vtable
->klass
->byval_arg
);
1165 return mono_type_get_object (mono_object_domain (obj
), &((MonoTransparentProxy
*)obj
)->remote_class
->proxy_class
->byval_arg
);
1169 mono_type_type_from_obj (MonoReflectionType
*mtype
, MonoObject
*obj
)
1171 MONO_ARCH_SAVE_REGS
;
1173 mtype
->type
= &obj
->vtable
->klass
->byval_arg
;
1174 g_assert (mtype
->type
->type
);
1178 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder
*mb
, MonoObject
*obj
)
1180 MONO_ARCH_SAVE_REGS
;
1182 MONO_CHECK_ARG_NULL (obj
);
1184 return mono_image_create_token (mb
->dynamic_image
, obj
, TRUE
, TRUE
);
1188 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder
*mb
,
1189 MonoReflectionMethod
*method
,
1190 MonoArray
*opt_param_types
)
1192 MONO_ARCH_SAVE_REGS
;
1194 MONO_CHECK_ARG_NULL (method
);
1196 return mono_image_create_method_token (
1197 mb
->dynamic_image
, (MonoObject
*) method
, opt_param_types
);
1201 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder
*mb
, HANDLE file
)
1203 MONO_ARCH_SAVE_REGS
;
1205 mono_image_create_pefile (mb
, file
);
1209 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder
*mb
)
1211 MONO_ARCH_SAVE_REGS
;
1213 mono_image_build_metadata (mb
);
1217 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder
*mb
, MonoObject
*obj
, guint32 token
)
1219 MONO_ARCH_SAVE_REGS
;
1221 mono_image_register_token (mb
->dynamic_image
, token
, obj
);
1225 get_caller (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1227 MonoMethod
**dest
= data
;
1229 /* skip unmanaged frames */
1245 get_executing (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1247 MonoMethod
**dest
= data
;
1249 /* skip unmanaged frames */
1254 if (!strcmp (m
->klass
->name_space
, "System.Reflection"))
1263 get_caller_no_reflection (MonoMethod
*m
, gint32 no
, gint32 ilo
, gboolean managed
, gpointer data
)
1265 MonoMethod
**dest
= data
;
1267 /* skip unmanaged frames */
1271 if (m
->wrapper_type
!= MONO_WRAPPER_NONE
)
1274 if (m
->klass
->image
== mono_defaults
.corlib
&& !strcmp (m
->klass
->name_space
, "System.Reflection"))
1288 static MonoReflectionType
*
1289 type_from_name (const char *str
, MonoBoolean ignoreCase
)
1291 MonoType
*type
= NULL
;
1292 MonoAssembly
*assembly
= NULL
;
1293 MonoTypeNameParse info
;
1294 char *temp_str
= g_strdup (str
);
1295 gboolean type_resolve
= FALSE
;
1297 MONO_ARCH_SAVE_REGS
;
1299 /* mono_reflection_parse_type() mangles the string */
1300 if (!mono_reflection_parse_type (temp_str
, &info
)) {
1301 mono_reflection_free_type_info (&info
);
1306 if (info
.assembly
.name
) {
1307 assembly
= mono_assembly_load (&info
.assembly
, NULL
, NULL
);
1309 MonoMethod
*m
= mono_method_get_last_managed ();
1310 MonoMethod
*dest
= m
;
1312 mono_stack_walk_no_il (get_caller_no_reflection
, &dest
);
1317 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1318 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1319 * to crash. This only seems to happen in some strange remoting
1320 * scenarios and I was unable to figure out what's happening there.
1321 * Dec 10, 2005 - Martin.
1325 assembly
= dest
->klass
->image
->assembly
;
1326 type_resolve
= TRUE
;
1328 g_warning (G_STRLOC
);
1333 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1334 type
= mono_reflection_get_type (assembly
->image
, &info
, ignoreCase
, &type_resolve
);
1337 if (!info
.assembly
.name
&& !type
) /* try mscorlib */
1338 type
= mono_reflection_get_type (NULL
, &info
, ignoreCase
, &type_resolve
);
1340 if (assembly
&& !type
&& type_resolve
) {
1341 type_resolve
= FALSE
; /* This will invoke TypeResolve if not done in the first 'if' */
1342 type
= mono_reflection_get_type (assembly
->image
, &info
, ignoreCase
, &type_resolve
);
1345 mono_reflection_free_type_info (&info
);
1351 return mono_type_get_object (mono_domain_get (), type
);
1355 MonoReflectionType
*
1356 mono_type_get (const char *str
)
1358 char *copy
= g_strdup (str
);
1359 MonoReflectionType
*type
= type_from_name (copy
, FALSE
);
1366 static MonoReflectionType
*
1367 ves_icall_type_from_name (MonoString
*name
,
1368 MonoBoolean throwOnError
,
1369 MonoBoolean ignoreCase
)
1371 char *str
= mono_string_to_utf8 (name
);
1372 MonoReflectionType
*type
;
1374 type
= type_from_name (str
, ignoreCase
);
1377 MonoException
*e
= NULL
;
1380 e
= mono_get_exception_type_load (name
, NULL
);
1382 mono_loader_clear_error ();
1384 mono_raise_exception (e
);
1391 static MonoReflectionType
*
1392 ves_icall_type_from_handle (MonoType
*handle
)
1394 MonoDomain
*domain
= mono_domain_get ();
1396 MONO_ARCH_SAVE_REGS
;
1398 return mono_type_get_object (domain
, handle
);
1402 ves_icall_System_Type_EqualsInternal (MonoReflectionType
*type
, MonoReflectionType
*c
)
1404 MONO_ARCH_SAVE_REGS
;
1406 if (c
&& type
->type
&& c
->type
)
1407 return mono_metadata_type_equal (type
->type
, c
->type
);
1409 return (type
== c
) ? TRUE
: FALSE
;
1412 /* System.TypeCode */
1431 TYPECODE_STRING
= 18
1435 ves_icall_type_GetTypeCodeInternal (MonoReflectionType
*type
)
1437 int t
= type
->type
->type
;
1439 MONO_ARCH_SAVE_REGS
;
1441 if (type
->type
->byref
)
1442 return TYPECODE_OBJECT
;
1446 case MONO_TYPE_VOID
:
1447 return TYPECODE_OBJECT
;
1448 case MONO_TYPE_BOOLEAN
:
1449 return TYPECODE_BOOLEAN
;
1451 return TYPECODE_BYTE
;
1453 return TYPECODE_SBYTE
;
1455 return TYPECODE_UINT16
;
1457 return TYPECODE_INT16
;
1458 case MONO_TYPE_CHAR
:
1459 return TYPECODE_CHAR
;
1463 return TYPECODE_OBJECT
;
1465 return TYPECODE_UINT32
;
1467 return TYPECODE_INT32
;
1469 return TYPECODE_UINT64
;
1471 return TYPECODE_INT64
;
1473 return TYPECODE_SINGLE
;
1475 return TYPECODE_DOUBLE
;
1476 case MONO_TYPE_VALUETYPE
:
1477 if (type
->type
->data
.klass
->enumtype
) {
1478 t
= mono_class_enum_basetype (type
->type
->data
.klass
)->type
;
1481 MonoClass
*k
= type
->type
->data
.klass
;
1482 if (strcmp (k
->name_space
, "System") == 0) {
1483 if (strcmp (k
->name
, "Decimal") == 0)
1484 return TYPECODE_DECIMAL
;
1485 else if (strcmp (k
->name
, "DateTime") == 0)
1486 return TYPECODE_DATETIME
;
1489 return TYPECODE_OBJECT
;
1490 case MONO_TYPE_STRING
:
1491 return TYPECODE_STRING
;
1492 case MONO_TYPE_SZARRAY
:
1493 case MONO_TYPE_ARRAY
:
1494 case MONO_TYPE_OBJECT
:
1496 case MONO_TYPE_MVAR
:
1497 case MONO_TYPE_TYPEDBYREF
:
1498 return TYPECODE_OBJECT
;
1499 case MONO_TYPE_CLASS
:
1501 MonoClass
*k
= type
->type
->data
.klass
;
1502 if (strcmp (k
->name_space
, "System") == 0) {
1503 if (strcmp (k
->name
, "DBNull") == 0)
1504 return TYPECODE_DBNULL
;
1507 return TYPECODE_OBJECT
;
1508 case MONO_TYPE_GENERICINST
:
1509 return TYPECODE_OBJECT
;
1511 g_error ("type 0x%02x not handled in GetTypeCode()", t
);
1517 ves_icall_type_is_subtype_of (MonoReflectionType
*type
, MonoReflectionType
*c
, MonoBoolean check_interfaces
)
1523 MONO_ARCH_SAVE_REGS
;
1525 g_assert (type
!= NULL
);
1527 domain
= ((MonoObject
*)type
)->vtable
->domain
;
1529 if (!c
) /* FIXME: dont know what do do here */
1532 klass
= mono_class_from_mono_type (type
->type
);
1533 klassc
= mono_class_from_mono_type (c
->type
);
1535 /* Interface check requires a more complex setup so we
1536 * only do for them. Otherwise we simply avoid mono_class_init.
1538 if (check_interfaces
) {
1539 mono_class_init_or_throw (klass
);
1540 mono_class_init_or_throw (klassc
);
1541 } else if (!klass
->supertypes
|| !klassc
->supertypes
) {
1542 mono_loader_lock ();
1543 mono_class_setup_supertypes (klass
);
1544 mono_class_setup_supertypes (klassc
);
1545 mono_loader_unlock ();
1548 if (type
->type
->byref
)
1549 return klassc
== mono_defaults
.object_class
;
1551 return mono_class_is_subclass_of (klass
, klassc
, check_interfaces
);
1555 mono_type_is_primitive (MonoType
*type
)
1557 return (type
->type
>= MONO_TYPE_BOOLEAN
&& type
->type
<= MONO_TYPE_R8
) ||
1558 type
-> type
== MONO_TYPE_I
|| type
->type
== MONO_TYPE_U
;
1562 mono_type_get_underlying_type_ignore_byref (MonoType
*type
)
1564 if (type
->type
== MONO_TYPE_VALUETYPE
&& type
->data
.klass
->enumtype
)
1565 return mono_class_enum_basetype (type
->data
.klass
);
1566 if (type
->type
== MONO_TYPE_GENERICINST
&& type
->data
.generic_class
->container_class
->enumtype
)
1567 return mono_class_enum_basetype (type
->data
.generic_class
->container_class
);
1572 ves_icall_type_is_assignable_from (MonoReflectionType
*type
, MonoReflectionType
*c
)
1578 MONO_ARCH_SAVE_REGS
;
1580 g_assert (type
!= NULL
);
1582 domain
= ((MonoObject
*)type
)->vtable
->domain
;
1584 klass
= mono_class_from_mono_type (type
->type
);
1585 klassc
= mono_class_from_mono_type (c
->type
);
1587 mono_class_init_or_throw (klass
);
1588 mono_class_init_or_throw (klassc
);
1590 if (type
->type
->byref
^ c
->type
->byref
)
1593 if (type
->type
->byref
) {
1594 MonoType
*t
= mono_type_get_underlying_type_ignore_byref (type
->type
);
1595 MonoType
*ot
= mono_type_get_underlying_type_ignore_byref (c
->type
);
1597 klass
= mono_class_from_mono_type (t
);
1598 klassc
= mono_class_from_mono_type (ot
);
1600 if (mono_type_is_primitive (t
)) {
1601 return mono_type_is_primitive (ot
) && klass
->instance_size
== klassc
->instance_size
;
1602 } else if (t
->type
== MONO_TYPE_VAR
|| t
->type
== MONO_TYPE_MVAR
) {
1603 return t
->type
== ot
->type
&& t
->data
.generic_param
->num
== ot
->data
.generic_param
->num
;
1604 } else if (t
->type
== MONO_TYPE_PTR
|| t
->type
== MONO_TYPE_FNPTR
) {
1605 return t
->type
== ot
->type
;
1607 if (ot
->type
== MONO_TYPE_VAR
|| ot
->type
== MONO_TYPE_MVAR
)
1610 if (klass
->valuetype
)
1611 return klass
== klassc
;
1612 return klass
->valuetype
== klassc
->valuetype
;
1615 return mono_class_is_assignable_from (klass
, klassc
);
1619 ves_icall_type_IsInstanceOfType (MonoReflectionType
*type
, MonoObject
*obj
)
1621 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1622 mono_class_init_or_throw (klass
);
1623 return mono_object_isinst (obj
, klass
) != NULL
;
1627 ves_icall_get_attributes (MonoReflectionType
*type
)
1629 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
1630 return klass
->flags
;
1633 static MonoReflectionMarshal
*
1634 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField
*field
)
1636 MonoClass
*klass
= field
->field
->parent
;
1637 MonoMarshalType
*info
;
1640 if (klass
->generic_container
||
1641 (klass
->generic_class
&& klass
->generic_class
->context
.class_inst
->is_open
))
1644 info
= mono_marshal_load_type_info (klass
);
1646 for (i
= 0; i
< info
->num_fields
; ++i
) {
1647 if (info
->fields
[i
].field
== field
->field
) {
1648 if (!info
->fields
[i
].mspec
)
1651 return mono_reflection_marshal_from_marshal_spec (field
->object
.vtable
->domain
, klass
, info
->fields
[i
].mspec
);
1658 static MonoReflectionField
*
1659 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField
*handle
, MonoType
*type
)
1661 gboolean found
= FALSE
;
1668 klass
= handle
->parent
;
1670 klass
= mono_class_from_mono_type (type
);
1672 /* Check that the field belongs to the class */
1673 for (k
= klass
; k
; k
= k
->parent
) {
1674 if (k
== handle
->parent
) {
1681 /* The managed code will throw the exception */
1685 return mono_field_get_object (mono_domain_get (), klass
, handle
);
1689 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField
*field
, MonoBoolean optional
)
1691 MonoType
*type
= field
->field
->type
;
1693 return type_array_from_modifiers (field
->field
->parent
->image
, type
, optional
);
1697 ves_icall_get_method_info (MonoMethod
*method
, MonoMethodInfo
*info
)
1699 MonoDomain
*domain
= mono_domain_get ();
1700 MonoMethodSignature
* sig
;
1701 MONO_ARCH_SAVE_REGS
;
1703 sig
= mono_method_signature (method
);
1705 g_assert (mono_loader_get_last_error ());
1706 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1709 MONO_STRUCT_SETREF (info
, parent
, mono_type_get_object (domain
, &method
->klass
->byval_arg
));
1710 MONO_STRUCT_SETREF (info
, ret
, mono_type_get_object (domain
, sig
->ret
));
1711 info
->attrs
= method
->flags
;
1712 info
->implattrs
= method
->iflags
;
1713 if (sig
->call_convention
== MONO_CALL_DEFAULT
)
1714 info
->callconv
= sig
->sentinelpos
>= 0 ? 2 : 1;
1716 if (sig
->call_convention
== MONO_CALL_VARARG
|| sig
->sentinelpos
>= 0)
1721 info
->callconv
|= (sig
->hasthis
<< 5) | (sig
->explicit_this
<< 6);
1725 ves_icall_get_parameter_info (MonoMethod
*method
, MonoReflectionMethod
*member
)
1727 MonoDomain
*domain
= mono_domain_get ();
1729 return mono_param_get_objects_internal (domain
, method
, member
->reftype
? mono_class_from_mono_type (member
->reftype
->type
) : NULL
);
1732 static MonoReflectionMarshal
*
1733 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod
*method
)
1735 MonoDomain
*domain
= mono_domain_get ();
1736 MonoReflectionMarshal
* res
= NULL
;
1737 MonoMarshalSpec
**mspecs
;
1740 mspecs
= g_new (MonoMarshalSpec
*, mono_method_signature (method
)->param_count
+ 1);
1741 mono_method_get_marshal_info (method
, mspecs
);
1744 res
= mono_reflection_marshal_from_marshal_spec (domain
, method
->klass
, mspecs
[0]);
1746 for (i
= mono_method_signature (method
)->param_count
; i
>= 0; i
--)
1748 mono_metadata_free_marshal_spec (mspecs
[i
]);
1755 ves_icall_MonoField_GetFieldOffset (MonoReflectionField
*field
)
1757 return field
->field
->offset
- sizeof (MonoObject
);
1760 static MonoReflectionType
*
1761 ves_icall_MonoField_GetParentType (MonoReflectionField
*field
, MonoBoolean declaring
)
1764 MONO_ARCH_SAVE_REGS
;
1766 parent
= declaring
? field
->field
->parent
: field
->klass
;
1768 return mono_type_get_object (mono_object_domain (field
), &parent
->byval_arg
);
1772 ves_icall_MonoField_GetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
)
1774 MonoClass
*fklass
= field
->klass
;
1775 MonoClassField
*cf
= field
->field
;
1776 MonoDomain
*domain
= mono_object_domain (field
);
1778 if (fklass
->image
->assembly
->ref_only
)
1779 mono_raise_exception (mono_get_exception_invalid_operation (
1780 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1782 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
1783 mono_security_core_clr_ensure_reflection_access_field (cf
);
1785 return mono_field_get_value_object (domain
, cf
, obj
);
1789 ves_icall_MonoField_SetValueInternal (MonoReflectionField
*field
, MonoObject
*obj
, MonoObject
*value
)
1791 MonoClassField
*cf
= field
->field
;
1794 MONO_ARCH_SAVE_REGS
;
1796 if (field
->klass
->image
->assembly
->ref_only
)
1797 mono_raise_exception (mono_get_exception_invalid_operation (
1798 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1800 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
1801 mono_security_core_clr_ensure_reflection_access_field (cf
);
1803 v
= (gchar
*) value
;
1804 if (!cf
->type
->byref
) {
1805 switch (cf
->type
->type
) {
1808 case MONO_TYPE_BOOLEAN
:
1811 case MONO_TYPE_CHAR
:
1820 case MONO_TYPE_VALUETYPE
:
1822 v
+= sizeof (MonoObject
);
1824 case MONO_TYPE_STRING
:
1825 case MONO_TYPE_OBJECT
:
1826 case MONO_TYPE_CLASS
:
1827 case MONO_TYPE_ARRAY
:
1828 case MONO_TYPE_SZARRAY
:
1831 case MONO_TYPE_GENERICINST
: {
1832 MonoGenericClass
*gclass
= cf
->type
->data
.generic_class
;
1833 g_assert (!gclass
->context
.class_inst
->is_open
);
1835 if (mono_class_is_nullable (mono_class_from_mono_type (cf
->type
))) {
1836 MonoClass
*nklass
= mono_class_from_mono_type (cf
->type
);
1837 MonoObject
*nullable
;
1840 * Convert the boxed vtype into a Nullable structure.
1841 * This is complicated by the fact that Nullables have
1842 * a variable structure.
1844 nullable
= mono_object_new (mono_domain_get (), nklass
);
1846 mono_nullable_init (mono_object_unbox (nullable
), value
, nklass
);
1848 v
= mono_object_unbox (nullable
);
1851 if (gclass
->container_class
->valuetype
&& (v
!= NULL
))
1852 v
+= sizeof (MonoObject
);
1856 g_error ("type 0x%x not handled in "
1857 "ves_icall_FieldInfo_SetValueInternal", cf
->type
->type
);
1862 if (cf
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
1863 MonoVTable
*vtable
= mono_class_vtable_full (mono_object_domain (field
), cf
->parent
, TRUE
);
1864 if (!vtable
->initialized
)
1865 mono_runtime_class_init (vtable
);
1866 mono_field_static_set_value (vtable
, cf
, v
);
1868 mono_field_set_value (obj
, cf
, v
);
1873 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField
*this)
1875 MonoObject
*o
= NULL
;
1876 MonoClassField
*field
= this->field
;
1878 MonoDomain
*domain
= mono_object_domain (this);
1880 MonoTypeEnum def_type
;
1881 const char *def_value
;
1883 MONO_ARCH_SAVE_REGS
;
1885 mono_class_init (field
->parent
);
1887 if (!(field
->type
->attrs
& FIELD_ATTRIBUTE_HAS_DEFAULT
))
1888 mono_raise_exception (mono_get_exception_invalid_operation (NULL
));
1890 if (field
->parent
->image
->dynamic
) {
1892 g_assert_not_reached ();
1895 def_value
= mono_class_get_field_default_value (field
, &def_type
);
1897 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1901 case MONO_TYPE_BOOLEAN
:
1904 case MONO_TYPE_CHAR
:
1912 case MONO_TYPE_R8
: {
1915 /* boxed value type */
1916 t
= g_new0 (MonoType
, 1);
1918 klass
= mono_class_from_mono_type (t
);
1920 o
= mono_object_new (domain
, klass
);
1921 v
= ((gchar
*) o
) + sizeof (MonoObject
);
1922 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, v
);
1925 case MONO_TYPE_STRING
:
1926 case MONO_TYPE_CLASS
:
1927 mono_get_constant_value_from_blob (domain
, def_type
, def_value
, &o
);
1930 g_assert_not_reached ();
1936 static MonoReflectionType
*
1937 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod
*rmethod
)
1939 MonoMethod
*method
= rmethod
->method
.method
;
1941 return mono_type_get_object (mono_object_domain (rmethod
), &method
->klass
->byval_arg
);
1944 /* From MonoProperty.cs */
1946 PInfo_Attributes
= 1,
1947 PInfo_GetMethod
= 1 << 1,
1948 PInfo_SetMethod
= 1 << 2,
1949 PInfo_ReflectedType
= 1 << 3,
1950 PInfo_DeclaringType
= 1 << 4,
1955 ves_icall_get_property_info (MonoReflectionProperty
*property
, MonoPropertyInfo
*info
, PInfo req_info
)
1957 MonoDomain
*domain
= mono_object_domain (property
);
1959 MONO_ARCH_SAVE_REGS
;
1961 if ((req_info
& PInfo_ReflectedType
) != 0)
1962 MONO_STRUCT_SETREF (info
, parent
, mono_type_get_object (domain
, &property
->klass
->byval_arg
));
1963 else if ((req_info
& PInfo_DeclaringType
) != 0)
1964 MONO_STRUCT_SETREF (info
, parent
, mono_type_get_object (domain
, &property
->property
->parent
->byval_arg
));
1966 if ((req_info
& PInfo_Name
) != 0)
1967 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, property
->property
->name
));
1969 if ((req_info
& PInfo_Attributes
) != 0)
1970 info
->attrs
= property
->property
->attrs
;
1972 if ((req_info
& PInfo_GetMethod
) != 0)
1973 MONO_STRUCT_SETREF (info
, get
, property
->property
->get
?
1974 mono_method_get_object (domain
, property
->property
->get
, property
->klass
): NULL
);
1976 if ((req_info
& PInfo_SetMethod
) != 0)
1977 MONO_STRUCT_SETREF (info
, set
, property
->property
->set
?
1978 mono_method_get_object (domain
, property
->property
->set
, property
->klass
): NULL
);
1980 * There may be other methods defined for properties, though, it seems they are not exposed
1981 * in the reflection API
1986 ves_icall_get_event_info (MonoReflectionMonoEvent
*event
, MonoEventInfo
*info
)
1988 MonoDomain
*domain
= mono_object_domain (event
);
1990 MONO_ARCH_SAVE_REGS
;
1992 MONO_STRUCT_SETREF (info
, reflected_type
, mono_type_get_object (domain
, &event
->klass
->byval_arg
));
1993 MONO_STRUCT_SETREF (info
, declaring_type
, mono_type_get_object (domain
, &event
->event
->parent
->byval_arg
));
1995 MONO_STRUCT_SETREF (info
, name
, mono_string_new (domain
, event
->event
->name
));
1996 info
->attrs
= event
->event
->attrs
;
1997 MONO_STRUCT_SETREF (info
, add_method
, event
->event
->add
? mono_method_get_object (domain
, event
->event
->add
, NULL
): NULL
);
1998 MONO_STRUCT_SETREF (info
, remove_method
, event
->event
->remove
? mono_method_get_object (domain
, event
->event
->remove
, NULL
): NULL
);
1999 MONO_STRUCT_SETREF (info
, raise_method
, event
->event
->raise
? mono_method_get_object (domain
, event
->event
->raise
, NULL
): NULL
);
2001 #ifndef MONO_SMALL_CONFIG
2002 if (event
->event
->other
) {
2004 while (event
->event
->other
[n
])
2006 MONO_STRUCT_SETREF (info
, other_methods
, mono_array_new (domain
, mono_defaults
.method_info_class
, n
));
2008 for (i
= 0; i
< n
; i
++)
2009 mono_array_setref (info
->other_methods
, i
, mono_method_get_object (domain
, event
->event
->other
[i
], NULL
));
2015 collect_interfaces (MonoClass
*klass
, GHashTable
*ifaces
, MonoError
*error
)
2020 mono_class_setup_interfaces (klass
, error
);
2021 if (!mono_error_ok (error
))
2024 for (i
= 0; i
< klass
->interface_count
; i
++) {
2025 ic
= klass
->interfaces
[i
];
2026 g_hash_table_insert (ifaces
, ic
, ic
);
2028 collect_interfaces (ic
, ifaces
, error
);
2029 if (!mono_error_ok (error
))
2035 MonoArray
*iface_array
;
2036 MonoGenericContext
*context
;
2040 } FillIfaceArrayData
;
2043 fill_iface_array (gpointer key
, gpointer value
, gpointer user_data
)
2045 FillIfaceArrayData
*data
= user_data
;
2046 MonoClass
*ic
= key
;
2047 MonoType
*ret
= &ic
->byval_arg
, *inflated
= NULL
;
2049 if (!mono_error_ok (data
->error
))
2052 if (data
->context
&& ic
->generic_class
&& ic
->generic_class
->context
.class_inst
->is_open
) {
2053 inflated
= ret
= mono_class_inflate_generic_type_checked (ret
, data
->context
, data
->error
);
2054 if (!mono_error_ok (data
->error
))
2058 mono_array_setref (data
->iface_array
, data
->next_idx
++, mono_type_get_object (data
->domain
, ret
));
2061 mono_metadata_free_type (inflated
);
2065 ves_icall_Type_GetInterfaces (MonoReflectionType
* type
)
2068 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2070 FillIfaceArrayData data
= { 0 };
2073 GHashTable
*iface_hash
= g_hash_table_new (NULL
, NULL
);
2075 if (class->generic_class
&& class->generic_class
->context
.class_inst
->is_open
) {
2076 data
.context
= mono_class_get_context (class);
2077 class = class->generic_class
->container_class
;
2080 for (parent
= class; parent
; parent
= parent
->parent
) {
2081 mono_class_setup_interfaces (parent
, &error
);
2082 if (!mono_error_ok (&error
))
2084 collect_interfaces (parent
, iface_hash
, &error
);
2085 if (!mono_error_ok (&error
))
2089 data
.error
= &error
;
2090 data
.domain
= mono_object_domain (type
);
2092 len
= g_hash_table_size (iface_hash
);
2094 return mono_array_new_cached (data
.domain
, mono_defaults
.monotype_class
, 0);
2096 data
.iface_array
= mono_array_new_cached (data
.domain
, mono_defaults
.monotype_class
, len
);
2097 g_hash_table_foreach (iface_hash
, fill_iface_array
, &data
);
2098 if (!mono_error_ok (&error
))
2101 g_hash_table_destroy (iface_hash
);
2102 return data
.iface_array
;
2105 g_hash_table_destroy (iface_hash
);
2106 mono_error_raise_exception (&error
);
2111 ves_icall_Type_GetInterfaceMapData (MonoReflectionType
*type
, MonoReflectionType
*iface
, MonoArray
**targets
, MonoArray
**methods
)
2113 gboolean variance_used
;
2114 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2115 MonoClass
*iclass
= mono_class_from_mono_type (iface
->type
);
2116 MonoReflectionMethod
*member
;
2119 int i
= 0, len
, ioffset
;
2122 MONO_ARCH_SAVE_REGS
;
2123 mono_class_init_or_throw (class);
2124 mono_class_init_or_throw (iclass
);
2126 mono_class_setup_vtable (class);
2128 ioffset
= mono_class_interface_offset_with_variance (class, iclass
, &variance_used
);
2132 len
= mono_class_num_methods (iclass
);
2133 domain
= mono_object_domain (type
);
2134 mono_gc_wbarrier_generic_store (targets
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.method_info_class
, len
));
2135 mono_gc_wbarrier_generic_store (methods
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.method_info_class
, len
));
2137 while ((method
= mono_class_get_methods (iclass
, &iter
))) {
2138 member
= mono_method_get_object (domain
, method
, iclass
);
2139 mono_array_setref (*methods
, i
, member
);
2140 member
= mono_method_get_object (domain
, class->vtable
[i
+ ioffset
], class);
2141 mono_array_setref (*targets
, i
, member
);
2148 ves_icall_Type_GetPacking (MonoReflectionType
*type
, guint32
*packing
, guint32
*size
)
2150 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2151 mono_class_init_or_throw (klass
);
2153 if (klass
->image
->dynamic
) {
2154 MonoReflectionTypeBuilder
*tb
= (MonoReflectionTypeBuilder
*)type
;
2155 *packing
= tb
->packing_size
;
2156 *size
= tb
->class_size
;
2158 mono_metadata_packing_from_typedef (klass
->image
, klass
->type_token
, packing
, size
);
2162 static MonoReflectionType
*
2163 ves_icall_MonoType_GetElementType (MonoReflectionType
*type
)
2167 MONO_ARCH_SAVE_REGS
;
2169 if (!type
->type
->byref
&& type
->type
->type
== MONO_TYPE_SZARRAY
)
2170 return mono_type_get_object (mono_object_domain (type
), &type
->type
->data
.klass
->byval_arg
);
2172 class = mono_class_from_mono_type (type
->type
);
2173 mono_class_init_or_throw (class);
2175 // GetElementType should only return a type for:
2176 // Array Pointer PassedByRef
2177 if (type
->type
->byref
)
2178 return mono_type_get_object (mono_object_domain (type
), &class->byval_arg
);
2179 else if (class->element_class
&& MONO_CLASS_IS_ARRAY (class))
2180 return mono_type_get_object (mono_object_domain (type
), &class->element_class
->byval_arg
);
2181 else if (class->element_class
&& type
->type
->type
== MONO_TYPE_PTR
)
2182 return mono_type_get_object (mono_object_domain (type
), &class->element_class
->byval_arg
);
2187 static MonoReflectionType
*
2188 ves_icall_get_type_parent (MonoReflectionType
*type
)
2190 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2191 return class->parent
? mono_type_get_object (mono_object_domain (type
), &class->parent
->byval_arg
): NULL
;
2195 ves_icall_type_ispointer (MonoReflectionType
*type
)
2197 MONO_ARCH_SAVE_REGS
;
2199 return type
->type
->type
== MONO_TYPE_PTR
;
2203 ves_icall_type_isprimitive (MonoReflectionType
*type
)
2205 MONO_ARCH_SAVE_REGS
;
2207 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
)));
2211 ves_icall_type_isbyref (MonoReflectionType
*type
)
2213 MONO_ARCH_SAVE_REGS
;
2215 return type
->type
->byref
;
2219 ves_icall_type_iscomobject (MonoReflectionType
*type
)
2221 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
2222 mono_class_init_or_throw (klass
);
2224 return (klass
&& klass
->is_com_object
);
2227 static MonoReflectionModule
*
2228 ves_icall_MonoType_get_Module (MonoReflectionType
*type
)
2230 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2231 mono_class_init_or_throw (class);
2233 return mono_module_get_object (mono_object_domain (type
), class->image
);
2236 static MonoReflectionAssembly
*
2237 ves_icall_MonoType_get_Assembly (MonoReflectionType
*type
)
2239 MonoDomain
*domain
= mono_domain_get ();
2240 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2242 mono_class_init_or_throw (class);
2244 return mono_assembly_get_object (domain
, class->image
->assembly
);
2247 static MonoReflectionType
*
2248 ves_icall_MonoType_get_DeclaringType (MonoReflectionType
*type
)
2250 MonoDomain
*domain
= mono_domain_get ();
2253 MONO_ARCH_SAVE_REGS
;
2255 if (type
->type
->byref
)
2257 if (type
->type
->type
== MONO_TYPE_VAR
)
2258 class = mono_type_get_generic_param_owner (type
->type
)->owner
.klass
;
2259 else if (type
->type
->type
== MONO_TYPE_MVAR
)
2260 class = mono_type_get_generic_param_owner (type
->type
)->owner
.method
->klass
;
2262 class = mono_class_from_mono_type (type
->type
)->nested_in
;
2264 return class ? mono_type_get_object (domain
, &class->byval_arg
) : NULL
;
2268 ves_icall_MonoType_get_Name (MonoReflectionType
*type
)
2270 MonoDomain
*domain
= mono_domain_get ();
2271 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2273 if (type
->type
->byref
) {
2274 char *n
= g_strdup_printf ("%s&", class->name
);
2275 MonoString
*res
= mono_string_new (domain
, n
);
2281 return mono_string_new (domain
, class->name
);
2286 ves_icall_MonoType_get_Namespace (MonoReflectionType
*type
)
2288 MonoDomain
*domain
= mono_domain_get ();
2289 MonoClass
*class = mono_class_from_mono_type (type
->type
);
2291 while (class->nested_in
)
2292 class = class->nested_in
;
2294 if (class->name_space
[0] == '\0')
2297 return mono_string_new (domain
, class->name_space
);
2301 ves_icall_MonoType_GetArrayRank (MonoReflectionType
*type
)
2305 if (type
->type
->type
!= MONO_TYPE_ARRAY
&& type
->type
->type
!= MONO_TYPE_SZARRAY
)
2306 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2308 class = mono_class_from_mono_type (type
->type
);
2309 mono_class_init_or_throw (class);
2315 ves_icall_MonoType_GetGenericArguments (MonoReflectionType
*type
)
2318 MonoClass
*klass
, *pklass
;
2319 MonoDomain
*domain
= mono_object_domain (type
);
2320 MonoVTable
*array_vtable
= mono_class_vtable_full (domain
, mono_array_class_get_cached (mono_defaults
.systemtype_class
, 1), TRUE
);
2322 MONO_ARCH_SAVE_REGS
;
2324 klass
= mono_class_from_mono_type (type
->type
);
2325 mono_class_init_or_throw (klass
);
2327 if (klass
->generic_container
) {
2328 MonoGenericContainer
*container
= klass
->generic_container
;
2329 res
= mono_array_new_specific (array_vtable
, container
->type_argc
);
2330 for (i
= 0; i
< container
->type_argc
; ++i
) {
2331 pklass
= mono_class_from_generic_parameter (mono_generic_container_get_param (container
, i
), klass
->image
, FALSE
);
2332 mono_array_setref (res
, i
, mono_type_get_object (domain
, &pklass
->byval_arg
));
2334 } else if (klass
->generic_class
) {
2335 MonoGenericInst
*inst
= klass
->generic_class
->context
.class_inst
;
2336 res
= mono_array_new_specific (array_vtable
, inst
->type_argc
);
2337 for (i
= 0; i
< inst
->type_argc
; ++i
)
2338 mono_array_setref (res
, i
, mono_type_get_object (domain
, inst
->type_argv
[i
]));
2340 res
= mono_array_new_specific (array_vtable
, 0);
2346 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType
*type
)
2349 MONO_ARCH_SAVE_REGS
;
2351 if (!IS_MONOTYPE (type
))
2354 if (type
->type
->byref
)
2357 klass
= mono_class_from_mono_type (type
->type
);
2358 return klass
->generic_container
!= NULL
;
2361 static MonoReflectionType
*
2362 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType
*type
)
2365 MONO_ARCH_SAVE_REGS
;
2367 if (type
->type
->byref
)
2370 klass
= mono_class_from_mono_type (type
->type
);
2371 mono_class_init_or_throw (klass
);
2373 if (klass
->generic_container
) {
2374 return type
; /* check this one */
2376 if (klass
->generic_class
) {
2377 MonoClass
*generic_class
= klass
->generic_class
->container_class
;
2380 tb
= mono_class_get_ref_info (generic_class
);
2382 if (generic_class
->wastypebuilder
&& tb
)
2385 return mono_type_get_object (mono_object_domain (type
), &generic_class
->byval_arg
);
2390 static MonoReflectionType
*
2391 ves_icall_Type_MakeGenericType (MonoReflectionType
*type
, MonoArray
*type_array
)
2393 MonoType
*geninst
, **types
;
2396 g_assert (IS_MONOTYPE (type
));
2397 mono_class_init_or_throw (mono_class_from_mono_type (type
->type
));
2399 count
= mono_array_length (type_array
);
2400 types
= g_new0 (MonoType
*, count
);
2402 for (i
= 0; i
< count
; i
++) {
2403 MonoReflectionType
*t
= mono_array_get (type_array
, gpointer
, i
);
2404 types
[i
] = t
->type
;
2407 geninst
= mono_reflection_bind_generic_parameters (type
, count
, types
);
2412 return mono_type_get_object (mono_object_domain (type
), geninst
);
2416 ves_icall_Type_get_IsGenericInstance (MonoReflectionType
*type
)
2419 MONO_ARCH_SAVE_REGS
;
2421 if (type
->type
->byref
)
2424 klass
= mono_class_from_mono_type (type
->type
);
2426 return klass
->generic_class
!= NULL
;
2430 ves_icall_Type_get_IsGenericType (MonoReflectionType
*type
)
2433 MONO_ARCH_SAVE_REGS
;
2435 if (!IS_MONOTYPE (type
))
2438 if (type
->type
->byref
)
2441 klass
= mono_class_from_mono_type (type
->type
);
2442 return klass
->generic_class
!= NULL
|| klass
->generic_container
!= NULL
;
2446 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType
*type
)
2448 MONO_ARCH_SAVE_REGS
;
2450 if (!IS_MONOTYPE (type
))
2453 if (is_generic_parameter (type
->type
))
2454 return mono_type_get_generic_param_num (type
->type
);
2458 static GenericParameterAttributes
2459 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType
*type
)
2461 MONO_ARCH_SAVE_REGS
;
2463 g_assert (IS_MONOTYPE (type
));
2464 g_assert (is_generic_parameter (type
->type
));
2465 return mono_generic_param_info (type
->type
->data
.generic_param
)->flags
;
2469 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType
*type
)
2471 MonoGenericParamInfo
*param_info
;
2477 MONO_ARCH_SAVE_REGS
;
2479 g_assert (IS_MONOTYPE (type
));
2481 domain
= mono_object_domain (type
);
2482 param_info
= mono_generic_param_info (type
->type
->data
.generic_param
);
2483 for (count
= 0, ptr
= param_info
->constraints
; ptr
&& *ptr
; ptr
++, count
++)
2486 res
= mono_array_new (domain
, mono_defaults
.monotype_class
, count
);
2487 for (i
= 0; i
< count
; i
++)
2488 mono_array_setref (res
, i
, mono_type_get_object (domain
, ¶m_info
->constraints
[i
]->byval_arg
));
2495 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType
*type
)
2497 MONO_ARCH_SAVE_REGS
;
2498 return is_generic_parameter (type
->type
);
2502 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder
*tb
)
2504 MONO_ARCH_SAVE_REGS
;
2505 return is_generic_parameter (tb
->type
.type
);
2509 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType
*enumtype
,
2510 MonoReflectionType
*t
)
2512 enumtype
->type
= t
->type
;
2515 static MonoReflectionMethod
*
2516 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType
*type
,
2517 MonoReflectionMethod
* generic
)
2524 MONO_ARCH_SAVE_REGS
;
2526 domain
= ((MonoObject
*)type
)->vtable
->domain
;
2528 klass
= mono_class_from_mono_type (type
->type
);
2529 mono_class_init_or_throw (klass
);
2532 while ((method
= mono_class_get_methods (klass
, &iter
))) {
2533 if (method
->token
== generic
->method
->token
)
2534 return mono_method_get_object (domain
, method
, klass
);
2542 static MonoReflectionMethod
*
2543 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType
*ref_type
)
2546 MonoType
*type
= ref_type
->type
;
2548 MONO_ARCH_SAVE_REGS
;
2550 if (type
->byref
|| (type
->type
!= MONO_TYPE_MVAR
&& type
->type
!= MONO_TYPE_VAR
))
2551 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2552 if (type
->type
== MONO_TYPE_VAR
)
2555 method
= mono_type_get_generic_param_owner (type
)->owner
.method
;
2557 return mono_method_get_object (mono_object_domain (ref_type
), method
, method
->klass
);
2560 static MonoReflectionDllImportAttribute
*
2561 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod
*method
)
2563 static MonoClass
*DllImportAttributeClass
= NULL
;
2564 MonoDomain
*domain
= mono_domain_get ();
2565 MonoReflectionDllImportAttribute
*attr
;
2566 MonoImage
*image
= method
->klass
->image
;
2567 MonoMethodPInvoke
*piinfo
= (MonoMethodPInvoke
*)method
;
2568 MonoTableInfo
*tables
= image
->tables
;
2569 MonoTableInfo
*im
= &tables
[MONO_TABLE_IMPLMAP
];
2570 MonoTableInfo
*mr
= &tables
[MONO_TABLE_MODULEREF
];
2571 guint32 im_cols
[MONO_IMPLMAP_SIZE
];
2572 guint32 scope_token
;
2573 const char *import
= NULL
;
2574 const char *scope
= NULL
;
2577 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
2580 if (!DllImportAttributeClass
) {
2581 DllImportAttributeClass
=
2582 mono_class_from_name (mono_defaults
.corlib
,
2583 "System.Runtime.InteropServices", "DllImportAttribute");
2584 g_assert (DllImportAttributeClass
);
2587 if (method
->klass
->image
->dynamic
) {
2588 MonoReflectionMethodAux
*method_aux
=
2589 g_hash_table_lookup (
2590 ((MonoDynamicImage
*)method
->klass
->image
)->method_aux_hash
, method
);
2592 import
= method_aux
->dllentry
;
2593 scope
= method_aux
->dll
;
2596 if (!import
|| !scope
) {
2597 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2602 if (piinfo
->implmap_idx
) {
2603 mono_metadata_decode_row (im
, piinfo
->implmap_idx
- 1, im_cols
, MONO_IMPLMAP_SIZE
);
2605 piinfo
->piflags
= im_cols
[MONO_IMPLMAP_FLAGS
];
2606 import
= mono_metadata_string_heap (image
, im_cols
[MONO_IMPLMAP_NAME
]);
2607 scope_token
= mono_metadata_decode_row_col (mr
, im_cols
[MONO_IMPLMAP_SCOPE
] - 1, MONO_MODULEREF_NAME
);
2608 scope
= mono_metadata_string_heap (image
, scope_token
);
2611 flags
= piinfo
->piflags
;
2613 attr
= (MonoReflectionDllImportAttribute
*)mono_object_new (domain
, DllImportAttributeClass
);
2615 MONO_OBJECT_SETREF (attr
, dll
, mono_string_new (domain
, scope
));
2616 MONO_OBJECT_SETREF (attr
, entry_point
, mono_string_new (domain
, import
));
2617 attr
->call_conv
= (flags
& 0x700) >> 8;
2618 attr
->charset
= ((flags
& 0x6) >> 1) + 1;
2619 if (attr
->charset
== 1)
2621 attr
->exact_spelling
= (flags
& 0x1) != 0;
2622 attr
->set_last_error
= (flags
& 0x40) != 0;
2623 attr
->best_fit_mapping
= (flags
& 0x30) == 0x10;
2624 attr
->throw_on_unmappable
= (flags
& 0x3000) == 0x1000;
2625 attr
->preserve_sig
= FALSE
;
2630 static MonoReflectionMethod
*
2631 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod
*method
)
2633 MonoMethodInflated
*imethod
;
2636 MONO_ARCH_SAVE_REGS
;
2638 if (method
->method
->is_generic
)
2641 if (!method
->method
->is_inflated
)
2644 imethod
= (MonoMethodInflated
*) method
->method
;
2646 result
= imethod
->declaring
;
2647 /* Not a generic method. */
2648 if (!result
->is_generic
)
2651 if (method
->method
->klass
->image
->dynamic
) {
2652 MonoDynamicImage
*image
= (MonoDynamicImage
*)method
->method
->klass
->image
;
2653 MonoReflectionMethod
*res
;
2656 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2657 * the dynamic case as well ?
2659 mono_loader_lock ();
2660 res
= mono_g_hash_table_lookup (image
->generic_def_objects
, imethod
);
2661 mono_loader_unlock ();
2667 if (imethod
->context
.class_inst
) {
2668 MonoClass
*klass
= ((MonoMethod
*) imethod
)->klass
;
2669 /*Generic methods gets the context of the GTD.*/
2670 if (mono_class_get_context (klass
))
2671 result
= mono_class_inflate_generic_method_full (result
, klass
, mono_class_get_context (klass
));
2674 return mono_method_get_object (mono_object_domain (method
), result
, NULL
);
2678 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod
*method
)
2680 MONO_ARCH_SAVE_REGS
;
2682 return mono_method_signature (method
->method
)->generic_param_count
!= 0;
2686 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod
*method
)
2688 MONO_ARCH_SAVE_REGS
;
2690 return method
->method
->is_generic
;
2694 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod
*method
)
2699 MONO_ARCH_SAVE_REGS
;
2701 domain
= mono_object_domain (method
);
2703 if (method
->method
->is_inflated
) {
2704 MonoGenericInst
*inst
= mono_method_get_context (method
->method
)->method_inst
;
2707 count
= inst
->type_argc
;
2708 res
= mono_array_new (domain
, mono_defaults
.systemtype_class
, count
);
2710 for (i
= 0; i
< count
; i
++)
2711 mono_array_setref (res
, i
, mono_type_get_object (domain
, inst
->type_argv
[i
]));
2717 count
= mono_method_signature (method
->method
)->generic_param_count
;
2718 res
= mono_array_new (domain
, mono_defaults
.systemtype_class
, count
);
2720 for (i
= 0; i
< count
; i
++) {
2721 MonoGenericContainer
*container
= mono_method_get_generic_container (method
->method
);
2722 MonoGenericParam
*param
= mono_generic_container_get_param (container
, i
);
2723 MonoClass
*pklass
= mono_class_from_generic_parameter (
2724 param
, method
->method
->klass
->image
, TRUE
);
2725 mono_array_setref (res
, i
,
2726 mono_type_get_object (domain
, &pklass
->byval_arg
));
2733 ves_icall_InternalInvoke (MonoReflectionMethod
*method
, MonoObject
*this, MonoArray
*params
, MonoException
**exc
)
2736 * Invoke from reflection is supposed to always be a virtual call (the API
2737 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2738 * greater flexibility.
2740 MonoMethod
*m
= method
->method
;
2744 MONO_ARCH_SAVE_REGS
;
2748 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
)
2749 mono_security_core_clr_ensure_reflection_access_method (m
);
2751 if (!(m
->flags
& METHOD_ATTRIBUTE_STATIC
)) {
2752 if (!mono_class_vtable_full (mono_object_domain (method
), m
->klass
, FALSE
)) {
2753 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_class_get_exception_for_failure (m
->klass
));
2758 if (!mono_object_isinst (this, m
->klass
)) {
2759 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Object does not match target type."));
2762 m
= mono_object_get_virtual_method (this, m
);
2763 /* must pass the pointer to the value for valuetype methods */
2764 if (m
->klass
->valuetype
)
2765 obj
= mono_object_unbox (this);
2766 } else if (strcmp (m
->name
, ".ctor") && !m
->wrapper_type
) {
2767 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name_msg (mono_defaults
.corlib
, "System.Reflection", "TargetException", "Non-static method requires a target."));
2772 pcount
= params
? mono_array_length (params
): 0;
2773 if (pcount
!= mono_method_signature (m
)->param_count
) {
2774 mono_gc_wbarrier_generic_store (exc
, (MonoObject
*) mono_exception_from_name (mono_defaults
.corlib
, "System.Reflection", "TargetParameterCountException"));
2778 if ((m
->klass
->flags
& TYPE_ATTRIBUTE_ABSTRACT
) && !strcmp (m
->name
, ".ctor") && !this) {
2779 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."));
2783 if (m
->klass
->image
->assembly
->ref_only
) {
2784 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."));
2788 if (m
->klass
->rank
&& !strcmp (m
->name
, ".ctor")) {
2791 intptr_t *lower_bounds
;
2792 pcount
= mono_array_length (params
);
2793 lengths
= alloca (sizeof (uintptr_t) * pcount
);
2794 /* Note: the synthetized array .ctors have int32 as argument type */
2795 for (i
= 0; i
< pcount
; ++i
)
2796 lengths
[i
] = *(int32_t*) ((char*)mono_array_get (params
, gpointer
, i
) + sizeof (MonoObject
));
2798 if (m
->klass
->rank
== pcount
) {
2799 /* Only lengths provided. */
2800 lower_bounds
= NULL
;
2802 g_assert (pcount
== (m
->klass
->rank
* 2));
2803 /* lower bounds are first. */
2804 lower_bounds
= (intptr_t*)lengths
;
2805 lengths
+= m
->klass
->rank
;
2808 return (MonoObject
*)mono_array_new_full (mono_object_domain (params
), m
->klass
, lengths
, lower_bounds
);
2810 return mono_runtime_invoke_array (m
, obj
, params
, NULL
);
2814 ves_icall_InternalExecute (MonoReflectionMethod
*method
, MonoObject
*this, MonoArray
*params
, MonoArray
**outArgs
)
2816 MonoDomain
*domain
= mono_object_domain (method
);
2817 MonoMethod
*m
= method
->method
;
2818 MonoMethodSignature
*sig
= mono_method_signature (m
);
2819 MonoArray
*out_args
;
2821 int i
, j
, outarg_count
= 0;
2823 MONO_ARCH_SAVE_REGS
;
2825 if (m
->klass
== mono_defaults
.object_class
) {
2827 if (!strcmp (m
->name
, "FieldGetter")) {
2828 MonoClass
*k
= this->vtable
->klass
;
2832 /* If this is a proxy, then it must be a CBO */
2833 if (k
== mono_defaults
.transparent_proxy_class
) {
2834 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
2835 this = tp
->rp
->unwrapped_server
;
2837 k
= this->vtable
->klass
;
2840 name
= mono_array_get (params
, MonoString
*, 1);
2841 str
= mono_string_to_utf8 (name
);
2844 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
2846 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2847 if (field_klass
->valuetype
)
2848 result
= mono_value_box (domain
, field_klass
, (char *)this + field
->offset
);
2850 result
= *((gpointer
*)((char *)this + field
->offset
));
2852 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 1);
2853 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2854 mono_array_setref (out_args
, 0, result
);
2862 g_assert_not_reached ();
2864 } else if (!strcmp (m
->name
, "FieldSetter")) {
2865 MonoClass
*k
= this->vtable
->klass
;
2871 /* If this is a proxy, then it must be a CBO */
2872 if (k
== mono_defaults
.transparent_proxy_class
) {
2873 MonoTransparentProxy
*tp
= (MonoTransparentProxy
*) this;
2874 this = tp
->rp
->unwrapped_server
;
2876 k
= this->vtable
->klass
;
2879 name
= mono_array_get (params
, MonoString
*, 1);
2880 str
= mono_string_to_utf8 (name
);
2883 MonoClassField
* field
= mono_class_get_field_from_name (k
, str
);
2885 MonoClass
*field_klass
= mono_class_from_mono_type (field
->type
);
2886 MonoObject
*val
= mono_array_get (params
, gpointer
, 2);
2888 if (field_klass
->valuetype
) {
2889 size
= mono_type_size (field
->type
, &align
);
2890 g_assert (size
== mono_class_value_size (field_klass
, NULL
));
2891 mono_gc_wbarrier_value_copy ((char *)this + field
->offset
, (char*)val
+ sizeof (MonoObject
), 1, field_klass
);
2893 mono_gc_wbarrier_set_field (this, (char*)this + field
->offset
, val
);
2896 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, 0);
2897 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2907 g_assert_not_reached ();
2912 for (i
= 0; i
< mono_array_length (params
); i
++) {
2913 if (sig
->params
[i
]->byref
)
2917 out_args
= mono_array_new (domain
, mono_defaults
.object_class
, outarg_count
);
2919 /* handle constructors only for objects already allocated */
2920 if (!strcmp (method
->method
->name
, ".ctor"))
2923 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2924 g_assert (!method
->method
->klass
->valuetype
);
2925 result
= mono_runtime_invoke_array (method
->method
, this, params
, NULL
);
2927 for (i
= 0, j
= 0; i
< mono_array_length (params
); i
++) {
2928 if (sig
->params
[i
]->byref
) {
2930 arg
= mono_array_get (params
, gpointer
, i
);
2931 mono_array_setref (out_args
, j
, arg
);
2936 mono_gc_wbarrier_generic_store (outArgs
, (MonoObject
*) out_args
);
2942 read_enum_value (char *mem
, int type
)
2946 return *(guint8
*)mem
;
2948 return *(gint8
*)mem
;
2950 return *(guint16
*)mem
;
2952 return *(gint16
*)mem
;
2954 return *(guint32
*)mem
;
2956 return *(gint32
*)mem
;
2958 return *(guint64
*)mem
;
2960 return *(gint64
*)mem
;
2962 g_assert_not_reached ();
2968 write_enum_value (char *mem
, int type
, guint64 value
)
2972 case MONO_TYPE_I1
: {
2973 guint8
*p
= (guint8
*)mem
;
2978 case MONO_TYPE_I2
: {
2979 guint16
*p
= (void*)mem
;
2984 case MONO_TYPE_I4
: {
2985 guint32
*p
= (void*)mem
;
2990 case MONO_TYPE_I8
: {
2991 guint64
*p
= (void*)mem
;
2996 g_assert_not_reached ();
3002 ves_icall_System_Enum_ToObject (MonoReflectionType
*enumType
, MonoObject
*value
)
3005 MonoClass
*enumc
, *objc
;
3010 MONO_ARCH_SAVE_REGS
;
3012 MONO_CHECK_ARG_NULL (enumType
);
3013 MONO_CHECK_ARG_NULL (value
);
3015 domain
= mono_object_domain (enumType
);
3016 enumc
= mono_class_from_mono_type (enumType
->type
);
3018 mono_class_init_or_throw (enumc
);
3020 objc
= value
->vtable
->klass
;
3022 if (!enumc
->enumtype
)
3023 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3024 if (!((objc
->enumtype
) || (objc
->byval_arg
.type
>= MONO_TYPE_I1
&& objc
->byval_arg
.type
<= MONO_TYPE_U8
)))
3025 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."));
3027 etype
= mono_class_enum_basetype (enumc
);
3029 /* MS throws this for typebuilders */
3030 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3032 res
= mono_object_new (domain
, enumc
);
3033 val
= read_enum_value ((char *)value
+ sizeof (MonoObject
), objc
->enumtype
? mono_class_enum_basetype (objc
)->type
: objc
->byval_arg
.type
);
3034 write_enum_value ((char *)res
+ sizeof (MonoObject
), etype
->type
, val
);
3040 ves_icall_System_Enum_get_value (MonoObject
*this)
3048 MONO_ARCH_SAVE_REGS
;
3053 g_assert (this->vtable
->klass
->enumtype
);
3055 enumc
= mono_class_from_mono_type (mono_class_enum_basetype (this->vtable
->klass
));
3056 res
= mono_object_new (mono_object_domain (this), enumc
);
3057 dst
= (char *)res
+ sizeof (MonoObject
);
3058 src
= (char *)this + sizeof (MonoObject
);
3059 size
= mono_class_value_size (enumc
, NULL
);
3061 memcpy (dst
, src
, size
);
3066 static MonoReflectionType
*
3067 ves_icall_System_Enum_get_underlying_type (MonoReflectionType
*type
)
3072 MONO_ARCH_SAVE_REGS
;
3074 klass
= mono_class_from_mono_type (type
->type
);
3075 mono_class_init_or_throw (klass
);
3077 etype
= mono_class_enum_basetype (klass
);
3079 /* MS throws this for typebuilders */
3080 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3082 return mono_type_get_object (mono_object_domain (type
), etype
);
3086 ves_icall_System_Enum_compare_value_to (MonoObject
*this, MonoObject
*other
)
3088 gpointer tdata
= (char *)this + sizeof (MonoObject
);
3089 gpointer odata
= (char *)other
+ sizeof (MonoObject
);
3090 MonoType
*basetype
= mono_class_enum_basetype (this->vtable
->klass
);
3091 g_assert (basetype
);
3093 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3094 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3095 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3098 return me > other ? 1 : -1; \
3101 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3102 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3103 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3106 return me - other; \
3109 switch (basetype
->type
) {
3111 COMPARE_ENUM_VALUES (guint8
);
3113 COMPARE_ENUM_VALUES (gint8
);
3114 case MONO_TYPE_CHAR
:
3116 COMPARE_ENUM_VALUES_RANGE (guint16
);
3118 COMPARE_ENUM_VALUES (gint16
);
3120 COMPARE_ENUM_VALUES (guint32
);
3122 COMPARE_ENUM_VALUES (gint32
);
3124 COMPARE_ENUM_VALUES (guint64
);
3126 COMPARE_ENUM_VALUES (gint64
);
3128 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3130 #undef COMPARE_ENUM_VALUES_RANGE
3131 #undef COMPARE_ENUM_VALUES
3136 ves_icall_System_Enum_get_hashcode (MonoObject
*this)
3138 gpointer data
= (char *)this + sizeof (MonoObject
);
3139 MonoType
*basetype
= mono_class_enum_basetype (this->vtable
->klass
);
3140 g_assert (basetype
);
3142 switch (basetype
->type
) {
3144 return *((gint8
*)data
);
3146 return *((guint8
*)data
);
3147 case MONO_TYPE_CHAR
:
3149 return *((guint16
*)data
);
3152 return *((gint16
*)data
);
3154 return *((guint32
*)data
);
3156 return *((gint32
*)data
);
3158 case MONO_TYPE_I8
: {
3159 gint64 value
= *((gint64
*)data
);
3160 return (gint
)(value
& 0xffffffff) ^ (int)(value
>> 32);
3163 g_error ("Implement type 0x%02x in get_hashcode", basetype
->type
);
3169 ves_icall_get_enum_info (MonoReflectionType
*type
, MonoEnumInfo
*info
)
3171 MonoDomain
*domain
= mono_object_domain (type
);
3172 MonoClass
*enumc
= mono_class_from_mono_type (type
->type
);
3173 guint j
= 0, nvalues
, crow
;
3175 MonoClassField
*field
;
3177 MONO_ARCH_SAVE_REGS
;
3179 mono_class_init_or_throw (enumc
);
3181 MONO_STRUCT_SETREF (info
, utype
, mono_type_get_object (domain
, mono_class_enum_basetype (enumc
)));
3182 nvalues
= mono_class_num_fields (enumc
) ? mono_class_num_fields (enumc
) - 1 : 0;
3183 MONO_STRUCT_SETREF (info
, names
, mono_array_new (domain
, mono_defaults
.string_class
, nvalues
));
3184 MONO_STRUCT_SETREF (info
, values
, mono_array_new (domain
, enumc
, nvalues
));
3188 while ((field
= mono_class_get_fields (enumc
, &iter
))) {
3191 MonoTypeEnum def_type
;
3193 if (strcmp ("value__", mono_field_get_name (field
)) == 0)
3195 if (mono_field_is_deleted (field
))
3197 mono_array_setref (info
->names
, j
, mono_string_new (domain
, mono_field_get_name (field
)));
3199 p
= mono_class_get_field_default_value (field
, &def_type
);
3200 len
= mono_metadata_decode_blob_size (p
, &p
);
3201 switch (mono_class_enum_basetype (enumc
)->type
) {
3204 mono_array_set (info
->values
, gchar
, j
, *p
);
3206 case MONO_TYPE_CHAR
:
3209 mono_array_set (info
->values
, gint16
, j
, read16 (p
));
3213 mono_array_set (info
->values
, gint32
, j
, read32 (p
));
3217 mono_array_set (info
->values
, gint64
, j
, read64 (p
));
3220 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc
)->type
);
3227 BFLAGS_IgnoreCase
= 1,
3228 BFLAGS_DeclaredOnly
= 2,
3229 BFLAGS_Instance
= 4,
3231 BFLAGS_Public
= 0x10,
3232 BFLAGS_NonPublic
= 0x20,
3233 BFLAGS_FlattenHierarchy
= 0x40,
3234 BFLAGS_InvokeMethod
= 0x100,
3235 BFLAGS_CreateInstance
= 0x200,
3236 BFLAGS_GetField
= 0x400,
3237 BFLAGS_SetField
= 0x800,
3238 BFLAGS_GetProperty
= 0x1000,
3239 BFLAGS_SetProperty
= 0x2000,
3240 BFLAGS_ExactBinding
= 0x10000,
3241 BFLAGS_SuppressChangeType
= 0x20000,
3242 BFLAGS_OptionalParamBinding
= 0x40000
3245 static MonoReflectionField
*
3246 ves_icall_Type_GetField (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3249 MonoClass
*startklass
, *klass
;
3251 MonoClassField
*field
;
3254 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3255 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3256 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3257 mono_class_init_or_throw (klass
);
3260 mono_raise_exception (mono_get_exception_argument_null ("name"));
3261 if (type
->type
->byref
)
3264 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
3267 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3268 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3271 while ((field
= mono_class_get_fields (klass
, &iter
))) {
3274 if (field
->type
== NULL
)
3276 if (mono_field_is_deleted (field
))
3278 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3279 if (bflags
& BFLAGS_Public
)
3281 } else if ((klass
== startklass
) || (field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3282 if (bflags
& BFLAGS_NonPublic
) {
3289 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
3290 if (bflags
& BFLAGS_Static
)
3291 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3294 if (bflags
& BFLAGS_Instance
)
3301 utf8_name
= mono_string_to_utf8 (name
);
3303 if (compare_func (mono_field_get_name (field
), utf8_name
)) {
3309 return mono_field_get_object (domain
, klass
, field
);
3311 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3318 ves_icall_Type_GetFields_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3321 MonoClass
*startklass
, *klass
, *refklass
;
3326 MonoClassField
*field
;
3327 MonoPtrArray tmp_array
;
3329 MONO_ARCH_SAVE_REGS
;
3331 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3332 if (type
->type
->byref
)
3333 return mono_array_new (domain
, mono_defaults
.field_info_class
, 0);
3334 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3335 refklass
= mono_class_from_mono_type (reftype
->type
);
3337 mono_class_init_or_throw (klass
);
3338 mono_class_init_or_throw (refklass
);
3340 mono_ptr_array_init (tmp_array
, 2);
3343 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3344 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3347 while ((field
= mono_class_get_fields (klass
, &iter
))) {
3349 if (mono_field_is_deleted (field
))
3351 if ((field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) == FIELD_ATTRIBUTE_PUBLIC
) {
3352 if (bflags
& BFLAGS_Public
)
3354 } else if ((klass
== startklass
) || (field
->type
->attrs
& FIELD_ATTRIBUTE_FIELD_ACCESS_MASK
) != FIELD_ATTRIBUTE_PRIVATE
) {
3355 if (bflags
& BFLAGS_NonPublic
) {
3362 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
) {
3363 if (bflags
& BFLAGS_Static
)
3364 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3367 if (bflags
& BFLAGS_Instance
)
3373 member
= (MonoObject
*)mono_field_get_object (domain
, refklass
, field
);
3374 mono_ptr_array_append (tmp_array
, member
);
3376 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3379 res
= mono_array_new_cached (domain
, mono_defaults
.field_info_class
, mono_ptr_array_size (tmp_array
));
3381 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3382 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3384 mono_ptr_array_destroy (tmp_array
);
3390 method_nonpublic (MonoMethod
* method
, gboolean start_klass
)
3392 switch (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) {
3393 case METHOD_ATTRIBUTE_ASSEM
:
3394 return (start_klass
|| mono_defaults
.generic_ilist_class
);
3395 case METHOD_ATTRIBUTE_PRIVATE
:
3397 case METHOD_ATTRIBUTE_PUBLIC
:
3405 ves_icall_Type_GetMethodsByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3407 static MonoClass
*MethodInfo_array
;
3409 MonoClass
*startklass
, *klass
, *refklass
;
3414 int i
, len
, match
, nslots
;
3415 /*FIXME, use MonoBitSet*/
3416 guint32 method_slots_default
[8];
3417 guint32
*method_slots
= NULL
;
3418 gchar
*mname
= NULL
;
3419 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3420 MonoVTable
*array_vtable
;
3422 MonoPtrArray tmp_array
;
3424 mono_ptr_array_init (tmp_array
, 4);
3426 if (!MethodInfo_array
) {
3427 MonoClass
*klass
= mono_array_class_get (mono_defaults
.method_info_class
, 1);
3428 mono_memory_barrier ();
3429 MethodInfo_array
= klass
;
3432 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3433 array_vtable
= mono_class_vtable_full (domain
, MethodInfo_array
, TRUE
);
3434 if (type
->type
->byref
)
3435 return mono_array_new_specific (array_vtable
, 0);
3436 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3437 refklass
= mono_class_from_mono_type (reftype
->type
);
3439 mono_class_init_or_throw (klass
);
3440 mono_class_init_or_throw (refklass
);
3444 mname
= mono_string_to_utf8 (name
);
3445 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3448 /* An optimization for calls made from Delegate:CreateDelegate () */
3449 if (klass
->delegate
&& mname
&& !strcmp (mname
, "Invoke") && (bflags
== (BFLAGS_Public
| BFLAGS_Static
| BFLAGS_Instance
))) {
3450 method
= mono_get_delegate_invoke (klass
);
3451 if (mono_loader_get_last_error ())
3454 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3456 res
= mono_array_new_specific (array_vtable
, 1);
3457 mono_array_setref (res
, 0, member
);
3462 mono_class_setup_vtable (klass
);
3463 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3466 if (is_generic_parameter (type
->type
))
3467 nslots
= mono_class_get_vtable_size (klass
->parent
);
3469 nslots
= MONO_CLASS_IS_INTERFACE (klass
) ? mono_class_num_methods (klass
) : mono_class_get_vtable_size (klass
);
3470 if (nslots
>= sizeof (method_slots_default
) * 8) {
3471 method_slots
= g_new0 (guint32
, nslots
/ 32 + 1);
3473 method_slots
= method_slots_default
;
3474 memset (method_slots
, 0, sizeof (method_slots_default
));
3477 mono_class_setup_vtable (klass
);
3478 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
|| mono_loader_get_last_error ())
3482 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3484 if (method
->slot
!= -1) {
3485 g_assert (method
->slot
< nslots
);
3486 if (method_slots
[method
->slot
>> 5] & (1 << (method
->slot
& 0x1f)))
3488 if (!(method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
))
3489 method_slots
[method
->slot
>> 5] |= 1 << (method
->slot
& 0x1f);
3492 if (method
->name
[0] == '.' && (strcmp (method
->name
, ".ctor") == 0 || strcmp (method
->name
, ".cctor") == 0))
3494 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3495 if (bflags
& BFLAGS_Public
)
3497 } else if ((bflags
& BFLAGS_NonPublic
) && method_nonpublic (method
, (klass
== startklass
))) {
3503 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3504 if (bflags
& BFLAGS_Static
)
3505 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3508 if (bflags
& BFLAGS_Instance
)
3516 if (compare_func (mname
, method
->name
))
3522 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3524 mono_ptr_array_append (tmp_array
, member
);
3526 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3530 if (method_slots
!= method_slots_default
)
3531 g_free (method_slots
);
3533 res
= mono_array_new_specific (array_vtable
, mono_ptr_array_size (tmp_array
));
3535 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3536 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3538 mono_ptr_array_destroy (tmp_array
);
3543 if (method_slots
!= method_slots_default
)
3544 g_free (method_slots
);
3545 mono_ptr_array_destroy (tmp_array
);
3546 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3547 ex
= mono_class_get_exception_for_failure (klass
);
3549 ex
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3550 mono_loader_clear_error ();
3552 mono_raise_exception (ex
);
3557 ves_icall_Type_GetConstructors_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3560 static MonoClass
*System_Reflection_ConstructorInfo
;
3561 MonoClass
*startklass
, *klass
, *refklass
;
3566 gpointer iter
= NULL
;
3567 MonoPtrArray tmp_array
;
3569 MONO_ARCH_SAVE_REGS
;
3571 mono_ptr_array_init (tmp_array
, 4); /*FIXME, guestimating*/
3573 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3574 if (type
->type
->byref
)
3575 return mono_array_new_cached (domain
, mono_defaults
.method_info_class
, 0);
3576 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3577 refklass
= mono_class_from_mono_type (reftype
->type
);
3579 mono_class_init_or_throw (klass
);
3580 mono_class_init_or_throw (refklass
);
3582 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3583 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3585 if (!System_Reflection_ConstructorInfo
)
3586 System_Reflection_ConstructorInfo
= mono_class_from_name (
3587 mono_defaults
.corlib
, "System.Reflection", "ConstructorInfo");
3590 while ((method
= mono_class_get_methods (klass
, &iter
))) {
3592 if (strcmp (method
->name
, ".ctor") && strcmp (method
->name
, ".cctor"))
3594 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3595 if (bflags
& BFLAGS_Public
)
3598 if (bflags
& BFLAGS_NonPublic
)
3604 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3605 if (bflags
& BFLAGS_Static
)
3606 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3609 if (bflags
& BFLAGS_Instance
)
3615 member
= (MonoObject
*)mono_method_get_object (domain
, method
, refklass
);
3617 mono_ptr_array_append (tmp_array
, member
);
3620 res
= mono_array_new_cached (domain
, System_Reflection_ConstructorInfo
, mono_ptr_array_size (tmp_array
));
3622 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3623 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3625 mono_ptr_array_destroy (tmp_array
);
3631 property_hash (gconstpointer data
)
3633 MonoProperty
*prop
= (MonoProperty
*)data
;
3635 return g_str_hash (prop
->name
);
3639 property_equal (MonoProperty
*prop1
, MonoProperty
*prop2
)
3641 // Properties are hide-by-name-and-signature
3642 if (!g_str_equal (prop1
->name
, prop2
->name
))
3645 if (prop1
->get
&& prop2
->get
&& !mono_metadata_signature_equal (mono_method_signature (prop1
->get
), mono_method_signature (prop2
->get
)))
3647 if (prop1
->set
&& prop2
->set
&& !mono_metadata_signature_equal (mono_method_signature (prop1
->set
), mono_method_signature (prop2
->set
)))
3653 property_accessor_nonpublic (MonoMethod
* accessor
, gboolean start_klass
)
3658 return method_nonpublic (accessor
, start_klass
);
3662 ves_icall_Type_GetPropertiesByName (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
, MonoBoolean ignore_case
, MonoReflectionType
*reftype
)
3665 static MonoClass
*System_Reflection_PropertyInfo
;
3666 MonoClass
*startklass
, *klass
;
3672 gchar
*propname
= NULL
;
3673 int (*compare_func
) (const char *s1
, const char *s2
) = NULL
;
3675 GHashTable
*properties
;
3676 MonoPtrArray tmp_array
;
3678 MONO_ARCH_SAVE_REGS
;
3680 mono_ptr_array_init (tmp_array
, 8); /*This the average for ASP.NET types*/
3682 if (!System_Reflection_PropertyInfo
)
3683 System_Reflection_PropertyInfo
= mono_class_from_name (
3684 mono_defaults
.corlib
, "System.Reflection", "PropertyInfo");
3686 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3687 if (type
->type
->byref
)
3688 return mono_array_new_cached (domain
, System_Reflection_PropertyInfo
, 0);
3689 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3690 mono_class_init_or_throw (klass
);
3695 propname
= mono_string_to_utf8 (name
);
3696 compare_func
= (ignore_case
) ? mono_utf8_strcasecmp
: strcmp
;
3699 mono_class_setup_vtable (klass
);
3701 properties
= g_hash_table_new (property_hash
, (GEqualFunc
)property_equal
);
3703 mono_class_setup_vtable (klass
);
3704 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
) {
3705 g_hash_table_destroy (properties
);
3708 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3712 while ((prop
= mono_class_get_properties (klass
, &iter
))) {
3718 flags
= method
->flags
;
3721 if ((prop
->get
&& ((prop
->get
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
)) ||
3722 (prop
->set
&& ((prop
->set
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
))) {
3723 if (bflags
& BFLAGS_Public
)
3725 } else if (bflags
& BFLAGS_NonPublic
) {
3726 if (property_accessor_nonpublic(prop
->get
, startklass
== klass
) ||
3727 property_accessor_nonpublic(prop
->set
, startklass
== klass
)) {
3734 if (flags
& METHOD_ATTRIBUTE_STATIC
) {
3735 if (bflags
& BFLAGS_Static
)
3736 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3739 if (bflags
& BFLAGS_Instance
)
3748 if (compare_func (propname
, prop
->name
))
3752 if (g_hash_table_lookup (properties
, prop
))
3755 mono_ptr_array_append (tmp_array
, mono_property_get_object (domain
, startklass
, prop
));
3757 g_hash_table_insert (properties
, prop
, prop
);
3759 if ((!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
)))
3762 g_hash_table_destroy (properties
);
3765 res
= mono_array_new_cached (domain
, System_Reflection_PropertyInfo
, mono_ptr_array_size (tmp_array
));
3766 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3767 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3769 mono_ptr_array_destroy (tmp_array
);
3774 static MonoReflectionEvent
*
3775 ves_icall_MonoType_GetEvent (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3778 MonoClass
*klass
, *startklass
;
3783 int (*compare_func
) (const char *s1
, const char *s2
);
3785 MONO_ARCH_SAVE_REGS
;
3787 event_name
= mono_string_to_utf8 (name
);
3788 if (type
->type
->byref
)
3790 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3791 domain
= mono_object_domain (type
);
3793 mono_class_init_or_throw (klass
);
3795 compare_func
= (bflags
& BFLAGS_IgnoreCase
) ? mono_utf8_strcasecmp
: strcmp
;
3797 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3798 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3801 while ((event
= mono_class_get_events (klass
, &iter
))) {
3802 if (compare_func (event
->name
, event_name
))
3805 method
= event
->add
;
3807 method
= event
->remove
;
3809 method
= event
->raise
;
3811 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3812 if (!(bflags
& BFLAGS_Public
))
3815 if (!(bflags
& BFLAGS_NonPublic
))
3817 if ((klass
!= startklass
) && (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PRIVATE
)
3821 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3822 if (!(bflags
& BFLAGS_Static
))
3824 if (!(bflags
& BFLAGS_FlattenHierarchy
) && (klass
!= startklass
))
3827 if (!(bflags
& BFLAGS_Instance
))
3831 if (!(bflags
& BFLAGS_NonPublic
))
3834 g_free (event_name
);
3835 return mono_event_get_object (domain
, startklass
, event
);
3838 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3841 g_free (event_name
);
3846 ves_icall_Type_GetEvents_internal (MonoReflectionType
*type
, guint32 bflags
, MonoReflectionType
*reftype
)
3849 static MonoClass
*System_Reflection_EventInfo
;
3850 MonoClass
*startklass
, *klass
;
3857 MonoPtrArray tmp_array
;
3859 MONO_ARCH_SAVE_REGS
;
3861 mono_ptr_array_init (tmp_array
, 4);
3863 if (!System_Reflection_EventInfo
)
3864 System_Reflection_EventInfo
= mono_class_from_name (
3865 mono_defaults
.corlib
, "System.Reflection", "EventInfo");
3867 domain
= mono_object_domain (type
);
3868 if (type
->type
->byref
)
3869 return mono_array_new_cached (domain
, System_Reflection_EventInfo
, 0);
3870 klass
= startklass
= mono_class_from_mono_type (type
->type
);
3871 mono_class_init_or_throw (klass
);
3875 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3876 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3879 while ((event
= mono_class_get_events (klass
, &iter
))) {
3881 method
= event
->add
;
3883 method
= event
->remove
;
3885 method
= event
->raise
;
3887 if ((method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) == METHOD_ATTRIBUTE_PUBLIC
) {
3888 if (bflags
& BFLAGS_Public
)
3890 } else if ((klass
== startklass
) || (method
->flags
& METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK
) != METHOD_ATTRIBUTE_PRIVATE
) {
3891 if (bflags
& BFLAGS_NonPublic
)
3896 if (bflags
& BFLAGS_NonPublic
)
3902 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
) {
3903 if (bflags
& BFLAGS_Static
)
3904 if ((bflags
& BFLAGS_FlattenHierarchy
) || (klass
== startklass
))
3907 if (bflags
& BFLAGS_Instance
)
3912 if (bflags
& BFLAGS_Instance
)
3916 mono_ptr_array_append (tmp_array
, mono_event_get_object (domain
, startklass
, event
));
3918 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3921 res
= mono_array_new_cached (domain
, System_Reflection_EventInfo
, mono_ptr_array_size (tmp_array
));
3923 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
3924 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
3926 mono_ptr_array_destroy (tmp_array
);
3931 static MonoReflectionType
*
3932 ves_icall_Type_GetNestedType (MonoReflectionType
*type
, MonoString
*name
, guint32 bflags
)
3940 MONO_ARCH_SAVE_REGS
;
3943 mono_raise_exception (mono_get_exception_argument_null ("name"));
3945 domain
= ((MonoObject
*)type
)->vtable
->domain
;
3946 if (type
->type
->byref
)
3948 klass
= mono_class_from_mono_type (type
->type
);
3949 mono_class_init_or_throw (klass
);
3951 str
= mono_string_to_utf8 (name
);
3954 if (klass
->exception_type
!= MONO_EXCEPTION_NONE
)
3955 mono_raise_exception (mono_class_get_exception_for_failure (klass
));
3958 * If a nested type is generic, return its generic type definition.
3959 * Note that this means that the return value is essentially a
3960 * nested type of the generic type definition of @klass.
3962 * A note in MSDN claims that a generic type definition can have
3963 * nested types that aren't generic. In any case, the container of that
3964 * nested type would be the generic type definition.
3966 if (klass
->generic_class
)
3967 klass
= klass
->generic_class
->container_class
;
3970 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
3972 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
3973 if (bflags
& BFLAGS_Public
)
3976 if (bflags
& BFLAGS_NonPublic
)
3981 if (strcmp (nested
->name
, str
) == 0){
3983 return mono_type_get_object (domain
, &nested
->byval_arg
);
3986 if (!(bflags
& BFLAGS_DeclaredOnly
) && (klass
= klass
->parent
))
3993 ves_icall_Type_GetNestedTypes (MonoReflectionType
*type
, guint32 bflags
)
4002 MonoPtrArray tmp_array
;
4004 MONO_ARCH_SAVE_REGS
;
4006 domain
= ((MonoObject
*)type
)->vtable
->domain
;
4007 if (type
->type
->byref
)
4008 return mono_array_new (domain
, mono_defaults
.monotype_class
, 0);
4009 klass
= mono_class_from_mono_type (type
->type
);
4010 mono_class_init_or_throw (klass
);
4013 * If a nested type is generic, return its generic type definition.
4014 * Note that this means that the return value is essentially the set
4015 * of nested types of the generic type definition of @klass.
4017 * A note in MSDN claims that a generic type definition can have
4018 * nested types that aren't generic. In any case, the container of that
4019 * nested type would be the generic type definition.
4021 if (klass
->generic_class
)
4022 klass
= klass
->generic_class
->container_class
;
4024 mono_ptr_array_init (tmp_array
, 1);
4026 while ((nested
= mono_class_get_nested_types (klass
, &iter
))) {
4028 if ((nested
->flags
& TYPE_ATTRIBUTE_VISIBILITY_MASK
) == TYPE_ATTRIBUTE_NESTED_PUBLIC
) {
4029 if (bflags
& BFLAGS_Public
)
4032 if (bflags
& BFLAGS_NonPublic
)
4037 member
= (MonoObject
*)mono_type_get_object (domain
, &nested
->byval_arg
);
4038 mono_ptr_array_append (tmp_array
, member
);
4041 res
= mono_array_new_cached (domain
, mono_defaults
.monotype_class
, mono_ptr_array_size (tmp_array
));
4043 for (i
= 0; i
< mono_ptr_array_size (tmp_array
); ++i
)
4044 mono_array_setref (res
, i
, mono_ptr_array_get (tmp_array
, i
));
4046 mono_ptr_array_destroy (tmp_array
);
4051 static MonoReflectionType
*
4052 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly
*assembly
, MonoReflectionModule
*module
, MonoString
*name
, MonoBoolean throwOnError
, MonoBoolean ignoreCase
)
4055 MonoType
*type
= NULL
;
4056 MonoTypeNameParse info
;
4057 gboolean type_resolve
;
4059 MONO_ARCH_SAVE_REGS
;
4061 /* On MS.NET, this does not fire a TypeResolve event */
4062 type_resolve
= TRUE
;
4063 str
= mono_string_to_utf8 (name
);
4064 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4065 if (!mono_reflection_parse_type (str
, &info
)) {
4067 mono_reflection_free_type_info (&info
);
4068 if (throwOnError
) /* uhm: this is a parse error, though... */
4069 mono_raise_exception (mono_get_exception_type_load (name
, NULL
));
4070 /*g_print ("failed parse\n");*/
4074 if (info
.assembly
.name
) {
4076 mono_reflection_free_type_info (&info
);
4078 /* 1.0 and 2.0 throw different exceptions */
4079 if (mono_defaults
.generic_ilist_class
)
4080 mono_raise_exception (mono_get_exception_argument (NULL
, "Type names passed to Assembly.GetType() must not specify an assembly."));
4082 mono_raise_exception (mono_get_exception_type_load (name
, NULL
));
4087 if (module
!= NULL
) {
4089 type
= mono_reflection_get_type (module
->image
, &info
, ignoreCase
, &type_resolve
);
4094 if (assembly
->assembly
->dynamic
) {
4095 /* Enumerate all modules */
4096 MonoReflectionAssemblyBuilder
*abuilder
= (MonoReflectionAssemblyBuilder
*)assembly
;
4100 if (abuilder
->modules
) {
4101 for (i
= 0; i
< mono_array_length (abuilder
->modules
); ++i
) {
4102 MonoReflectionModuleBuilder
*mb
= mono_array_get (abuilder
->modules
, MonoReflectionModuleBuilder
*, i
);
4103 type
= mono_reflection_get_type (&mb
->dynamic_image
->image
, &info
, ignoreCase
, &type_resolve
);
4109 if (!type
&& abuilder
->loaded_modules
) {
4110 for (i
= 0; i
< mono_array_length (abuilder
->loaded_modules
); ++i
) {
4111 MonoReflectionModule
*mod
= mono_array_get (abuilder
->loaded_modules
, MonoReflectionModule
*, i
);
4112 type
= mono_reflection_get_type (mod
->image
, &info
, ignoreCase
, &type_resolve
);
4119 type
= mono_reflection_get_type (assembly
->assembly
->image
, &info
, ignoreCase
, &type_resolve
);
4121 mono_reflection_free_type_info (&info
);
4123 MonoException
*e
= NULL
;
4126 e
= mono_get_exception_type_load (name
, NULL
);
4128 if (mono_loader_get_last_error () && mono_defaults
.generic_ilist_class
)
4129 e
= mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4131 mono_loader_clear_error ();
4134 mono_raise_exception (e
);
4139 if (type
->type
== MONO_TYPE_CLASS
) {
4140 MonoClass
*klass
= mono_type_get_class (type
);
4142 if (mono_is_security_manager_active () && !klass
->exception_type
)
4143 /* Some security problems are detected during generic vtable construction */
4144 mono_class_setup_vtable (klass
);
4145 /* need to report exceptions ? */
4146 if (throwOnError
&& klass
->exception_type
) {
4147 /* report SecurityException (or others) that occured when loading the assembly */
4148 MonoException
*exc
= mono_class_get_exception_for_failure (klass
);
4149 mono_loader_clear_error ();
4150 mono_raise_exception (exc
);
4151 } else if (klass
->exception_type
== MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND
) {
4156 /* g_print ("got it\n"); */
4157 return mono_type_get_object (mono_object_domain (assembly
), type
);
4161 replace_shadow_path (MonoDomain
*domain
, gchar
*dirname
, gchar
**filename
)
4164 gchar
*shadow_ini_file
;
4167 /* Check for shadow-copied assembly */
4168 if (mono_is_shadow_copy_enabled (domain
, dirname
)) {
4169 shadow_ini_file
= g_build_filename (dirname
, "__AssemblyInfo__.ini", NULL
);
4171 if (!g_file_get_contents (shadow_ini_file
, &content
, &len
, NULL
) ||
4172 !g_file_test (content
, G_FILE_TEST_IS_REGULAR
)) {
4178 g_free (shadow_ini_file
);
4179 if (content
!= NULL
) {
4182 *filename
= content
;
4190 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly
*assembly
, MonoBoolean escaped
)
4192 MonoDomain
*domain
= mono_object_domain (assembly
);
4193 MonoAssembly
*mass
= assembly
->assembly
;
4194 MonoString
*res
= NULL
;
4199 MONO_ARCH_SAVE_REGS
;
4201 if (g_path_is_absolute (mass
->image
->name
)) {
4202 absolute
= g_strdup (mass
->image
->name
);
4203 dirname
= g_path_get_dirname (absolute
);
4205 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
4206 dirname
= g_strdup (mass
->basedir
);
4209 replace_shadow_path (domain
, dirname
, &absolute
);
4214 for (i
= strlen (absolute
) - 1; i
>= 0; i
--)
4215 if (absolute
[i
] == '\\')
4220 uri
= g_filename_to_uri (absolute
, NULL
, NULL
);
4222 const char *prepend
= "file://";
4224 if (*absolute
== '/' && *(absolute
+ 1) == '/') {
4227 prepend
= "file:///";
4230 uri
= g_strconcat (prepend
, absolute
, NULL
);
4234 res
= mono_string_new (domain
, uri
);
4242 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly
*assembly
)
4244 MonoAssembly
*mass
= assembly
->assembly
;
4246 MONO_ARCH_SAVE_REGS
;
4248 return mass
->in_gac
;
4251 static MonoReflectionAssembly
*
4252 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString
*mname
, MonoObject
*evidence
)
4256 MonoImageOpenStatus status
;
4258 MONO_ARCH_SAVE_REGS
;
4260 name
= mono_string_to_utf8 (mname
);
4261 res
= mono_assembly_load_with_partial_name (name
, &status
);
4267 return mono_assembly_get_object (mono_domain_get (), res
);
4271 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly
*assembly
)
4273 MonoDomain
*domain
= mono_object_domain (assembly
);
4276 MONO_ARCH_SAVE_REGS
;
4278 res
= mono_string_new (domain
, mono_image_get_filename (assembly
->assembly
->image
));
4284 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly
*assembly
)
4286 MONO_ARCH_SAVE_REGS
;
4288 return assembly
->assembly
->ref_only
;
4292 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly
*assembly
)
4294 MonoDomain
*domain
= mono_object_domain (assembly
);
4296 MONO_ARCH_SAVE_REGS
;
4298 return mono_string_new (domain
, assembly
->assembly
->image
->version
);
4301 static MonoReflectionMethod
*
4302 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly
*assembly
)
4304 guint32 token
= mono_image_get_entry_point (assembly
->assembly
->image
);
4306 MONO_ARCH_SAVE_REGS
;
4310 return mono_method_get_object (mono_object_domain (assembly
), mono_get_method (assembly
->assembly
->image
, token
, NULL
), NULL
);
4313 static MonoReflectionModule
*
4314 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly
*assembly
)
4316 return mono_module_get_object (mono_object_domain (assembly
), assembly
->assembly
->image
);
4320 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly
*assembly
)
4322 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4323 MonoArray
*result
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, table
->rows
);
4327 MONO_ARCH_SAVE_REGS
;
4329 for (i
= 0; i
< table
->rows
; ++i
) {
4330 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_MANIFEST_NAME
));
4331 mono_array_setref (result
, i
, mono_string_new (mono_object_domain (assembly
), val
));
4337 create_version (MonoDomain
*domain
, guint32 major
, guint32 minor
, guint32 build
, guint32 revision
)
4339 static MonoClass
*System_Version
= NULL
;
4340 static MonoMethod
*create_version
= NULL
;
4344 if (!System_Version
) {
4345 System_Version
= mono_class_from_name (mono_defaults
.corlib
, "System", "Version");
4346 g_assert (System_Version
);
4349 if (!create_version
) {
4350 MonoMethodDesc
*desc
= mono_method_desc_new (":.ctor(int,int,int,int)", FALSE
);
4351 create_version
= mono_method_desc_search_in_class (desc
, System_Version
);
4352 g_assert (create_version
);
4353 mono_method_desc_free (desc
);
4359 args
[3] = &revision
;
4360 result
= mono_object_new (domain
, System_Version
);
4361 mono_runtime_invoke (create_version
, result
, args
, NULL
);
4367 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly
*assembly
)
4369 static MonoClass
*System_Reflection_AssemblyName
;
4371 MonoDomain
*domain
= mono_object_domain (assembly
);
4373 static MonoMethod
*create_culture
= NULL
;
4374 MonoImage
*image
= assembly
->assembly
->image
;
4377 MONO_ARCH_SAVE_REGS
;
4379 if (!System_Reflection_AssemblyName
)
4380 System_Reflection_AssemblyName
= mono_class_from_name (
4381 mono_defaults
.corlib
, "System.Reflection", "AssemblyName");
4383 t
= &assembly
->assembly
->image
->tables
[MONO_TABLE_ASSEMBLYREF
];
4386 result
= mono_array_new (domain
, System_Reflection_AssemblyName
, count
);
4388 if (count
> 0 && !create_culture
) {
4389 MonoMethodDesc
*desc
= mono_method_desc_new (
4390 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4391 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4392 g_assert (create_culture
);
4393 mono_method_desc_free (desc
);
4396 for (i
= 0; i
< count
; i
++) {
4397 MonoReflectionAssemblyName
*aname
;
4398 guint32 cols
[MONO_ASSEMBLYREF_SIZE
];
4400 mono_metadata_decode_row (t
, i
, cols
, MONO_ASSEMBLYREF_SIZE
);
4402 aname
= (MonoReflectionAssemblyName
*) mono_object_new (
4403 domain
, System_Reflection_AssemblyName
);
4405 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_NAME
])));
4407 aname
->major
= cols
[MONO_ASSEMBLYREF_MAJOR_VERSION
];
4408 aname
->minor
= cols
[MONO_ASSEMBLYREF_MINOR_VERSION
];
4409 aname
->build
= cols
[MONO_ASSEMBLYREF_BUILD_NUMBER
];
4410 aname
->revision
= cols
[MONO_ASSEMBLYREF_REV_NUMBER
];
4411 aname
->flags
= cols
[MONO_ASSEMBLYREF_FLAGS
];
4412 aname
->versioncompat
= 1; /* SameMachine (default) */
4413 aname
->hashalg
= ASSEMBLY_HASH_SHA1
; /* SHA1 (default) */
4414 MONO_OBJECT_SETREF (aname
, version
, create_version (domain
, aname
->major
, aname
->minor
, aname
->build
, aname
->revision
));
4416 if (create_culture
) {
4418 MonoBoolean assembly_ref
= 1;
4419 args
[0] = mono_string_new (domain
, mono_metadata_string_heap (image
, cols
[MONO_ASSEMBLYREF_CULTURE
]));
4420 args
[1] = &assembly_ref
;
4421 MONO_OBJECT_SETREF (aname
, cultureInfo
, mono_runtime_invoke (create_culture
, NULL
, args
, NULL
));
4424 if (cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]) {
4425 const gchar
*pkey_ptr
= mono_metadata_blob_heap (image
, cols
[MONO_ASSEMBLYREF_PUBLIC_KEY
]);
4426 guint32 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
4428 if ((cols
[MONO_ASSEMBLYREF_FLAGS
] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
)) {
4429 /* public key token isn't copied - the class library will
4430 automatically generate it from the public key if required */
4431 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4432 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
4434 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4435 memcpy (mono_array_addr (aname
->keyToken
, guint8
, 0), pkey_ptr
, pkey_len
);
4438 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
4441 /* note: this function doesn't return the codebase on purpose (i.e. it can
4442 be used under partial trust as path information isn't present). */
4444 mono_array_setref (result
, i
, aname
);
4455 foreach_namespace (const char* key
, gconstpointer val
, NameSpaceInfo
*info
)
4457 MonoString
*name
= mono_string_new (mono_object_domain (info
->res
), key
);
4459 mono_array_setref (info
->res
, info
->idx
, name
);
4464 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly
*assembly
)
4466 MonoImage
*img
= assembly
->assembly
->image
;
4471 MONO_ARCH_SAVE_REGS
;
4473 mono_image_lock (img
);
4474 mono_image_init_name_cache (img
);
4477 len
= g_hash_table_size (img
->name_cache
);
4478 mono_image_unlock (img
);
4480 /*we can't create objects holding the image lock */
4481 res
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, len
);
4483 mono_image_lock (img
);
4484 /*len might have changed, create a new array*/
4485 if (len
!= g_hash_table_size (img
->name_cache
))
4490 g_hash_table_foreach (img
->name_cache
, (GHFunc
)foreach_namespace
, &info
);
4491 mono_image_unlock (img
);
4496 /* move this in some file in mono/util/ */
4498 g_concat_dir_and_file (const char *dir
, const char *file
)
4500 g_return_val_if_fail (dir
!= NULL
, NULL
);
4501 g_return_val_if_fail (file
!= NULL
, NULL
);
4504 * If the directory name doesn't have a / on the end, we need
4505 * to add one so we get a proper path to the file
4507 if (dir
[strlen(dir
) - 1] != G_DIR_SEPARATOR
)
4508 return g_strconcat (dir
, G_DIR_SEPARATOR_S
, file
, NULL
);
4510 return g_strconcat (dir
, file
, NULL
);
4514 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, gint32
*size
, MonoReflectionModule
**ref_module
)
4516 char *n
= mono_string_to_utf8 (name
);
4517 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4519 guint32 cols
[MONO_MANIFEST_SIZE
];
4520 guint32 impl
, file_idx
;
4524 MONO_ARCH_SAVE_REGS
;
4526 for (i
= 0; i
< table
->rows
; ++i
) {
4527 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
4528 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
4529 if (strcmp (val
, n
) == 0)
4533 if (i
== table
->rows
)
4536 impl
= cols
[MONO_MANIFEST_IMPLEMENTATION
];
4539 * this code should only be called after obtaining the
4540 * ResourceInfo and handling the other cases.
4542 g_assert ((impl
& MONO_IMPLEMENTATION_MASK
) == MONO_IMPLEMENTATION_FILE
);
4543 file_idx
= impl
>> MONO_IMPLEMENTATION_BITS
;
4545 module
= mono_image_load_file_for_image (assembly
->assembly
->image
, file_idx
);
4550 module
= assembly
->assembly
->image
;
4552 mono_gc_wbarrier_generic_store (ref_module
, (MonoObject
*) mono_module_get_object (mono_domain_get (), module
));
4554 return (void*)mono_image_get_resource (module
, cols
[MONO_MANIFEST_OFFSET
], (guint32
*)size
);
4558 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoManifestResourceInfo
*info
)
4560 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_MANIFESTRESOURCE
];
4562 guint32 cols
[MONO_MANIFEST_SIZE
];
4563 guint32 file_cols
[MONO_FILE_SIZE
];
4567 MONO_ARCH_SAVE_REGS
;
4569 n
= mono_string_to_utf8 (name
);
4570 for (i
= 0; i
< table
->rows
; ++i
) {
4571 mono_metadata_decode_row (table
, i
, cols
, MONO_MANIFEST_SIZE
);
4572 val
= mono_metadata_string_heap (assembly
->assembly
->image
, cols
[MONO_MANIFEST_NAME
]);
4573 if (strcmp (val
, n
) == 0)
4577 if (i
== table
->rows
)
4580 if (!cols
[MONO_MANIFEST_IMPLEMENTATION
]) {
4581 info
->location
= RESOURCE_LOCATION_EMBEDDED
| RESOURCE_LOCATION_IN_MANIFEST
;
4584 switch (cols
[MONO_MANIFEST_IMPLEMENTATION
] & MONO_IMPLEMENTATION_MASK
) {
4585 case MONO_IMPLEMENTATION_FILE
:
4586 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
4587 table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
4588 mono_metadata_decode_row (table
, i
- 1, file_cols
, MONO_FILE_SIZE
);
4589 val
= mono_metadata_string_heap (assembly
->assembly
->image
, file_cols
[MONO_FILE_NAME
]);
4590 MONO_OBJECT_SETREF (info
, filename
, mono_string_new (mono_object_domain (assembly
), val
));
4591 if (file_cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
4594 info
->location
= RESOURCE_LOCATION_EMBEDDED
;
4597 case MONO_IMPLEMENTATION_ASSEMBLYREF
:
4598 i
= cols
[MONO_MANIFEST_IMPLEMENTATION
] >> MONO_IMPLEMENTATION_BITS
;
4599 mono_assembly_load_reference (assembly
->assembly
->image
, i
- 1);
4600 if (assembly
->assembly
->image
->references
[i
- 1] == (gpointer
)-1) {
4601 char *msg
= g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i
- 1, assembly
->assembly
->image
->name
);
4602 MonoException
*ex
= mono_get_exception_file_not_found2 (msg
, NULL
);
4604 mono_raise_exception (ex
);
4606 MONO_OBJECT_SETREF (info
, assembly
, mono_assembly_get_object (mono_domain_get (), assembly
->assembly
->image
->references
[i
- 1]));
4608 /* Obtain info recursively */
4609 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info
->assembly
, name
, info
);
4610 info
->location
|= RESOURCE_LOCATION_ANOTHER_ASSEMBLY
;
4613 case MONO_IMPLEMENTATION_EXP_TYPE
:
4614 g_assert_not_reached ();
4623 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly
*assembly
, MonoString
*name
, MonoBoolean resource_modules
)
4625 MonoTableInfo
*table
= &assembly
->assembly
->image
->tables
[MONO_TABLE_FILE
];
4626 MonoArray
*result
= NULL
;
4631 MONO_ARCH_SAVE_REGS
;
4633 /* check hash if needed */
4635 n
= mono_string_to_utf8 (name
);
4636 for (i
= 0; i
< table
->rows
; ++i
) {
4637 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
4638 if (strcmp (val
, n
) == 0) {
4641 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
4642 fn
= mono_string_new (mono_object_domain (assembly
), n
);
4644 return (MonoObject
*)fn
;
4652 for (i
= 0; i
< table
->rows
; ++i
) {
4653 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
))
4657 result
= mono_array_new (mono_object_domain (assembly
), mono_defaults
.string_class
, count
);
4660 for (i
= 0; i
< table
->rows
; ++i
) {
4661 if (resource_modules
|| !(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
4662 val
= mono_metadata_string_heap (assembly
->assembly
->image
, mono_metadata_decode_row_col (table
, i
, MONO_FILE_NAME
));
4663 n
= g_concat_dir_and_file (assembly
->assembly
->basedir
, val
);
4664 mono_array_setref (result
, count
, mono_string_new (mono_object_domain (assembly
), n
));
4669 return (MonoObject
*)result
;
4673 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly
*assembly
)
4675 MonoDomain
*domain
= mono_domain_get();
4678 int i
, j
, file_count
= 0;
4679 MonoImage
**modules
;
4680 guint32 module_count
, real_module_count
;
4681 MonoTableInfo
*table
;
4682 guint32 cols
[MONO_FILE_SIZE
];
4683 MonoImage
*image
= assembly
->assembly
->image
;
4685 g_assert (image
!= NULL
);
4686 g_assert (!assembly
->assembly
->dynamic
);
4688 table
= &image
->tables
[MONO_TABLE_FILE
];
4689 file_count
= table
->rows
;
4691 modules
= image
->modules
;
4692 module_count
= image
->module_count
;
4694 real_module_count
= 0;
4695 for (i
= 0; i
< module_count
; ++i
)
4697 real_module_count
++;
4699 klass
= mono_class_from_name (mono_defaults
.corlib
, "System.Reflection", "Module");
4700 res
= mono_array_new (domain
, klass
, 1 + real_module_count
+ file_count
);
4702 mono_array_setref (res
, 0, mono_module_get_object (domain
, image
));
4704 for (i
= 0; i
< module_count
; ++i
)
4706 mono_array_setref (res
, j
, mono_module_get_object (domain
, modules
[i
]));
4710 for (i
= 0; i
< file_count
; ++i
, ++j
) {
4711 mono_metadata_decode_row (table
, i
, cols
, MONO_FILE_SIZE
);
4712 if (cols
[MONO_FILE_FLAGS
] && FILE_CONTAINS_NO_METADATA
)
4713 mono_array_setref (res
, j
, mono_module_file_get_object (domain
, image
, i
));
4715 MonoImage
*m
= mono_image_load_file_for_image (image
, i
+ 1);
4717 MonoString
*fname
= mono_string_new (mono_domain_get (), mono_metadata_string_heap (image
, cols
[MONO_FILE_NAME
]));
4718 mono_raise_exception (mono_get_exception_file_not_found2 (NULL
, fname
));
4720 mono_array_setref (res
, j
, mono_module_get_object (domain
, m
));
4727 static MonoReflectionMethod
*
4728 ves_icall_GetCurrentMethod (void)
4730 MonoMethod
*m
= mono_method_get_last_managed ();
4732 while (m
->is_inflated
)
4733 m
= ((MonoMethodInflated
*)m
)->declaring
;
4735 return mono_method_get_object (mono_domain_get (), m
, NULL
);
4740 mono_method_get_equivalent_method (MonoMethod
*method
, MonoClass
*klass
)
4743 if (method
->is_inflated
&& ((MonoMethodInflated
*)method
)->context
.method_inst
) {
4744 MonoMethodInflated
*inflated
= (MonoMethodInflated
*)method
;
4745 //method is inflated, we should inflate it on the other class
4746 MonoGenericContext ctx
;
4747 ctx
.method_inst
= inflated
->context
.method_inst
;
4748 ctx
.class_inst
= inflated
->context
.class_inst
;
4749 if (klass
->generic_class
)
4750 ctx
.class_inst
= klass
->generic_class
->context
.class_inst
;
4751 else if (klass
->generic_container
)
4752 ctx
.class_inst
= klass
->generic_container
->context
.class_inst
;
4753 return mono_class_inflate_generic_method_full (inflated
->declaring
, klass
, &ctx
);
4756 mono_class_setup_methods (method
->klass
);
4757 if (method
->klass
->exception_type
)
4759 for (i
= 0; i
< method
->klass
->method
.count
; ++i
) {
4760 if (method
->klass
->methods
[i
] == method
) {
4765 mono_class_setup_methods (klass
);
4766 if (klass
->exception_type
)
4768 g_assert (offset
>= 0 && offset
< klass
->method
.count
);
4769 return klass
->methods
[offset
];
4772 static MonoReflectionMethod
*
4773 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod
*method
, MonoType
*type
)
4777 klass
= mono_class_from_mono_type (type
);
4778 if (mono_class_get_generic_type_definition (method
->klass
) != mono_class_get_generic_type_definition (klass
))
4780 if (method
->klass
!= klass
) {
4781 method
= mono_method_get_equivalent_method (method
, klass
);
4786 klass
= method
->klass
;
4787 return mono_method_get_object (mono_domain_get (), method
, klass
);
4790 static MonoReflectionMethod
*
4791 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod
*method
)
4793 return mono_method_get_object (mono_domain_get (), method
, NULL
);
4796 static MonoReflectionMethodBody
*
4797 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod
*method
)
4799 return mono_method_body_get_object (mono_domain_get (), method
);
4802 static MonoReflectionAssembly
*
4803 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4805 MonoMethod
*dest
= NULL
;
4807 MONO_ARCH_SAVE_REGS
;
4809 mono_stack_walk_no_il (get_executing
, &dest
);
4810 return mono_assembly_get_object (mono_domain_get (), dest
->klass
->image
->assembly
);
4814 static MonoReflectionAssembly
*
4815 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4817 MonoDomain
* domain
= mono_domain_get ();
4819 MONO_ARCH_SAVE_REGS
;
4821 if (!domain
->entry_assembly
)
4824 return mono_assembly_get_object (domain
, domain
->entry_assembly
);
4827 static MonoReflectionAssembly
*
4828 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4833 MONO_ARCH_SAVE_REGS
;
4836 mono_stack_walk_no_il (get_executing
, &dest
);
4838 mono_stack_walk_no_il (get_caller
, &dest
);
4841 return mono_assembly_get_object (mono_domain_get (), dest
->klass
->image
->assembly
);
4845 ves_icall_System_MonoType_getFullName (MonoReflectionType
*object
, gboolean full_name
,
4846 gboolean assembly_qualified
)
4848 MonoDomain
*domain
= mono_object_domain (object
);
4849 MonoTypeNameFormat format
;
4854 format
= assembly_qualified
?
4855 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
:
4856 MONO_TYPE_NAME_FORMAT_FULL_NAME
;
4858 format
= MONO_TYPE_NAME_FORMAT_REFLECTION
;
4860 name
= mono_type_get_name_full (object
->type
, format
);
4864 if (full_name
&& (object
->type
->type
== MONO_TYPE_VAR
|| object
->type
->type
== MONO_TYPE_MVAR
)) {
4869 res
= mono_string_new (domain
, name
);
4876 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType
*this)
4878 MonoClass
*klass
= mono_class_from_mono_type (this->type
);
4879 mono_class_init_or_throw (klass
);
4880 return mono_security_core_clr_class_level (klass
);
4884 fill_reflection_assembly_name (MonoDomain
*domain
, MonoReflectionAssemblyName
*aname
, MonoAssemblyName
*name
, const char *absolute
, gboolean by_default_version
, gboolean default_publickey
, gboolean default_token
)
4886 static MonoMethod
*create_culture
= NULL
;
4889 const char *pkey_ptr
;
4891 MonoBoolean assembly_ref
= 0;
4893 MONO_ARCH_SAVE_REGS
;
4895 MONO_OBJECT_SETREF (aname
, name
, mono_string_new (domain
, name
->name
));
4896 aname
->major
= name
->major
;
4897 aname
->minor
= name
->minor
;
4898 aname
->build
= name
->build
;
4899 aname
->flags
= name
->flags
;
4900 aname
->revision
= name
->revision
;
4901 aname
->hashalg
= name
->hash_alg
;
4902 aname
->versioncompat
= 1; /* SameMachine (default) */
4904 if (by_default_version
)
4905 MONO_OBJECT_SETREF (aname
, version
, create_version (domain
, name
->major
, name
->minor
, name
->build
, name
->revision
));
4908 if (absolute
!= NULL
&& *absolute
!= '\0') {
4909 const gchar
*prepend
= "file://";
4912 codebase
= g_strdup (absolute
);
4917 for (i
= strlen (codebase
) - 1; i
>= 0; i
--)
4918 if (codebase
[i
] == '\\')
4921 if (*codebase
== '/' && *(codebase
+ 1) == '/') {
4924 prepend
= "file:///";
4928 result
= g_strconcat (prepend
, codebase
, NULL
);
4934 MONO_OBJECT_SETREF (aname
, codebase
, mono_string_new (domain
, codebase
));
4938 if (!create_culture
) {
4939 MonoMethodDesc
*desc
= mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE
);
4940 create_culture
= mono_method_desc_search_in_image (desc
, mono_defaults
.corlib
);
4941 g_assert (create_culture
);
4942 mono_method_desc_free (desc
);
4945 if (name
->culture
) {
4946 args
[0] = mono_string_new (domain
, name
->culture
);
4947 args
[1] = &assembly_ref
;
4948 MONO_OBJECT_SETREF (aname
, cultureInfo
, mono_runtime_invoke (create_culture
, NULL
, args
, NULL
));
4951 if (name
->public_key
) {
4952 pkey_ptr
= (char*)name
->public_key
;
4953 pkey_len
= mono_metadata_decode_blob_size (pkey_ptr
, &pkey_ptr
);
4955 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, pkey_len
));
4956 memcpy (mono_array_addr (aname
->publicKey
, guint8
, 0), pkey_ptr
, pkey_len
);
4957 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
4958 } else if (default_publickey
) {
4959 MONO_OBJECT_SETREF (aname
, publicKey
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
4960 aname
->flags
|= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG
;
4963 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4964 if (name
->public_key_token
[0]) {
4968 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 8));
4969 p
= mono_array_addr (aname
->keyToken
, char, 0);
4971 for (i
= 0, j
= 0; i
< 8; i
++) {
4972 *p
= g_ascii_xdigit_value (name
->public_key_token
[j
++]) << 4;
4973 *p
|= g_ascii_xdigit_value (name
->public_key_token
[j
++]);
4976 } else if (default_token
) {
4977 MONO_OBJECT_SETREF (aname
, keyToken
, mono_array_new (domain
, mono_defaults
.byte_class
, 0));
4982 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly
*assembly
)
4984 MonoDomain
*domain
= mono_object_domain (assembly
);
4985 MonoAssembly
*mass
= assembly
->assembly
;
4989 name
= g_strdup_printf (
4990 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4992 mass
->aname
.major
, mass
->aname
.minor
, mass
->aname
.build
, mass
->aname
.revision
,
4993 mass
->aname
.culture
&& *mass
->aname
.culture
? mass
->aname
.culture
: "neutral",
4994 mass
->aname
.public_key_token
[0] ? (char *)mass
->aname
.public_key_token
: "null",
4995 (mass
->aname
.flags
& ASSEMBLYREF_RETARGETABLE_FLAG
) ? ", Retargetable=Yes" : "");
4997 res
= mono_string_new (domain
, name
);
5004 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly
*assembly
, MonoReflectionAssemblyName
*aname
)
5007 MonoAssembly
*mass
= assembly
->assembly
;
5009 MONO_ARCH_SAVE_REGS
;
5011 if (g_path_is_absolute (mass
->image
->name
)) {
5012 fill_reflection_assembly_name (mono_object_domain (assembly
),
5013 aname
, &mass
->aname
, mass
->image
->name
, TRUE
,
5017 absolute
= g_build_filename (mass
->basedir
, mass
->image
->name
, NULL
);
5019 fill_reflection_assembly_name (mono_object_domain (assembly
),
5020 aname
, &mass
->aname
, absolute
, TRUE
, TRUE
,
5027 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString
*fname
, MonoReflectionAssemblyName
*aname
)
5030 MonoImageOpenStatus status
= MONO_IMAGE_OK
;
5033 MonoAssemblyName name
;
5036 MONO_ARCH_SAVE_REGS
;
5038 filename
= mono_string_to_utf8 (fname
);
5040 dirname
= g_path_get_dirname (filename
);
5041 replace_shadow_path (mono_domain_get (), dirname
, &filename
);
5044 image
= mono_image_open (filename
, &status
);
5050 if (status
== MONO_IMAGE_IMAGE_INVALID
)
5051 exc
= mono_get_exception_bad_image_format2 (NULL
, fname
);
5053 exc
= mono_get_exception_file_not_found2 (NULL
, fname
);
5054 mono_raise_exception (exc
);
5057 res
= mono_assembly_fill_assembly_name (image
, &name
);
5059 mono_image_close (image
);
5061 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5064 fill_reflection_assembly_name (mono_domain_get (), aname
, &name
, filename
,
5068 mono_image_close (image
);
5072 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly
*assembly
,
5073 char **minimum
, guint32
*minLength
, char **optional
, guint32
*optLength
, char **refused
, guint32
*refLength
)
5075 MonoBoolean result
= FALSE
;
5076 MonoDeclSecurityEntry entry
;
5078 /* SecurityAction.RequestMinimum */
5079 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQMIN
, &entry
)) {
5080 *minimum
= entry
.blob
;
5081 *minLength
= entry
.size
;
5084 /* SecurityAction.RequestOptional */
5085 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQOPT
, &entry
)) {
5086 *optional
= entry
.blob
;
5087 *optLength
= entry
.size
;
5090 /* SecurityAction.RequestRefuse */
5091 if (mono_declsec_get_assembly_action (assembly
->assembly
, SECURITY_ACTION_REQREFUSE
, &entry
)) {
5092 *refused
= entry
.blob
;
5093 *refLength
= entry
.size
;
5101 mono_module_get_types (MonoDomain
*domain
, MonoImage
*image
, MonoArray
**exceptions
, MonoBoolean exportedOnly
)
5105 MonoTableInfo
*tdef
= &image
->tables
[MONO_TABLE_TYPEDEF
];
5107 guint32 attrs
, visibility
;
5109 /* we start the count from 1 because we skip the special type <Module> */
5112 for (i
= 1; i
< tdef
->rows
; ++i
) {
5113 attrs
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEDEF_FLAGS
);
5114 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5115 if (visibility
== TYPE_ATTRIBUTE_PUBLIC
|| visibility
== TYPE_ATTRIBUTE_NESTED_PUBLIC
)
5119 count
= tdef
->rows
- 1;
5121 res
= mono_array_new (domain
, mono_defaults
.monotype_class
, count
);
5122 *exceptions
= mono_array_new (domain
, mono_defaults
.exception_class
, count
);
5124 for (i
= 1; i
< tdef
->rows
; ++i
) {
5125 attrs
= mono_metadata_decode_row_col (tdef
, i
, MONO_TYPEDEF_FLAGS
);
5126 visibility
= attrs
& TYPE_ATTRIBUTE_VISIBILITY_MASK
;
5127 if (!exportedOnly
|| (visibility
== TYPE_ATTRIBUTE_PUBLIC
|| visibility
== TYPE_ATTRIBUTE_NESTED_PUBLIC
)) {
5128 klass
= mono_class_get (image
, (i
+ 1) | MONO_TOKEN_TYPE_DEF
);
5130 mono_array_setref (res
, count
, mono_type_get_object (domain
, &klass
->byval_arg
));
5132 MonoLoaderError
*error
;
5135 error
= mono_loader_get_last_error ();
5136 g_assert (error
!= NULL
);
5138 ex
= mono_loader_error_prepare_exception (error
);
5139 mono_array_setref (*exceptions
, count
, ex
);
5141 if (mono_loader_get_last_error ())
5142 mono_loader_clear_error ();
5151 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly
*assembly
, MonoBoolean exportedOnly
)
5153 MonoArray
*res
= NULL
;
5154 MonoArray
*exceptions
= NULL
;
5155 MonoImage
*image
= NULL
;
5156 MonoTableInfo
*table
= NULL
;
5159 int i
, len
, ex_count
;
5161 MONO_ARCH_SAVE_REGS
;
5163 domain
= mono_object_domain (assembly
);
5165 g_assert (!assembly
->assembly
->dynamic
);
5166 image
= assembly
->assembly
->image
;
5167 table
= &image
->tables
[MONO_TABLE_FILE
];
5168 res
= mono_module_get_types (domain
, image
, &exceptions
, exportedOnly
);
5170 /* Append data from all modules in the assembly */
5171 for (i
= 0; i
< table
->rows
; ++i
) {
5172 if (!(mono_metadata_decode_row_col (table
, i
, MONO_FILE_FLAGS
) & FILE_CONTAINS_NO_METADATA
)) {
5173 MonoImage
*loaded_image
= mono_assembly_load_module (image
->assembly
, i
+ 1);
5176 MonoArray
*res2
= mono_module_get_types (domain
, loaded_image
, &ex2
, exportedOnly
);
5177 /* Append the new types to the end of the array */
5178 if (mono_array_length (res2
) > 0) {
5180 MonoArray
*res3
, *ex3
;
5182 len1
= mono_array_length (res
);
5183 len2
= mono_array_length (res2
);
5185 res3
= mono_array_new (domain
, mono_defaults
.monotype_class
, len1
+ len2
);
5186 mono_array_memcpy_refs (res3
, 0, res
, 0, len1
);
5187 mono_array_memcpy_refs (res3
, len1
, res2
, 0, len2
);
5190 ex3
= mono_array_new (domain
, mono_defaults
.monotype_class
, len1
+ len2
);
5191 mono_array_memcpy_refs (ex3
, 0, exceptions
, 0, len1
);
5192 mono_array_memcpy_refs (ex3
, len1
, ex2
, 0, len2
);
5199 /* the ReflectionTypeLoadException must have all the types (Types property),
5200 * NULL replacing types which throws an exception. The LoaderException must
5201 * contain all exceptions for NULL items.
5204 len
= mono_array_length (res
);
5207 for (i
= 0; i
< len
; i
++) {
5208 MonoReflectionType
*t
= mono_array_get (res
, gpointer
, i
);
5212 klass
= mono_type_get_class (t
->type
);
5213 if ((klass
!= NULL
) && klass
->exception_type
) {
5214 /* keep the class in the list */
5215 list
= g_list_append (list
, klass
);
5216 /* and replace Type with NULL */
5217 mono_array_setref (res
, i
, NULL
);
5224 if (list
|| ex_count
) {
5226 MonoException
*exc
= NULL
;
5227 MonoArray
*exl
= NULL
;
5228 int j
, length
= g_list_length (list
) + ex_count
;
5230 mono_loader_clear_error ();
5232 exl
= mono_array_new (domain
, mono_defaults
.exception_class
, length
);
5233 /* Types for which mono_class_get () succeeded */
5234 for (i
= 0, tmp
= list
; tmp
; i
++, tmp
= tmp
->next
) {
5235 MonoException
*exc
= mono_class_get_exception_for_failure (tmp
->data
);
5236 mono_array_setref (exl
, i
, exc
);
5238 /* Types for which it don't */
5239 for (j
= 0; j
< mono_array_length (exceptions
); ++j
) {
5240 MonoException
*exc
= mono_array_get (exceptions
, MonoException
*, j
);
5242 g_assert (i
< length
);
5243 mono_array_setref (exl
, i
, exc
);
5250 exc
= mono_get_exception_reflection_type_load (res
, exl
);
5251 mono_loader_clear_error ();
5252 mono_raise_exception (exc
);
5259 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName
*name
, MonoString
*assname
)
5261 MonoAssemblyName aname
;
5262 MonoDomain
*domain
= mono_object_domain (name
);
5264 gboolean is_version_defined
;
5265 gboolean is_token_defined
;
5267 aname
.public_key
= NULL
;
5268 val
= mono_string_to_utf8 (assname
);
5269 if (!mono_assembly_name_parse_full (val
, &aname
, TRUE
, &is_version_defined
, &is_token_defined
)) {
5270 g_free ((guint8
*) aname
.public_key
);
5275 fill_reflection_assembly_name (domain
, name
, &aname
, "", is_version_defined
,
5276 FALSE
, is_token_defined
);
5278 mono_assembly_name_free (&aname
);
5279 g_free ((guint8
*) aname
.public_key
);
5285 static MonoReflectionType
*
5286 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule
*module
)
5288 MonoDomain
*domain
= mono_object_domain (module
);
5291 MONO_ARCH_SAVE_REGS
;
5293 g_assert (module
->image
);
5295 if (module
->image
->dynamic
&& ((MonoDynamicImage
*)(module
->image
))->initial_image
)
5296 /* These images do not have a global type */
5299 klass
= mono_class_get (module
->image
, 1 | MONO_TOKEN_TYPE_DEF
);
5300 return mono_type_get_object (domain
, &klass
->byval_arg
);
5304 ves_icall_System_Reflection_Module_Close (MonoReflectionModule
*module
)
5306 /*if (module->image)
5307 mono_image_close (module->image);*/
5311 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule
*module
)
5313 MonoDomain
*domain
= mono_object_domain (module
);
5315 MONO_ARCH_SAVE_REGS
;
5317 g_assert (module
->image
);
5318 return mono_string_new (domain
, module
->image
->guid
);
5322 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule
*module
)
5325 if (module
->image
&& module
->image
->is_module_handle
)
5326 return module
->image
->raw_data
;
5329 return (gpointer
) (-1);
5333 ves_icall_System_Reflection_Module_GetPEKind (MonoImage
*image
, gint32
*pe_kind
, gint32
*machine
)
5335 if (image
->dynamic
) {
5336 MonoDynamicImage
*dyn
= (MonoDynamicImage
*)image
;
5337 *pe_kind
= dyn
->pe_kind
;
5338 *machine
= dyn
->machine
;
5341 *pe_kind
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_cli_header
.ch_flags
& 0x3;
5342 *machine
= ((MonoCLIImageInfo
*)(image
->image_info
))->cli_header
.coff
.coff_machine
;
5347 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage
*image
)
5349 return (image
->md_version_major
<< 16) | (image
->md_version_minor
);
5353 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule
*module
)
5355 MonoArray
*exceptions
;
5358 MONO_ARCH_SAVE_REGS
;
5361 return mono_array_new (mono_object_domain (module
), mono_defaults
.monotype_class
, 0);
5363 MonoArray
*res
= mono_module_get_types (mono_object_domain (module
), module
->image
, &exceptions
, FALSE
);
5364 for (i
= 0; i
< mono_array_length (exceptions
); ++i
) {
5365 MonoException
*ex
= mono_array_get (exceptions
, MonoException
*, i
);
5367 mono_raise_exception (ex
);
5374 mono_metadata_memberref_is_method (MonoImage
*image
, guint32 token
)
5376 guint32 cols
[MONO_MEMBERREF_SIZE
];
5378 mono_metadata_decode_row (&image
->tables
[MONO_TABLE_MEMBERREF
], mono_metadata_token_index (token
) - 1, cols
, MONO_MEMBERREF_SIZE
);
5379 sig
= mono_metadata_blob_heap (image
, cols
[MONO_MEMBERREF_SIGNATURE
]);
5380 mono_metadata_decode_blob_size (sig
, &sig
);
5381 return (*sig
!= 0x6);
5385 init_generic_context_from_args (MonoGenericContext
*context
, MonoArray
*type_args
, MonoArray
*method_args
)
5388 context
->class_inst
= mono_metadata_get_generic_inst (mono_array_length (type_args
),
5389 mono_array_addr (type_args
, MonoType
*, 0));
5391 context
->class_inst
= NULL
;
5393 context
->method_inst
= mono_metadata_get_generic_inst (mono_array_length (method_args
),
5394 mono_array_addr (method_args
, MonoType
*, 0));
5396 context
->method_inst
= NULL
;
5400 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5403 int table
= mono_metadata_token_table (token
);
5404 int index
= mono_metadata_token_index (token
);
5405 MonoGenericContext context
;
5407 *error
= ResolveTokenError_Other
;
5409 /* Validate token */
5410 if ((table
!= MONO_TABLE_TYPEDEF
) && (table
!= MONO_TABLE_TYPEREF
) &&
5411 (table
!= MONO_TABLE_TYPESPEC
)) {
5412 *error
= ResolveTokenError_BadTable
;
5416 if (image
->dynamic
) {
5417 if (type_args
|| method_args
)
5418 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5419 klass
= mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5422 return &klass
->byval_arg
;
5425 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5426 *error
= ResolveTokenError_OutOfRange
;
5430 init_generic_context_from_args (&context
, type_args
, method_args
);
5431 klass
= mono_class_get_full (image
, token
, &context
);
5433 if (mono_loader_get_last_error ())
5434 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5437 return &klass
->byval_arg
;
5443 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5445 int table
= mono_metadata_token_table (token
);
5446 int index
= mono_metadata_token_index (token
);
5447 MonoGenericContext context
;
5450 *error
= ResolveTokenError_Other
;
5452 /* Validate token */
5453 if ((table
!= MONO_TABLE_METHOD
) && (table
!= MONO_TABLE_METHODSPEC
) &&
5454 (table
!= MONO_TABLE_MEMBERREF
)) {
5455 *error
= ResolveTokenError_BadTable
;
5459 if (image
->dynamic
) {
5460 if (type_args
|| method_args
)
5461 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5462 /* FIXME: validate memberref token type */
5463 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5466 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5467 *error
= ResolveTokenError_OutOfRange
;
5470 if ((table
== MONO_TABLE_MEMBERREF
) && (!mono_metadata_memberref_is_method (image
, token
))) {
5471 *error
= ResolveTokenError_BadTable
;
5475 init_generic_context_from_args (&context
, type_args
, method_args
);
5476 method
= mono_get_method_full (image
, token
, NULL
, &context
);
5478 if (mono_loader_get_last_error ())
5479 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5485 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*error
)
5487 int index
= mono_metadata_token_index (token
);
5489 *error
= ResolveTokenError_Other
;
5491 /* Validate token */
5492 if (mono_metadata_token_code (token
) != MONO_TOKEN_STRING
) {
5493 *error
= ResolveTokenError_BadTable
;
5498 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5500 if ((index
<= 0) || (index
>= image
->heap_us
.size
)) {
5501 *error
= ResolveTokenError_OutOfRange
;
5505 /* FIXME: What to do if the index points into the middle of a string ? */
5507 return mono_ldstr (mono_domain_get (), image
, index
);
5510 static MonoClassField
*
5511 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5514 int table
= mono_metadata_token_table (token
);
5515 int index
= mono_metadata_token_index (token
);
5516 MonoGenericContext context
;
5517 MonoClassField
*field
;
5519 *error
= ResolveTokenError_Other
;
5521 /* Validate token */
5522 if ((table
!= MONO_TABLE_FIELD
) && (table
!= MONO_TABLE_MEMBERREF
)) {
5523 *error
= ResolveTokenError_BadTable
;
5527 if (image
->dynamic
) {
5528 if (type_args
|| method_args
)
5529 mono_raise_exception (mono_get_exception_not_implemented (NULL
));
5530 /* FIXME: validate memberref token type */
5531 return mono_lookup_dynamic_token_class (image
, token
, FALSE
, NULL
, NULL
);
5534 if ((index
<= 0) || (index
> image
->tables
[table
].rows
)) {
5535 *error
= ResolveTokenError_OutOfRange
;
5538 if ((table
== MONO_TABLE_MEMBERREF
) && (mono_metadata_memberref_is_method (image
, token
))) {
5539 *error
= ResolveTokenError_BadTable
;
5543 init_generic_context_from_args (&context
, type_args
, method_args
);
5544 field
= mono_field_from_token (image
, token
, &klass
, &context
);
5546 if (mono_loader_get_last_error ())
5547 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5554 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage
*image
, guint32 token
, MonoArray
*type_args
, MonoArray
*method_args
, MonoResolveTokenError
*error
)
5556 int table
= mono_metadata_token_table (token
);
5558 *error
= ResolveTokenError_Other
;
5561 case MONO_TABLE_TYPEDEF
:
5562 case MONO_TABLE_TYPEREF
:
5563 case MONO_TABLE_TYPESPEC
: {
5564 MonoType
*t
= ves_icall_System_Reflection_Module_ResolveTypeToken (image
, token
, type_args
, method_args
, error
);
5566 return (MonoObject
*)mono_type_get_object (mono_domain_get (), t
);
5570 case MONO_TABLE_METHOD
:
5571 case MONO_TABLE_METHODSPEC
: {
5572 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
5574 return (MonoObject
*)mono_method_get_object (mono_domain_get (), m
, m
->klass
);
5578 case MONO_TABLE_FIELD
: {
5579 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
5581 return (MonoObject
*)mono_field_get_object (mono_domain_get (), f
->parent
, f
);
5585 case MONO_TABLE_MEMBERREF
:
5586 if (mono_metadata_memberref_is_method (image
, token
)) {
5587 MonoMethod
*m
= ves_icall_System_Reflection_Module_ResolveMethodToken (image
, token
, type_args
, method_args
, error
);
5589 return (MonoObject
*)mono_method_get_object (mono_domain_get (), m
, m
->klass
);
5594 MonoClassField
*f
= ves_icall_System_Reflection_Module_ResolveFieldToken (image
, token
, type_args
, method_args
, error
);
5596 return (MonoObject
*)mono_field_get_object (mono_domain_get (), f
->parent
, f
);
5603 *error
= ResolveTokenError_BadTable
;
5610 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage
*image
, guint32 token
, MonoResolveTokenError
*error
)
5612 int table
= mono_metadata_token_table (token
);
5613 int idx
= mono_metadata_token_index (token
);
5614 MonoTableInfo
*tables
= image
->tables
;
5619 *error
= ResolveTokenError_OutOfRange
;
5621 /* FIXME: Support other tables ? */
5622 if (table
!= MONO_TABLE_STANDALONESIG
)
5628 if ((idx
== 0) || (idx
> tables
[MONO_TABLE_STANDALONESIG
].rows
))
5631 sig
= mono_metadata_decode_row_col (&tables
[MONO_TABLE_STANDALONESIG
], idx
- 1, 0);
5633 ptr
= mono_metadata_blob_heap (image
, sig
);
5634 len
= mono_metadata_decode_blob_size (ptr
, &ptr
);
5636 res
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, len
);
5637 memcpy (mono_array_addr (res
, guint8
, 0), ptr
, len
);
5641 static MonoReflectionType
*
5642 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder
*tb
, MonoString
*smodifiers
)
5645 int isbyref
= 0, rank
;
5646 char *str
= mono_string_to_utf8 (smodifiers
);
5649 MONO_ARCH_SAVE_REGS
;
5651 klass
= mono_class_from_mono_type (tb
->type
.type
);
5653 /* logic taken from mono_reflection_parse_type(): keep in sync */
5657 if (isbyref
) { /* only one level allowed by the spec */
5664 return mono_type_get_object (mono_object_domain (tb
), &klass
->this_arg
);
5667 klass
= mono_ptr_class_get (&klass
->byval_arg
);
5668 mono_class_init (klass
);
5679 else if (*p
!= '*') { /* '*' means unknown lower bound */
5690 klass
= mono_array_class_get (klass
, rank
);
5691 mono_class_init (klass
);
5698 return mono_type_get_object (mono_object_domain (tb
), &klass
->byval_arg
);
5702 ves_icall_Type_IsArrayImpl (MonoReflectionType
*t
)
5707 MONO_ARCH_SAVE_REGS
;
5710 res
= !type
->byref
&& (type
->type
== MONO_TYPE_ARRAY
|| type
->type
== MONO_TYPE_SZARRAY
);
5715 static MonoReflectionType
*
5716 ves_icall_Type_make_array_type (MonoReflectionType
*type
, int rank
)
5718 MonoClass
*klass
, *aklass
;
5720 MONO_ARCH_SAVE_REGS
;
5722 klass
= mono_class_from_mono_type (type
->type
);
5723 mono_class_init_or_throw (klass
);
5725 if (rank
== 0) //single dimentional array
5726 aklass
= mono_array_class_get (klass
, 1);
5728 aklass
= mono_bounded_array_class_get (klass
, rank
, TRUE
);
5730 return mono_type_get_object (mono_object_domain (type
), &aklass
->byval_arg
);
5733 static MonoReflectionType
*
5734 ves_icall_Type_make_byref_type (MonoReflectionType
*type
)
5738 MONO_ARCH_SAVE_REGS
;
5740 klass
= mono_class_from_mono_type (type
->type
);
5741 mono_class_init_or_throw (klass
);
5743 return mono_type_get_object (mono_object_domain (type
), &klass
->this_arg
);
5746 static MonoReflectionType
*
5747 ves_icall_Type_MakePointerType (MonoReflectionType
*type
)
5751 mono_class_init_or_throw (mono_class_from_mono_type (type
->type
));
5753 pklass
= mono_ptr_class_get (type
->type
);
5755 return mono_type_get_object (mono_object_domain (type
), &pklass
->byval_arg
);
5759 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType
*type
, MonoObject
*target
,
5760 MonoReflectionMethod
*info
, MonoBoolean throwOnBindFailure
)
5762 MonoClass
*delegate_class
= mono_class_from_mono_type (type
->type
);
5763 MonoObject
*delegate
;
5765 MonoMethod
*method
= info
->method
;
5767 MONO_ARCH_SAVE_REGS
;
5769 mono_class_init_or_throw (delegate_class
);
5771 mono_assert (delegate_class
->parent
== mono_defaults
.multicastdelegate_class
);
5773 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR
) {
5774 if (!mono_security_core_clr_ensure_delegate_creation (method
, throwOnBindFailure
))
5778 delegate
= mono_object_new (mono_object_domain (type
), delegate_class
);
5780 if (method
->dynamic
) {
5781 /* Creating a trampoline would leak memory */
5782 func
= mono_compile_method (method
);
5784 func
= mono_create_ftnptr (mono_domain_get (),
5785 mono_runtime_create_jump_trampoline (mono_domain_get (), method
, TRUE
));
5788 mono_delegate_ctor_with_method (delegate
, target
, func
, method
);
5794 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate
*this)
5796 /* Reset the invoke impl to the default one */
5797 this->invoke_impl
= mono_runtime_create_delegate_trampoline (this->object
.vtable
->klass
);
5801 * Magic number to convert a time which is relative to
5802 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5804 #define EPOCH_ADJUST ((guint64)62135596800LL)
5807 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5809 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5812 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5814 convert_to_absolute_date(SYSTEMTIME
*date
)
5816 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5817 static int days_in_month
[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5818 static int leap_days_in_month
[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5819 /* from the calendar FAQ */
5820 int a
= (14 - date
->wMonth
) / 12;
5821 int y
= date
->wYear
- a
;
5822 int m
= date
->wMonth
+ 12 * a
- 2;
5823 int d
= (1 + y
+ y
/4 - y
/100 + y
/400 + (31*m
)/12) % 7;
5825 /* d is now the day of the week for the first of the month (0 == Sunday) */
5827 int day_of_week
= date
->wDayOfWeek
;
5829 /* set day_in_month to the first day in the month which falls on day_of_week */
5830 int day_in_month
= 1 + (day_of_week
- d
);
5831 if (day_in_month
<= 0)
5834 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5835 date
->wDay
= day_in_month
+ (date
->wDay
- 1) * 7;
5836 if (date
->wDay
> (IS_LEAP(date
->wYear
) ? leap_days_in_month
[date
->wMonth
- 1] : days_in_month
[date
->wMonth
- 1]))
5843 * Return's the offset from GMT of a local time.
5845 * tm is a local time
5846 * t is the same local time as seconds.
5849 gmt_offset(struct tm
*tm
, time_t t
)
5851 #if defined (HAVE_TM_GMTOFF)
5852 return tm
->tm_gmtoff
;
5857 g
.tm_isdst
= tm
->tm_isdst
;
5859 return (int)difftime(t
, t2
);
5864 * This is heavily based on zdump.c from glibc 2.2.
5866 * * data[0]: start of daylight saving time (in DateTime ticks).
5867 * * data[1]: end of daylight saving time (in DateTime ticks).
5868 * * data[2]: utcoffset (in TimeSpan ticks).
5869 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5870 * * name[0]: name of this timezone when not daylight saving.
5871 * * name[1]: name of this timezone when daylight saving.
5873 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5874 * the class library allows years between 1 and 9999.
5876 * Returns true on success and zero on failure.
5879 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year
, MonoArray
**data
, MonoArray
**names
)
5882 MonoDomain
*domain
= mono_domain_get ();
5883 struct tm start
, tt
;
5887 int is_daylight
= 0, day
;
5890 MONO_ARCH_SAVE_REGS
;
5892 MONO_CHECK_ARG_NULL (data
);
5893 MONO_CHECK_ARG_NULL (names
);
5895 mono_gc_wbarrier_generic_store (data
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.int64_class
, 4));
5896 mono_gc_wbarrier_generic_store (names
, (MonoObject
*) mono_array_new (domain
, mono_defaults
.string_class
, 2));
5899 * no info is better than crashing: we'll need our own tz data
5900 * to make this work properly, anyway. The range is probably
5901 * reduced to 1970 .. 2037 because that is what mktime is
5902 * guaranteed to support (we get into an infinite loop
5906 memset (&start
, 0, sizeof (start
));
5909 start
.tm_year
= year
-1900;
5911 t
= mktime (&start
);
5913 if ((year
< 1970) || (year
> 2037) || (t
== -1)) {
5915 tt
= *localtime (&t
);
5916 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5917 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5918 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5922 gmtoff
= gmt_offset (&start
, t
);
5924 /* For each day of the year, calculate the tm_gmtoff. */
5925 for (day
= 0; day
< 365; day
++) {
5928 tt
= *localtime (&t
);
5930 /* Daylight saving starts or ends here. */
5931 if (gmt_offset (&tt
, t
) != gmtoff
) {
5935 /* Try to find the exact hour when daylight saving starts/ends. */
5939 tt1
= *localtime (&t1
);
5940 } while (gmt_offset (&tt1
, t1
) != gmtoff
);
5942 /* Try to find the exact minute when daylight saving starts/ends. */
5945 tt1
= *localtime (&t1
);
5946 } while (gmt_offset (&tt1
, t1
) == gmtoff
);
5948 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5950 /* Write data, if we're already in daylight saving, we're done. */
5952 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5953 mono_array_set ((*data
), gint64
, 1, ((gint64
)t1
+ EPOCH_ADJUST
) * 10000000L);
5956 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5957 mono_array_set ((*data
), gint64
, 0, ((gint64
)t1
+ EPOCH_ADJUST
) * 10000000L);
5961 /* This is only set once when we enter daylight saving. */
5962 mono_array_set ((*data
), gint64
, 2, (gint64
)gmtoff
* 10000000L);
5963 mono_array_set ((*data
), gint64
, 3, (gint64
)(gmt_offset (&tt
, t
) - gmtoff
) * 10000000L);
5965 gmtoff
= gmt_offset (&tt
, t
);
5970 strftime (tzone
, sizeof (tzone
), "%Z", &tt
);
5971 mono_array_setref ((*names
), 0, mono_string_new (domain
, tzone
));
5972 mono_array_setref ((*names
), 1, mono_string_new (domain
, tzone
));
5973 mono_array_set ((*data
), gint64
, 0, 0);
5974 mono_array_set ((*data
), gint64
, 1, 0);
5975 mono_array_set ((*data
), gint64
, 2, (gint64
) gmtoff
* 10000000L);
5976 mono_array_set ((*data
), gint64
, 3, 0);
5981 MonoDomain
*domain
= mono_domain_get ();
5982 TIME_ZONE_INFORMATION tz_info
;
5987 tz_id
= GetTimeZoneInformation (&tz_info
);
5988 if (tz_id
== TIME_ZONE_ID_INVALID
)
5991 MONO_CHECK_ARG_NULL (data
);
5992 MONO_CHECK_ARG_NULL (names
);
5994 mono_gc_wbarrier_generic_store (data
, mono_array_new (domain
, mono_defaults
.int64_class
, 4));
5995 mono_gc_wbarrier_generic_store (names
, mono_array_new (domain
, mono_defaults
.string_class
, 2));
5997 for (i
= 0; i
< 32; ++i
)
5998 if (!tz_info
.DaylightName
[i
])
6000 mono_array_setref ((*names
), 1, mono_string_new_utf16 (domain
, tz_info
.DaylightName
, i
));
6001 for (i
= 0; i
< 32; ++i
)
6002 if (!tz_info
.StandardName
[i
])
6004 mono_array_setref ((*names
), 0, mono_string_new_utf16 (domain
, tz_info
.StandardName
, i
));
6006 if ((year
<= 1601) || (year
> 30827)) {
6008 * According to MSDN, the MS time functions can't handle dates outside
6014 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6015 if (tz_id
!= TIME_ZONE_ID_UNKNOWN
) {
6016 tz_info
.StandardDate
.wYear
= year
;
6017 convert_to_absolute_date(&tz_info
.StandardDate
);
6018 err
= SystemTimeToFileTime (&tz_info
.StandardDate
, &ft
);
6023 mono_array_set ((*data
), gint64
, 1, FILETIME_ADJUST
+ (((guint64
)ft
.dwHighDateTime
<<32) | ft
.dwLowDateTime
));
6024 tz_info
.DaylightDate
.wYear
= year
;
6025 convert_to_absolute_date(&tz_info
.DaylightDate
);
6026 err
= SystemTimeToFileTime (&tz_info
.DaylightDate
, &ft
);
6031 mono_array_set ((*data
), gint64
, 0, FILETIME_ADJUST
+ (((guint64
)ft
.dwHighDateTime
<<32) | ft
.dwLowDateTime
));
6033 mono_array_set ((*data
), gint64
, 2, (tz_info
.Bias
+ tz_info
.StandardBias
) * -600000000LL);
6034 mono_array_set ((*data
), gint64
, 3, (tz_info
.DaylightBias
- tz_info
.StandardBias
) * -600000000LL);
6041 ves_icall_System_Object_obj_address (MonoObject
*this)
6043 MONO_ARCH_SAVE_REGS
;
6050 static inline gint32
6051 mono_array_get_byte_length (MonoArray
*array
)
6057 klass
= array
->obj
.vtable
->klass
;
6059 if (array
->bounds
== NULL
)
6060 length
= array
->max_length
;
6063 for (i
= 0; i
< klass
->rank
; ++ i
)
6064 length
*= array
->bounds
[i
].length
;
6067 switch (klass
->element_class
->byval_arg
.type
) {
6070 case MONO_TYPE_BOOLEAN
:
6074 case MONO_TYPE_CHAR
:
6082 return length
* sizeof (gpointer
);
6093 ves_icall_System_Buffer_ByteLengthInternal (MonoArray
*array
)
6095 MONO_ARCH_SAVE_REGS
;
6097 return mono_array_get_byte_length (array
);
6101 ves_icall_System_Buffer_GetByteInternal (MonoArray
*array
, gint32 idx
)
6103 MONO_ARCH_SAVE_REGS
;
6105 return mono_array_get (array
, gint8
, idx
);
6109 ves_icall_System_Buffer_SetByteInternal (MonoArray
*array
, gint32 idx
, gint8 value
)
6111 MONO_ARCH_SAVE_REGS
;
6113 mono_array_set (array
, gint8
, idx
, value
);
6117 ves_icall_System_Buffer_BlockCopyInternal (MonoArray
*src
, gint32 src_offset
, MonoArray
*dest
, gint32 dest_offset
, gint32 count
)
6119 guint8
*src_buf
, *dest_buf
;
6121 MONO_ARCH_SAVE_REGS
;
6123 /* watch out for integer overflow */
6124 if ((src_offset
> mono_array_get_byte_length (src
) - count
) || (dest_offset
> mono_array_get_byte_length (dest
) - count
))
6127 src_buf
= (guint8
*)src
->vector
+ src_offset
;
6128 dest_buf
= (guint8
*)dest
->vector
+ dest_offset
;
6131 memcpy (dest_buf
, src_buf
, count
);
6133 memmove (dest_buf
, src_buf
, count
); /* Source and dest are the same array */
6139 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject
*this, MonoString
*class_name
)
6141 MonoDomain
*domain
= mono_object_domain (this);
6143 MonoRealProxy
*rp
= ((MonoRealProxy
*)this);
6144 MonoTransparentProxy
*tp
;
6148 MONO_ARCH_SAVE_REGS
;
6150 res
= mono_object_new (domain
, mono_defaults
.transparent_proxy_class
);
6151 tp
= (MonoTransparentProxy
*) res
;
6153 MONO_OBJECT_SETREF (tp
, rp
, rp
);
6154 type
= ((MonoReflectionType
*)rp
->class_to_proxy
)->type
;
6155 klass
= mono_class_from_mono_type (type
);
6157 tp
->custom_type_info
= (mono_object_isinst (this, mono_defaults
.iremotingtypeinfo_class
) != NULL
);
6158 tp
->remote_class
= mono_remote_class (domain
, class_name
, klass
);
6160 res
->vtable
= mono_remote_class_vtable (domain
, tp
->remote_class
, rp
);
6164 static MonoReflectionType
*
6165 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy
*tp
)
6167 return mono_type_get_object (mono_object_domain (tp
), &tp
->remote_class
->proxy_class
->byval_arg
);
6170 /* System.Environment */
6173 ves_icall_System_Environment_get_UserName (void)
6175 MONO_ARCH_SAVE_REGS
;
6177 /* using glib is more portable */
6178 return mono_string_new (mono_domain_get (), g_get_user_name ());
6183 ves_icall_System_Environment_get_MachineName (void)
6185 #if defined (HOST_WIN32)
6190 len
= MAX_COMPUTERNAME_LENGTH
+ 1;
6191 buf
= g_new (gunichar2
, len
);
6194 if (GetComputerName (buf
, (PDWORD
) &len
))
6195 result
= mono_string_new_utf16 (mono_domain_get (), buf
, len
);
6199 #elif !defined(DISABLE_SOCKETS)
6203 if (gethostname (buf
, sizeof (buf
)) == 0)
6204 result
= mono_string_new (mono_domain_get (), buf
);
6210 return mono_string_new (mono_domain_get (), "mono");
6215 ves_icall_System_Environment_get_Platform (void)
6217 #if defined (TARGET_WIN32)
6220 #elif defined(__MACH__)
6223 // For compatibility with our client code, this will be 4 for a while.
6224 // We will eventually move to 6 to match .NET, but it requires all client
6225 // code to be updated and the documentation everywhere to be updated
6236 ves_icall_System_Environment_get_NewLine (void)
6238 MONO_ARCH_SAVE_REGS
;
6240 #if defined (HOST_WIN32)
6241 return mono_string_new (mono_domain_get (), "\r\n");
6243 return mono_string_new (mono_domain_get (), "\n");
6248 ves_icall_System_Environment_GetEnvironmentVariable (MonoString
*name
)
6253 MONO_ARCH_SAVE_REGS
;
6258 utf8_name
= mono_string_to_utf8 (name
); /* FIXME: this should be ascii */
6259 value
= g_getenv (utf8_name
);
6266 return mono_string_new (mono_domain_get (), value
);
6270 * There is no standard way to get at environ.
6273 #ifndef __MINGW32_VERSION
6275 /* Apple defines this in crt_externs.h but doesn't provide that header for
6276 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6277 * in fact exist on all implementations (so far)
6279 gchar
***_NSGetEnviron(void);
6280 #define environ (*_NSGetEnviron())
6289 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6300 env_strings
= GetEnvironmentStrings();
6303 env_string
= env_strings
;
6304 while (*env_string
!= '\0') {
6305 /* weird case that MS seems to skip */
6306 if (*env_string
!= '=')
6308 while (*env_string
!= '\0')
6314 domain
= mono_domain_get ();
6315 names
= mono_array_new (domain
, mono_defaults
.string_class
, n
);
6319 env_string
= env_strings
;
6320 while (*env_string
!= '\0') {
6321 /* weird case that MS seems to skip */
6322 if (*env_string
!= '=') {
6323 equal_str
= wcschr(env_string
, '=');
6324 g_assert(equal_str
);
6325 str
= mono_string_new_utf16 (domain
, env_string
, equal_str
-env_string
);
6326 mono_array_setref (names
, n
, str
);
6329 while (*env_string
!= '\0')
6334 FreeEnvironmentStrings (env_strings
);
6346 MONO_ARCH_SAVE_REGS
;
6349 for (e
= environ
; *e
!= 0; ++ e
)
6352 domain
= mono_domain_get ();
6353 names
= mono_array_new (domain
, mono_defaults
.string_class
, n
);
6356 for (e
= environ
; *e
!= 0; ++ e
) {
6357 parts
= g_strsplit (*e
, "=", 2);
6359 str
= mono_string_new (domain
, *parts
);
6360 mono_array_setref (names
, n
, str
);
6373 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6375 #if !GLIB_CHECK_VERSION(2,4,0)
6376 #define g_setenv(a,b,c) setenv(a,b,c)
6377 #define g_unsetenv(a) unsetenv(a)
6381 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString
*name
, MonoString
*value
)
6386 gunichar2
*utf16_name
, *utf16_value
;
6388 gchar
*utf8_name
, *utf8_value
;
6391 MONO_ARCH_SAVE_REGS
;
6394 utf16_name
= mono_string_to_utf16 (name
);
6395 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
6396 SetEnvironmentVariable (utf16_name
, NULL
);
6397 g_free (utf16_name
);
6401 utf16_value
= mono_string_to_utf16 (value
);
6403 SetEnvironmentVariable (utf16_name
, utf16_value
);
6405 g_free (utf16_name
);
6406 g_free (utf16_value
);
6408 utf8_name
= mono_string_to_utf8 (name
); /* FIXME: this should be ascii */
6410 if ((value
== NULL
) || (mono_string_length (value
) == 0) || (mono_string_chars (value
)[0] == 0)) {
6411 g_unsetenv (utf8_name
);
6416 utf8_value
= mono_string_to_utf8_checked (value
, &error
);
6417 if (!mono_error_ok (&error
)) {
6419 mono_error_raise_exception (&error
);
6421 g_setenv (utf8_name
, utf8_value
, TRUE
);
6424 g_free (utf8_value
);
6429 ves_icall_System_Environment_Exit (int result
)
6431 MONO_ARCH_SAVE_REGS
;
6433 mono_threads_set_shutting_down ();
6435 mono_runtime_set_shutting_down ();
6437 /* This will kill the tp threads which cannot be suspended */
6438 mono_thread_pool_cleanup ();
6440 /* Suspend all managed threads since the runtime is going away */
6441 mono_thread_suspend_all_other_threads ();
6443 mono_runtime_quit ();
6445 /* we may need to do some cleanup here... */
6450 ves_icall_System_Environment_GetGacPath (void)
6452 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6456 ves_icall_System_Environment_GetWindowsFolderPath (int folder
)
6458 #if defined (HOST_WIN32)
6459 #ifndef CSIDL_FLAG_CREATE
6460 #define CSIDL_FLAG_CREATE 0x8000
6463 WCHAR path
[MAX_PATH
];
6464 /* Create directory if no existing */
6465 if (SUCCEEDED (SHGetFolderPathW (NULL
, folder
| CSIDL_FLAG_CREATE
, NULL
, 0, path
))) {
6469 return mono_string_new_utf16 (mono_domain_get (), path
, len
);
6472 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6474 return mono_string_new (mono_domain_get (), "");
6478 ves_icall_System_Environment_GetLogicalDrives (void)
6480 gunichar2 buf
[128], *ptr
, *dname
;
6482 guint initial_size
= 127, size
= 128;
6485 MonoString
*drivestr
;
6486 MonoDomain
*domain
= mono_domain_get ();
6489 MONO_ARCH_SAVE_REGS
;
6494 while (size
> initial_size
) {
6495 size
= (guint
) GetLogicalDriveStrings (initial_size
, ptr
);
6496 if (size
> initial_size
) {
6499 ptr
= g_malloc0 ((size
+ 1) * sizeof (gunichar2
));
6500 initial_size
= size
;
6514 result
= mono_array_new (domain
, mono_defaults
.string_class
, ndrives
);
6519 while (*u16
) { u16
++; len
++; }
6520 drivestr
= mono_string_new_utf16 (domain
, dname
, len
);
6521 mono_array_setref (result
, ndrives
++, drivestr
);
6532 ves_icall_System_Environment_InternalGetHome (void)
6534 MONO_ARCH_SAVE_REGS
;
6536 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6539 static const char *encodings
[] = {
6541 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6542 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6543 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6545 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6546 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6547 "x_unicode_2_0_utf_7",
6549 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6550 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6552 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6555 "unicodefffe", "utf_16be",
6562 * Returns the internal codepage, if the value of "int_code_page" is
6563 * 1 at entry, and we can not compute a suitable code page number,
6564 * returns the code page as a string
6567 ves_icall_System_Text_Encoding_InternalCodePage (gint32
*int_code_page
)
6572 char *codepage
= NULL
;
6574 int want_name
= *int_code_page
;
6577 *int_code_page
= -1;
6578 MONO_ARCH_SAVE_REGS
;
6580 g_get_charset (&cset
);
6581 c
= codepage
= strdup (cset
);
6582 for (c
= codepage
; *c
; c
++){
6583 if (isascii (*c
) && isalpha (*c
))
6588 /* g_print ("charset: %s\n", cset); */
6590 /* handle some common aliases */
6593 for (i
= 0; p
!= 0; ){
6594 if ((gssize
) p
< 7){
6596 p
= encodings
[++i
];
6599 if (strcmp (p
, codepage
) == 0){
6600 *int_code_page
= code
;
6603 p
= encodings
[++i
];
6606 if (strstr (codepage
, "utf_8") != NULL
)
6607 *int_code_page
|= 0x10000000;
6610 if (want_name
&& *int_code_page
== -1)
6611 return mono_string_new (mono_domain_get (), cset
);
6617 ves_icall_System_Environment_get_HasShutdownStarted (void)
6619 if (mono_runtime_is_shutting_down ())
6622 if (mono_domain_is_unloading (mono_domain_get ()))
6629 ves_icall_System_Environment_BroadcastSettingChange (void)
6632 SendMessageTimeout (HWND_BROADCAST
, WM_SETTINGCHANGE
, NULL
, L
"Environment", SMTO_ABORTIFHUNG
, 2000, 0);
6637 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage
*this,
6638 MonoReflectionMethod
*method
,
6639 MonoArray
*out_args
)
6641 MONO_ARCH_SAVE_REGS
;
6643 mono_message_init (mono_object_domain (this), this, method
, out_args
);
6647 ves_icall_IsTransparentProxy (MonoObject
*proxy
)
6649 MONO_ARCH_SAVE_REGS
;
6654 if (proxy
->vtable
->klass
== mono_defaults
.transparent_proxy_class
)
6660 static MonoReflectionMethod
*
6661 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6662 MonoReflectionType
*rtype
, MonoReflectionMethod
*rmethod
)
6666 MonoMethod
**vtable
;
6667 MonoMethod
*res
= NULL
;
6669 MONO_CHECK_ARG_NULL (rtype
);
6670 MONO_CHECK_ARG_NULL (rmethod
);
6672 method
= rmethod
->method
;
6673 klass
= mono_class_from_mono_type (rtype
->type
);
6674 mono_class_init_or_throw (klass
);
6676 if (MONO_CLASS_IS_INTERFACE (klass
))
6679 if (method
->flags
& METHOD_ATTRIBUTE_STATIC
)
6682 if ((method
->flags
& METHOD_ATTRIBUTE_FINAL
) || !(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
)) {
6683 if (klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
))
6689 mono_class_setup_vtable (klass
);
6690 vtable
= klass
->vtable
;
6692 if (method
->klass
->flags
& TYPE_ATTRIBUTE_INTERFACE
) {
6693 gboolean variance_used
= FALSE
;
6694 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6695 int offs
= mono_class_interface_offset_with_variance (klass
, method
->klass
, &variance_used
);
6697 res
= vtable
[offs
+ method
->slot
];
6699 if (!(klass
== method
->klass
|| mono_class_is_subclass_of (klass
, method
->klass
, FALSE
)))
6702 if (method
->slot
!= -1)
6703 res
= vtable
[method
->slot
];
6709 return mono_method_get_object (mono_domain_get (), res
, NULL
);
6713 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType
*type
, MonoBoolean enable
)
6718 MONO_ARCH_SAVE_REGS
;
6720 klass
= mono_class_from_mono_type (type
->type
);
6721 vtable
= mono_class_vtable_full (mono_domain_get (), klass
, TRUE
);
6723 if (enable
) vtable
->remote
= 1;
6724 else vtable
->remote
= 0;
6728 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType
*type
)
6733 MONO_ARCH_SAVE_REGS
;
6735 domain
= mono_object_domain (type
);
6736 klass
= mono_class_from_mono_type (type
->type
);
6737 mono_class_init_or_throw (klass
);
6739 if (klass
->rank
>= 1) {
6740 g_assert (klass
->rank
== 1);
6741 return (MonoObject
*) mono_array_new (domain
, klass
->element_class
, 0);
6743 /* Bypass remoting object creation check */
6744 return mono_object_new_alloc_specific (mono_class_vtable_full (domain
, klass
, TRUE
));
6749 ves_icall_System_IO_get_temp_path (void)
6751 MONO_ARCH_SAVE_REGS
;
6753 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6756 #ifndef PLATFORM_NO_DRIVEINFO
6758 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString
*path_name
, guint64
*free_bytes_avail
,
6759 guint64
*total_number_of_bytes
, guint64
*total_number_of_free_bytes
,
6763 ULARGE_INTEGER wapi_free_bytes_avail
;
6764 ULARGE_INTEGER wapi_total_number_of_bytes
;
6765 ULARGE_INTEGER wapi_total_number_of_free_bytes
;
6767 MONO_ARCH_SAVE_REGS
;
6769 *error
= ERROR_SUCCESS
;
6770 result
= GetDiskFreeSpaceEx (mono_string_chars (path_name
), &wapi_free_bytes_avail
, &wapi_total_number_of_bytes
,
6771 &wapi_total_number_of_free_bytes
);
6774 *free_bytes_avail
= wapi_free_bytes_avail
.QuadPart
;
6775 *total_number_of_bytes
= wapi_total_number_of_bytes
.QuadPart
;
6776 *total_number_of_free_bytes
= wapi_total_number_of_free_bytes
.QuadPart
;
6778 *free_bytes_avail
= 0;
6779 *total_number_of_bytes
= 0;
6780 *total_number_of_free_bytes
= 0;
6781 *error
= GetLastError ();
6788 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString
*root_path_name
)
6790 MONO_ARCH_SAVE_REGS
;
6792 return GetDriveType (mono_string_chars (root_path_name
));
6797 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod
*method
)
6799 MONO_ARCH_SAVE_REGS
;
6801 return mono_compile_method (method
);
6805 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6810 MONO_ARCH_SAVE_REGS
;
6812 path
= g_build_path (G_DIR_SEPARATOR_S
, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version
, "machine.config", NULL
);
6814 #if defined (HOST_WIN32)
6815 /* Avoid mixing '/' and '\\' */
6818 for (i
= strlen (path
) - 1; i
>= 0; i
--)
6819 if (path
[i
] == '/')
6823 mcpath
= mono_string_new (mono_domain_get (), path
);
6830 get_bundled_machine_config (void)
6832 const gchar
*machine_config
;
6834 MONO_ARCH_SAVE_REGS
;
6836 machine_config
= mono_get_machine_config ();
6838 if (!machine_config
)
6841 return mono_string_new (mono_domain_get (), machine_config
);
6845 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6850 MONO_ARCH_SAVE_REGS
;
6852 path
= g_path_get_dirname (mono_get_config_dir ());
6854 #if defined (HOST_WIN32)
6855 /* Avoid mixing '/' and '\\' */
6858 for (i
= strlen (path
) - 1; i
>= 0; i
--)
6859 if (path
[i
] == '/')
6863 ipath
= mono_string_new (mono_domain_get (), path
);
6870 ves_icall_get_resources_ptr (MonoReflectionAssembly
*assembly
, gpointer
*result
, gint32
*size
)
6872 MonoPEResourceDataEntry
*entry
;
6875 MONO_ARCH_SAVE_REGS
;
6877 if (!assembly
|| !result
|| !size
)
6882 image
= assembly
->assembly
->image
;
6883 entry
= mono_image_lookup_resource (image
, MONO_PE_RESOURCE_ID_ASPNET_STRING
, 0, NULL
);
6887 *result
= mono_image_rva_map (image
, entry
->rde_data_offset
);
6892 *size
= entry
->rde_size
;
6898 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6900 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6904 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString
*message
)
6906 #if defined (HOST_WIN32)
6907 OutputDebugString (mono_string_chars (message
));
6909 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6913 /* Only used for value types */
6915 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType
*type
)
6920 MONO_ARCH_SAVE_REGS
;
6922 domain
= mono_object_domain (type
);
6923 klass
= mono_class_from_mono_type (type
->type
);
6924 mono_class_init_or_throw (klass
);
6926 if (mono_class_is_nullable (klass
))
6927 /* No arguments -> null */
6930 return mono_object_new (domain
, klass
);
6933 static MonoReflectionMethod
*
6934 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod
*m
, gboolean definition
)
6936 MonoClass
*klass
, *parent
;
6937 MonoMethod
*method
= m
->method
;
6938 MonoMethod
*result
= NULL
;
6940 MONO_ARCH_SAVE_REGS
;
6942 if (method
->klass
== NULL
)
6945 if (!(method
->flags
& METHOD_ATTRIBUTE_VIRTUAL
) ||
6946 MONO_CLASS_IS_INTERFACE (method
->klass
) ||
6947 method
->flags
& METHOD_ATTRIBUTE_NEW_SLOT
)
6950 klass
= method
->klass
;
6951 if (klass
->generic_class
)
6952 klass
= klass
->generic_class
->container_class
;
6955 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6956 for (parent
= klass
->parent
; parent
!= NULL
; parent
= parent
->parent
) {
6957 mono_class_setup_vtable (parent
);
6958 if (parent
->vtable_size
<= method
->slot
)
6963 klass
= klass
->parent
;
6968 if (klass
== method
->klass
)
6971 result
= klass
->vtable
[method
->slot
];
6972 if (result
== NULL
) {
6973 /* It is an abstract method */
6974 gpointer iter
= NULL
;
6975 while ((result
= mono_class_get_methods (klass
, &iter
)))
6976 if (result
->slot
== method
->slot
)
6983 return mono_method_get_object (mono_domain_get (), result
, NULL
);
6987 ves_icall_MonoMethod_get_name (MonoReflectionMethod
*m
)
6989 MonoMethod
*method
= m
->method
;
6991 MONO_OBJECT_SETREF (m
, name
, mono_string_new (mono_object_domain (m
), method
->name
));
6996 mono_ArgIterator_Setup (MonoArgIterator
*iter
, char* argsp
, char* start
)
6998 MONO_ARCH_SAVE_REGS
;
7000 iter
->sig
= *(MonoMethodSignature
**)argsp
;
7002 g_assert (iter
->sig
->sentinelpos
<= iter
->sig
->param_count
);
7003 g_assert (iter
->sig
->call_convention
== MONO_CALL_VARARG
);
7006 /* FIXME: it's not documented what start is exactly... */
7010 iter
->args
= argsp
+ sizeof (gpointer
);
7012 iter
->num_args
= iter
->sig
->param_count
- iter
->sig
->sentinelpos
;
7014 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7018 mono_ArgIterator_IntGetNextArg (MonoArgIterator
*iter
)
7020 guint32 i
, arg_size
;
7023 MONO_ARCH_SAVE_REGS
;
7025 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7027 g_assert (i
< iter
->sig
->param_count
);
7029 res
.type
= iter
->sig
->params
[i
];
7030 res
.klass
= mono_class_from_mono_type (res
.type
);
7031 res
.value
= iter
->args
;
7032 arg_size
= mono_type_stack_size (res
.type
, &align
);
7033 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7034 if (arg_size
<= sizeof (gpointer
)) {
7036 int padding
= arg_size
- mono_type_size (res
.type
, &dummy
);
7037 res
.value
= (guint8
*)res
.value
+ padding
;
7040 iter
->args
= (char*)iter
->args
+ arg_size
;
7043 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7049 mono_ArgIterator_IntGetNextArgT (MonoArgIterator
*iter
, MonoType
*type
)
7051 guint32 i
, arg_size
;
7054 MONO_ARCH_SAVE_REGS
;
7056 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7058 g_assert (i
< iter
->sig
->param_count
);
7060 while (i
< iter
->sig
->param_count
) {
7061 if (!mono_metadata_type_equal (type
, iter
->sig
->params
[i
]))
7063 res
.type
= iter
->sig
->params
[i
];
7064 res
.klass
= mono_class_from_mono_type (res
.type
);
7065 /* FIXME: endianess issue... */
7066 res
.value
= iter
->args
;
7067 arg_size
= mono_type_stack_size (res
.type
, &align
);
7068 iter
->args
= (char*)iter
->args
+ arg_size
;
7070 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7073 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7082 mono_ArgIterator_IntGetNextArgType (MonoArgIterator
*iter
)
7085 MONO_ARCH_SAVE_REGS
;
7087 i
= iter
->sig
->sentinelpos
+ iter
->next_arg
;
7089 g_assert (i
< iter
->sig
->param_count
);
7091 return iter
->sig
->params
[i
];
7095 mono_TypedReference_ToObject (MonoTypedRef tref
)
7097 MONO_ARCH_SAVE_REGS
;
7099 if (MONO_TYPE_IS_REFERENCE (tref
.type
)) {
7100 MonoObject
** objp
= tref
.value
;
7104 return mono_value_box (mono_domain_get (), tref
.klass
, tref
.value
);
7108 mono_TypedReference_ToObjectInternal (MonoType
*type
, gpointer value
, MonoClass
*klass
)
7110 MONO_ARCH_SAVE_REGS
;
7112 if (MONO_TYPE_IS_REFERENCE (type
)) {
7113 MonoObject
** objp
= value
;
7117 return mono_value_box (mono_domain_get (), klass
, value
);
7121 prelink_method (MonoMethod
*method
)
7123 const char *exc_class
, *exc_arg
;
7124 if (!(method
->flags
& METHOD_ATTRIBUTE_PINVOKE_IMPL
))
7126 mono_lookup_pinvoke_call (method
, &exc_class
, &exc_arg
);
7128 mono_raise_exception(
7129 mono_exception_from_name_msg (mono_defaults
.corlib
, "System", exc_class
, exc_arg
) );
7131 /* create the wrapper, too? */
7135 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod
*method
)
7137 MONO_ARCH_SAVE_REGS
;
7138 prelink_method (method
->method
);
7142 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType
*type
)
7144 MonoClass
*klass
= mono_class_from_mono_type (type
->type
);
7146 gpointer iter
= NULL
;
7147 MONO_ARCH_SAVE_REGS
;
7149 mono_class_init_or_throw (klass
);
7151 while ((m
= mono_class_get_methods (klass
, &iter
)))
7155 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7157 ves_icall_System_NumberFormatter_GetFormatterTables (guint64
const **mantissas
,
7158 gint32
const **exponents
,
7159 gunichar2
const **digitLowerTable
,
7160 gunichar2
const **digitUpperTable
,
7161 gint64
const **tenPowersList
,
7162 gint32
const **decHexDigits
)
7164 *mantissas
= Formatter_MantissaBitsTable
;
7165 *exponents
= Formatter_TensExponentTable
;
7166 *digitLowerTable
= Formatter_DigitLowerTable
;
7167 *digitUpperTable
= Formatter_DigitUpperTable
;
7168 *tenPowersList
= Formatter_TenPowersList
;
7169 *decHexDigits
= Formatter_DecHexDigits
;
7172 /* These parameters are "readonly" in corlib/System/Char.cs */
7174 ves_icall_System_Char_GetDataTablePointers (guint8
const **category_data
,
7175 guint8
const **numeric_data
,
7176 gdouble
const **numeric_data_values
,
7177 guint16
const **to_lower_data_low
,
7178 guint16
const **to_lower_data_high
,
7179 guint16
const **to_upper_data_low
,
7180 guint16
const **to_upper_data_high
)
7182 *category_data
= CategoryData
;
7183 *numeric_data
= NumericData
;
7184 *numeric_data_values
= NumericDataValues
;
7185 *to_lower_data_low
= ToLowerDataLow
;
7186 *to_lower_data_high
= ToLowerDataHigh
;
7187 *to_upper_data_low
= ToUpperDataLow
;
7188 *to_upper_data_high
= ToUpperDataHigh
;
7192 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod
*method
)
7194 return method
->method
->token
;
7198 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7199 * and avoid useless allocations.
7202 type_array_from_modifiers (MonoImage
*image
, MonoType
*type
, int optional
)
7206 for (i
= 0; i
< type
->num_mods
; ++i
) {
7207 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
))
7212 res
= mono_array_new (mono_domain_get (), mono_defaults
.systemtype_class
, count
);
7214 for (i
= 0; i
< type
->num_mods
; ++i
) {
7215 if ((optional
&& !type
->modifiers
[i
].required
) || (!optional
&& type
->modifiers
[i
].required
)) {
7216 MonoClass
*klass
= mono_class_get (image
, type
->modifiers
[i
].token
);
7217 mono_array_setref (res
, count
, mono_type_get_object (mono_domain_get (), &klass
->byval_arg
));
7225 param_info_get_type_modifiers (MonoReflectionParameter
*param
, MonoBoolean optional
)
7227 MonoType
*type
= param
->ClassImpl
->type
;
7228 MonoClass
*member_class
= mono_object_class (param
->MemberImpl
);
7229 MonoMethod
*method
= NULL
;
7232 MonoMethodSignature
*sig
;
7234 if (mono_class_is_reflection_method_or_constructor (member_class
)) {
7235 MonoReflectionMethod
*rmethod
= (MonoReflectionMethod
*)param
->MemberImpl
;
7236 method
= rmethod
->method
;
7237 } else if (member_class
->image
== mono_defaults
.corlib
&& !strcmp ("MonoProperty", member_class
->name
)) {
7238 MonoReflectionProperty
*prop
= (MonoReflectionProperty
*)param
->MemberImpl
;
7239 if (!(method
= prop
->property
->get
))
7240 method
= prop
->property
->set
;
7243 char *type_name
= mono_type_get_full_name (member_class
);
7244 char *msg
= g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name
);
7245 MonoException
*ex
= mono_get_exception_not_supported (msg
);
7248 mono_raise_exception (ex
);
7251 image
= method
->klass
->image
;
7252 pos
= param
->PositionImpl
;
7253 sig
= mono_method_signature (method
);
7257 type
= sig
->params
[pos
];
7259 return type_array_from_modifiers (image
, type
, optional
);
7263 get_property_type (MonoProperty
*prop
)
7265 MonoMethodSignature
*sig
;
7267 sig
= mono_method_signature (prop
->get
);
7269 } else if (prop
->set
) {
7270 sig
= mono_method_signature (prop
->set
);
7271 return sig
->params
[sig
->param_count
- 1];
7277 property_info_get_type_modifiers (MonoReflectionProperty
*property
, MonoBoolean optional
)
7279 MonoType
*type
= get_property_type (property
->property
);
7280 MonoImage
*image
= property
->klass
->image
;
7284 return type_array_from_modifiers (image
, type
, optional
);
7288 *Construct a MonoType suited to be used to decode a constant blob object.
7290 * @type is the target type which will be constructed
7291 * @blob_type is the blob type, for example, that comes from the constant table
7292 * @real_type is the expected constructed type.
7295 mono_type_from_blob_type (MonoType
*type
, MonoTypeEnum blob_type
, MonoType
*real_type
)
7297 type
->type
= blob_type
;
7298 type
->data
.klass
= NULL
;
7299 if (blob_type
== MONO_TYPE_CLASS
)
7300 type
->data
.klass
= mono_defaults
.object_class
;
7301 else if (real_type
->type
== MONO_TYPE_VALUETYPE
&& real_type
->data
.klass
->enumtype
) {
7302 /* For enums, we need to use the base type */
7303 type
->type
= MONO_TYPE_VALUETYPE
;
7304 type
->data
.klass
= mono_class_from_mono_type (real_type
);
7306 type
->data
.klass
= mono_class_from_mono_type (real_type
);
7310 property_info_get_default_value (MonoReflectionProperty
*property
)
7313 MonoProperty
*prop
= property
->property
;
7314 MonoType
*type
= get_property_type (prop
);
7315 MonoDomain
*domain
= mono_object_domain (property
);
7316 MonoTypeEnum def_type
;
7317 const char *def_value
;
7320 g_assert (!prop
->parent
->image
->dynamic
);
7322 mono_class_init (prop
->parent
);
7324 if (!(prop
->attrs
& PROPERTY_ATTRIBUTE_HAS_DEFAULT
))
7325 mono_raise_exception (mono_get_exception_invalid_operation (NULL
));
7327 def_value
= mono_class_get_property_default_value (prop
, &def_type
);
7329 mono_type_from_blob_type (&blob_type
, def_type
, type
);
7330 o
= mono_get_object_from_blob (domain
, &blob_type
, def_value
);
7336 custom_attrs_defined_internal (MonoObject
*obj
, MonoReflectionType
*attr_type
)
7338 MonoClass
*attr_class
= mono_class_from_mono_type (attr_type
->type
);
7339 MonoCustomAttrInfo
*cinfo
;
7342 mono_class_init_or_throw (attr_class
);
7344 cinfo
= mono_reflection_get_custom_attrs_info (obj
);
7347 found
= mono_custom_attrs_has_attr (cinfo
, attr_class
);
7349 mono_custom_attrs_free (cinfo
);
7354 custom_attrs_get_by_type (MonoObject
*obj
, MonoReflectionType
*attr_type
)
7356 MonoClass
*attr_class
= attr_type
? mono_class_from_mono_type (attr_type
->type
) : NULL
;
7360 mono_class_init_or_throw (attr_class
);
7362 res
= mono_reflection_get_custom_attrs_by_type (obj
, attr_class
);
7364 if (mono_loader_get_last_error ()) {
7365 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7366 g_assert_not_reached ();
7375 ves_icall_Mono_Runtime_GetDisplayName (void)
7378 MonoString
*display_name
;
7380 info
= mono_get_runtime_callbacks ()->get_runtime_build_info ();
7381 display_name
= mono_string_new (mono_domain_get (), info
);
7383 return display_name
;
7387 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code
)
7389 MonoString
*message
;
7393 ret
= FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
|
7394 FORMAT_MESSAGE_IGNORE_INSERTS
, NULL
, code
, 0,
7397 message
= mono_string_new (mono_domain_get (), "Error looking up error string");
7399 message
= mono_string_new_utf16 (mono_domain_get (), buf
, ret
);
7407 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7408 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7409 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7410 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7411 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7412 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7413 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7414 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7418 base64_to_byte_array (gunichar2
*start
, gint ilength
, MonoBoolean allowWhitespaceOnly
)
7423 gunichar2 last
, prev_last
, prev2_last
;
7431 last
= prev_last
= 0, prev2_last
= 0;
7432 for (i
= 0; i
< ilength
; i
++) {
7434 if (c
>= sizeof (dbase64
)) {
7435 exc
= mono_exception_from_name_msg (mono_get_corlib (),
7436 "System", "FormatException",
7437 "Invalid character found.");
7438 mono_raise_exception (exc
);
7439 } else if (isspace (c
)) {
7442 prev2_last
= prev_last
;
7448 olength
= ilength
- ignored
;
7450 if (allowWhitespaceOnly
&& olength
== 0) {
7451 return mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, 0);
7454 if ((olength
& 3) != 0 || olength
<= 0) {
7455 exc
= mono_exception_from_name_msg (mono_get_corlib (), "System",
7456 "FormatException", "Invalid length.");
7457 mono_raise_exception (exc
);
7460 if (prev2_last
== '=') {
7461 exc
= mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7462 mono_raise_exception (exc
);
7465 olength
= (olength
* 3) / 4;
7469 if (prev_last
== '=')
7472 result
= mono_array_new (mono_domain_get (), mono_defaults
.byte_class
, olength
);
7473 res_ptr
= mono_array_addr (result
, guchar
, 0);
7474 for (i
= 0; i
< ilength
; ) {
7477 for (k
= 0; k
< 4 && i
< ilength
;) {
7483 if (((b
[k
] = dbase64
[c
]) & 0x80) != 0) {
7484 exc
= mono_exception_from_name_msg (mono_get_corlib (),
7485 "System", "FormatException",
7486 "Invalid character found.");
7487 mono_raise_exception (exc
);
7492 *res_ptr
++ = (b
[0] << 2) | (b
[1] >> 4);
7494 *res_ptr
++ = (b
[1] << 4) | (b
[2] >> 2);
7496 *res_ptr
++ = (b
[2] << 6) | b
[3];
7498 while (i
< ilength
&& isspace (start
[i
]))
7506 InternalFromBase64String (MonoString
*str
, MonoBoolean allowWhitespaceOnly
)
7508 MONO_ARCH_SAVE_REGS
;
7510 return base64_to_byte_array (mono_string_chars (str
),
7511 mono_string_length (str
), allowWhitespaceOnly
);
7515 InternalFromBase64CharArray (MonoArray
*input
, gint offset
, gint length
)
7517 MONO_ARCH_SAVE_REGS
;
7519 return base64_to_byte_array (mono_array_addr (input
, gunichar2
, offset
),
7523 #define ICALL_TYPE(id,name,first)
7524 #define ICALL(id,name,func) Icall_ ## id,
7527 #include "metadata/icall-def.h"
7533 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7534 #define ICALL(id,name,func)
7536 #include "metadata/icall-def.h"
7542 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7543 #define ICALL(id,name,func)
7545 guint16 first_icall
;
7548 static const IcallTypeDesc
7549 icall_type_descs
[] = {
7550 #include "metadata/icall-def.h"
7554 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7557 #define ICALL_TYPE(id,name,first)
7560 #ifdef HAVE_ARRAY_ELEM_INIT
7561 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7562 #define MSGSTRFIELD1(line) str##line
7564 static const struct msgstrtn_t
{
7565 #define ICALL(id,name,func)
7567 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7568 #include "metadata/icall-def.h"
7570 } icall_type_names_str
= {
7571 #define ICALL_TYPE(id,name,first) (name),
7572 #include "metadata/icall-def.h"
7575 static const guint16 icall_type_names_idx
[] = {
7576 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7577 #include "metadata/icall-def.h"
7580 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7582 static const struct msgstr_t
{
7584 #define ICALL_TYPE(id,name,first)
7585 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7586 #include "metadata/icall-def.h"
7588 } icall_names_str
= {
7589 #define ICALL(id,name,func) (name),
7590 #include "metadata/icall-def.h"
7593 static const guint16 icall_names_idx
[] = {
7594 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7595 #include "metadata/icall-def.h"
7598 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7604 #define ICALL_TYPE(id,name,first) name,
7605 #define ICALL(id,name,func)
7606 static const char* const
7607 icall_type_names
[] = {
7608 #include "metadata/icall-def.h"
7612 #define icall_type_name_get(id) (icall_type_names [(id)])
7616 #define ICALL_TYPE(id,name,first)
7617 #define ICALL(id,name,func) name,
7618 static const char* const
7620 #include "metadata/icall-def.h"
7623 #define icall_name_get(id) icall_names [(id)]
7625 #endif /* !HAVE_ARRAY_ELEM_INIT */
7629 #define ICALL_TYPE(id,name,first)
7630 #define ICALL(id,name,func) func,
7631 static const gconstpointer
7632 icall_functions
[] = {
7633 #include "metadata/icall-def.h"
7637 static GHashTable
*icall_hash
= NULL
;
7638 static GHashTable
*jit_icall_hash_name
= NULL
;
7639 static GHashTable
*jit_icall_hash_addr
= NULL
;
7642 mono_icall_init (void)
7646 /* check that tables are sorted: disable in release */
7649 const char *prev_class
= NULL
;
7650 const char *prev_method
;
7652 for (i
= 0; i
< Icall_type_num
; ++i
) {
7653 const IcallTypeDesc
*desc
;
7656 if (prev_class
&& strcmp (prev_class
, icall_type_name_get (i
)) >= 0)
7657 g_print ("class %s should come before class %s\n", icall_type_name_get (i
), prev_class
);
7658 prev_class
= icall_type_name_get (i
);
7659 desc
= &icall_type_descs
[i
];
7660 num_icalls
= icall_desc_num_icalls (desc
);
7661 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7662 for (j
= 0; j
< num_icalls
; ++j
) {
7663 const char *methodn
= icall_name_get (desc
->first_icall
+ j
);
7664 if (prev_method
&& strcmp (prev_method
, methodn
) >= 0)
7665 g_print ("method %s should come before method %s\n", methodn
, prev_method
);
7666 prev_method
= methodn
;
7671 icall_hash
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, NULL
);
7675 mono_icall_cleanup (void)
7677 g_hash_table_destroy (icall_hash
);
7678 g_hash_table_destroy (jit_icall_hash_name
);
7679 g_hash_table_destroy (jit_icall_hash_addr
);
7683 mono_add_internal_call (const char *name
, gconstpointer method
)
7685 mono_loader_lock ();
7687 g_hash_table_insert (icall_hash
, g_strdup (name
), (gpointer
) method
);
7689 mono_loader_unlock ();
7692 #ifdef HAVE_ARRAY_ELEM_INIT
7694 compare_method_imap (const void *key
, const void *elem
)
7696 const char* method_name
= (const char*)&icall_names_str
+ (*(guint16
*)elem
);
7697 return strcmp (key
, method_name
);
7701 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
7703 const guint16
*nameslot
= bsearch (name
, icall_names_idx
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names_idx
[0]), compare_method_imap
);
7706 return (gpointer
)icall_functions
[(nameslot
- &icall_names_idx
[0])];
7710 compare_class_imap (const void *key
, const void *elem
)
7712 const char* class_name
= (const char*)&icall_type_names_str
+ (*(guint16
*)elem
);
7713 return strcmp (key
, class_name
);
7716 static const IcallTypeDesc
*
7717 find_class_icalls (const char *name
)
7719 const guint16
*nameslot
= bsearch (name
, icall_type_names_idx
, Icall_type_num
, sizeof (icall_type_names_idx
[0]), compare_class_imap
);
7722 return &icall_type_descs
[nameslot
- &icall_type_names_idx
[0]];
7727 compare_method_imap (const void *key
, const void *elem
)
7729 const char** method_name
= (const char**)elem
;
7730 return strcmp (key
, *method_name
);
7734 find_method_icall (const IcallTypeDesc
*imap
, const char *name
)
7736 const char **nameslot
= bsearch (name
, icall_names
+ imap
->first_icall
, icall_desc_num_icalls (imap
), sizeof (icall_names
[0]), compare_method_imap
);
7739 return (gpointer
)icall_functions
[(nameslot
- icall_names
)];
7743 compare_class_imap (const void *key
, const void *elem
)
7745 const char** class_name
= (const char**)elem
;
7746 return strcmp (key
, *class_name
);
7749 static const IcallTypeDesc
*
7750 find_class_icalls (const char *name
)
7752 const char **nameslot
= bsearch (name
, icall_type_names
, Icall_type_num
, sizeof (icall_type_names
[0]), compare_class_imap
);
7755 return &icall_type_descs
[nameslot
- icall_type_names
];
7761 * we should probably export this as an helper (handle nested types).
7762 * Returns the number of chars written in buf.
7765 concat_class_name (char *buf
, int bufsize
, MonoClass
*klass
)
7767 int nspacelen
, cnamelen
;
7768 nspacelen
= strlen (klass
->name_space
);
7769 cnamelen
= strlen (klass
->name
);
7770 if (nspacelen
+ cnamelen
+ 2 > bufsize
)
7773 memcpy (buf
, klass
->name_space
, nspacelen
);
7774 buf
[nspacelen
++] = '.';
7776 memcpy (buf
+ nspacelen
, klass
->name
, cnamelen
);
7777 buf
[nspacelen
+ cnamelen
] = 0;
7778 return nspacelen
+ cnamelen
;
7782 mono_lookup_internal_call (MonoMethod
*method
)
7787 int typelen
= 0, mlen
, siglen
;
7789 const IcallTypeDesc
*imap
;
7791 g_assert (method
!= NULL
);
7793 if (method
->is_inflated
)
7794 method
= ((MonoMethodInflated
*) method
)->declaring
;
7796 if (method
->klass
->nested_in
) {
7797 int pos
= concat_class_name (mname
, sizeof (mname
)-2, method
->klass
->nested_in
);
7801 mname
[pos
++] = '/';
7804 typelen
= concat_class_name (mname
+pos
, sizeof (mname
)-pos
-1, method
->klass
);
7810 typelen
= concat_class_name (mname
, sizeof (mname
), method
->klass
);
7815 imap
= find_class_icalls (mname
);
7817 mname
[typelen
] = ':';
7818 mname
[typelen
+ 1] = ':';
7820 mlen
= strlen (method
->name
);
7821 memcpy (mname
+ typelen
+ 2, method
->name
, mlen
);
7822 sigstart
= mname
+ typelen
+ 2 + mlen
;
7825 tmpsig
= mono_signature_get_desc (mono_method_signature (method
), TRUE
);
7826 siglen
= strlen (tmpsig
);
7827 if (typelen
+ mlen
+ siglen
+ 6 > sizeof (mname
))
7830 memcpy (sigstart
+ 1, tmpsig
, siglen
);
7831 sigstart
[siglen
+ 1] = ')';
7832 sigstart
[siglen
+ 2] = 0;
7835 mono_loader_lock ();
7837 res
= g_hash_table_lookup (icall_hash
, mname
);
7839 mono_loader_unlock ();
7842 /* try without signature */
7844 res
= g_hash_table_lookup (icall_hash
, mname
);
7846 mono_loader_unlock ();
7850 /* it wasn't found in the static call tables */
7852 mono_loader_unlock ();
7855 res
= find_method_icall (imap
, sigstart
- mlen
);
7857 mono_loader_unlock ();
7860 /* try _with_ signature */
7862 res
= find_method_icall (imap
, sigstart
- mlen
);
7864 mono_loader_unlock ();
7868 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname
);
7869 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7870 g_print ("The out of sync library is: %s\n", method
->klass
->image
->name
);
7871 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7872 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");
7873 g_print ("If you see other errors or faults after this message they are probably related\n");
7874 g_print ("and you need to fix your mono install first.\n");
7876 mono_loader_unlock ();
7882 type_from_typename (char *typename
)
7884 MonoClass
*klass
= NULL
; /* assignment to shut GCC warning up */
7886 if (!strcmp (typename
, "int"))
7887 klass
= mono_defaults
.int_class
;
7888 else if (!strcmp (typename
, "ptr"))
7889 klass
= mono_defaults
.int_class
;
7890 else if (!strcmp (typename
, "void"))
7891 klass
= mono_defaults
.void_class
;
7892 else if (!strcmp (typename
, "int32"))
7893 klass
= mono_defaults
.int32_class
;
7894 else if (!strcmp (typename
, "uint32"))
7895 klass
= mono_defaults
.uint32_class
;
7896 else if (!strcmp (typename
, "int8"))
7897 klass
= mono_defaults
.sbyte_class
;
7898 else if (!strcmp (typename
, "uint8"))
7899 klass
= mono_defaults
.byte_class
;
7900 else if (!strcmp (typename
, "int16"))
7901 klass
= mono_defaults
.int16_class
;
7902 else if (!strcmp (typename
, "uint16"))
7903 klass
= mono_defaults
.uint16_class
;
7904 else if (!strcmp (typename
, "long"))
7905 klass
= mono_defaults
.int64_class
;
7906 else if (!strcmp (typename
, "ulong"))
7907 klass
= mono_defaults
.uint64_class
;
7908 else if (!strcmp (typename
, "float"))
7909 klass
= mono_defaults
.single_class
;
7910 else if (!strcmp (typename
, "double"))
7911 klass
= mono_defaults
.double_class
;
7912 else if (!strcmp (typename
, "object"))
7913 klass
= mono_defaults
.object_class
;
7914 else if (!strcmp (typename
, "obj"))
7915 klass
= mono_defaults
.object_class
;
7916 else if (!strcmp (typename
, "string"))
7917 klass
= mono_defaults
.string_class
;
7918 else if (!strcmp (typename
, "bool"))
7919 klass
= mono_defaults
.boolean_class
;
7920 else if (!strcmp (typename
, "boolean"))
7921 klass
= mono_defaults
.boolean_class
;
7923 g_error ("%s", typename
);
7924 g_assert_not_reached ();
7926 return &klass
->byval_arg
;
7929 MonoMethodSignature
*
7930 mono_create_icall_signature (const char *sigstr
)
7935 MonoMethodSignature
*res
;
7937 mono_loader_lock ();
7938 res
= g_hash_table_lookup (mono_defaults
.corlib
->helper_signatures
, sigstr
);
7940 mono_loader_unlock ();
7944 parts
= g_strsplit (sigstr
, " ", 256);
7953 res
= mono_metadata_signature_alloc (mono_defaults
.corlib
, len
- 1);
7958 * Under windows, the default pinvoke calling convention is STDCALL but
7961 res
->call_convention
= MONO_CALL_C
;
7964 res
->ret
= type_from_typename (parts
[0]);
7965 for (i
= 1; i
< len
; ++i
) {
7966 res
->params
[i
- 1] = type_from_typename (parts
[i
]);
7971 g_hash_table_insert (mono_defaults
.corlib
->helper_signatures
, (gpointer
)sigstr
, res
);
7973 mono_loader_unlock ();
7979 mono_find_jit_icall_by_name (const char *name
)
7981 MonoJitICallInfo
*info
;
7982 g_assert (jit_icall_hash_name
);
7984 mono_loader_lock ();
7985 info
= g_hash_table_lookup (jit_icall_hash_name
, name
);
7986 mono_loader_unlock ();
7991 mono_find_jit_icall_by_addr (gconstpointer addr
)
7993 MonoJitICallInfo
*info
;
7994 g_assert (jit_icall_hash_addr
);
7996 mono_loader_lock ();
7997 info
= g_hash_table_lookup (jit_icall_hash_addr
, (gpointer
)addr
);
7998 mono_loader_unlock ();
8004 * mono_get_jit_icall_info:
8006 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8007 * caller should access it while holding the loader lock.
8010 mono_get_jit_icall_info (void)
8012 return jit_icall_hash_name
;
8016 mono_register_jit_icall_wrapper (MonoJitICallInfo
*info
, gconstpointer wrapper
)
8018 mono_loader_lock ();
8019 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)wrapper
, info
);
8020 mono_loader_unlock ();
8024 mono_register_jit_icall (gconstpointer func
, const char *name
, MonoMethodSignature
*sig
, gboolean is_save
)
8026 MonoJitICallInfo
*info
;
8031 mono_loader_lock ();
8033 if (!jit_icall_hash_name
) {
8034 jit_icall_hash_name
= g_hash_table_new_full (g_str_hash
, g_str_equal
, NULL
, g_free
);
8035 jit_icall_hash_addr
= g_hash_table_new (NULL
, NULL
);
8038 if (g_hash_table_lookup (jit_icall_hash_name
, name
)) {
8039 g_warning ("jit icall already defined \"%s\"\n", name
);
8040 g_assert_not_reached ();
8043 info
= g_new0 (MonoJitICallInfo
, 1);
8050 info
->wrapper
= func
;
8052 info
->wrapper
= NULL
;
8055 g_hash_table_insert (jit_icall_hash_name
, (gpointer
)info
->name
, info
);
8056 g_hash_table_insert (jit_icall_hash_addr
, (gpointer
)func
, info
);
8058 mono_loader_unlock ();