5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HAVE_WCHAR_H)
34 #include "mono/metadata/icall-internals.h"
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool-ms.h>
40 #include <mono/metadata/threadpool-ms-io.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/image-internals.h>
44 #include <mono/metadata/assembly.h>
45 #include <mono/metadata/assembly-internals.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/w32process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/metadata/handle.h>
85 #include <mono/metadata/w32mutex.h>
86 #include <mono/metadata/w32semaphore.h>
87 #include <mono/metadata/w32event.h>
88 #include <mono/io-layer/io-layer.h>
89 #include <mono/utils/monobitset.h>
90 #include <mono/utils/mono-time.h>
91 #include <mono/utils/mono-proclib.h>
92 #include <mono/utils/mono-string.h>
93 #include <mono/utils/mono-error-internals.h>
94 #include <mono/utils/mono-mmap.h>
95 #include <mono/utils/mono-io-portability.h>
96 #include <mono/utils/mono-digest.h>
97 #include <mono/utils/bsearch.h>
98 #include <mono/utils/mono-os-mutex.h>
99 #include <mono/utils/mono-threads.h>
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_for_class_failure (error, klass);
140 mono_icall_make_platform_path (gchar *path)
145 static inline const gchar *
146 mono_icall_get_file_path_prefix (const gchar *path)
150 #endif /* HOST_WIN32 */
152 ICALL_EXPORT MonoObject *
153 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
159 MonoObject *result = NULL;
161 ac = (MonoClass *)arr->obj.vtable->klass;
163 esize = mono_array_element_size (ac);
164 ea = (gpointer*)((char*)arr->vector + (pos * esize));
166 if (ac->element_class->valuetype) {
167 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
168 mono_error_set_pending_exception (&error);
170 result = (MonoObject *)*ea;
174 ICALL_EXPORT MonoObject *
175 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
181 MONO_CHECK_ARG_NULL (idxs, NULL);
184 ic = (MonoClass *)io->obj.vtable->klass;
186 ac = (MonoClass *)arr->obj.vtable->klass;
188 g_assert (ic->rank == 1);
189 if (io->bounds != NULL || io->max_length != ac->rank) {
190 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
194 ind = (gint32 *)io->vector;
196 if (arr->bounds == NULL) {
197 if (*ind < 0 || *ind >= arr->max_length) {
198 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
202 return ves_icall_System_Array_GetValueImpl (arr, *ind);
205 for (i = 0; i < ac->rank; i++) {
206 if ((ind [i] < arr->bounds [i].lower_bound) ||
207 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
208 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
213 pos = ind [0] - arr->bounds [0].lower_bound;
214 for (i = 1; i < ac->rank; i++)
215 pos = pos * arr->bounds [i].length + ind [i] -
216 arr->bounds [i].lower_bound;
218 return ves_icall_System_Array_GetValueImpl (arr, pos);
222 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
225 MonoClass *ac, *vc, *ec;
234 mono_error_init (&error);
237 vc = value->vtable->klass;
241 ac = arr->obj.vtable->klass;
242 ec = ac->element_class;
244 esize = mono_array_element_size (ac);
245 ea = (gpointer*)((char*)arr->vector + (pos * esize));
246 va = (gpointer*)((char*)value + sizeof (MonoObject));
248 if (mono_class_is_nullable (ec)) {
249 mono_nullable_init ((guint8*)ea, value, ec);
254 mono_gc_bzero_atomic (ea, esize);
258 #define NO_WIDENING_CONVERSION G_STMT_START{\
259 mono_set_pending_exception (mono_get_exception_argument ( \
260 "value", "not a widening conversion")); \
264 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
265 if (esize < vsize + (extra)) { \
266 mono_set_pending_exception (mono_get_exception_argument ( \
267 "value", "not a widening conversion")); \
272 #define INVALID_CAST G_STMT_START{ \
273 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
274 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
278 /* Check element (destination) type. */
279 switch (ec->byval_arg.type) {
280 case MONO_TYPE_STRING:
281 switch (vc->byval_arg.type) {
282 case MONO_TYPE_STRING:
288 case MONO_TYPE_BOOLEAN:
289 switch (vc->byval_arg.type) {
290 case MONO_TYPE_BOOLEAN:
303 NO_WIDENING_CONVERSION;
312 if (!ec->valuetype) {
313 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
314 if (mono_error_set_pending_exception (&error))
318 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
322 if (mono_object_isinst_checked (value, ec, &error)) {
323 if (ec->has_references)
324 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
326 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
329 if (mono_error_set_pending_exception (&error))
335 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
337 et = ec->byval_arg.type;
338 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
339 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
341 vt = vc->byval_arg.type;
342 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
343 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
345 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
351 case MONO_TYPE_CHAR: \
352 CHECK_WIDENING_CONVERSION(0); \
353 *(etype *) ea = (etype) u64; \
355 /* You can't assign a signed value to an unsigned array. */ \
360 /* You can't assign a floating point number to an integer array. */ \
363 NO_WIDENING_CONVERSION; \
367 #define ASSIGN_SIGNED(etype) G_STMT_START{\
373 CHECK_WIDENING_CONVERSION(0); \
374 *(etype *) ea = (etype) i64; \
376 /* You can assign an unsigned value to a signed array if the array's */ \
377 /* element size is larger than the value size. */ \
382 case MONO_TYPE_CHAR: \
383 CHECK_WIDENING_CONVERSION(1); \
384 *(etype *) ea = (etype) u64; \
386 /* You can't assign a floating point number to an integer array. */ \
389 NO_WIDENING_CONVERSION; \
393 #define ASSIGN_REAL(etype) G_STMT_START{\
397 CHECK_WIDENING_CONVERSION(0); \
398 *(etype *) ea = (etype) r64; \
400 /* All integer values fit into a floating point array, so we don't */ \
401 /* need to CHECK_WIDENING_CONVERSION here. */ \
406 *(etype *) ea = (etype) i64; \
412 case MONO_TYPE_CHAR: \
413 *(etype *) ea = (etype) u64; \
420 u64 = *(guint8 *) va;
423 u64 = *(guint16 *) va;
426 u64 = *(guint32 *) va;
429 u64 = *(guint64 *) va;
435 i64 = *(gint16 *) va;
438 i64 = *(gint32 *) va;
441 i64 = *(gint64 *) va;
444 r64 = *(gfloat *) va;
447 r64 = *(gdouble *) va;
450 u64 = *(guint16 *) va;
452 case MONO_TYPE_BOOLEAN:
453 /* Boolean is only compatible with itself. */
466 NO_WIDENING_CONVERSION;
473 /* If we can't do a direct copy, let's try a widening conversion. */
476 ASSIGN_UNSIGNED (guint16);
478 ASSIGN_UNSIGNED (guint8);
480 ASSIGN_UNSIGNED (guint16);
482 ASSIGN_UNSIGNED (guint32);
484 ASSIGN_UNSIGNED (guint64);
486 ASSIGN_SIGNED (gint8);
488 ASSIGN_SIGNED (gint16);
490 ASSIGN_SIGNED (gint32);
492 ASSIGN_SIGNED (gint64);
494 ASSIGN_REAL (gfloat);
496 ASSIGN_REAL (gdouble);
500 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
504 #undef NO_WIDENING_CONVERSION
505 #undef CHECK_WIDENING_CONVERSION
506 #undef ASSIGN_UNSIGNED
512 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
518 MONO_CHECK_ARG_NULL (idxs,);
520 ic = idxs->obj.vtable->klass;
521 ac = arr->obj.vtable->klass;
523 g_assert (ic->rank == 1);
524 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
525 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
529 ind = (gint32 *)idxs->vector;
531 if (arr->bounds == NULL) {
532 if (*ind < 0 || *ind >= arr->max_length) {
533 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
537 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
541 for (i = 0; i < ac->rank; i++)
542 if ((ind [i] < arr->bounds [i].lower_bound) ||
543 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
544 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
548 pos = ind [0] - arr->bounds [0].lower_bound;
549 for (i = 1; i < ac->rank; i++)
550 pos = pos * arr->bounds [i].length + ind [i] -
551 arr->bounds [i].lower_bound;
553 ves_icall_System_Array_SetValueImpl (arr, value, pos);
556 ICALL_EXPORT MonoArray *
557 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
560 MonoClass *aklass, *klass;
563 gboolean bounded = FALSE;
565 MONO_CHECK_ARG_NULL (type, NULL);
566 MONO_CHECK_ARG_NULL (lengths, NULL);
568 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
570 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
572 for (i = 0; i < mono_array_length (lengths); i++) {
573 if (mono_array_get (lengths, gint32, i) < 0) {
574 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
579 klass = mono_class_from_mono_type (type->type);
580 mono_class_init_checked (klass, &error);
581 if (mono_error_set_pending_exception (&error))
584 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
585 /* vectors are not the same as one dimensional arrays with no-zero bounds */
590 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
592 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
593 for (i = 0; i < aklass->rank; ++i) {
594 sizes [i] = mono_array_get (lengths, guint32, i);
596 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
598 sizes [i + aklass->rank] = 0;
601 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
602 mono_error_set_pending_exception (&error);
607 ICALL_EXPORT MonoArray *
608 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
611 MonoClass *aklass, *klass;
614 gboolean bounded = FALSE;
616 MONO_CHECK_ARG_NULL (type, NULL);
617 MONO_CHECK_ARG_NULL (lengths, NULL);
619 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
621 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
623 for (i = 0; i < mono_array_length (lengths); i++) {
624 if ((mono_array_get (lengths, gint64, i) < 0) ||
625 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
626 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
631 klass = mono_class_from_mono_type (type->type);
632 mono_class_init_checked (klass, &error);
633 if (mono_error_set_pending_exception (&error))
636 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
637 /* vectors are not the same as one dimensional arrays with no-zero bounds */
642 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
644 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
645 for (i = 0; i < aklass->rank; ++i) {
646 sizes [i] = mono_array_get (lengths, guint64, i);
648 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
650 sizes [i + aklass->rank] = 0;
653 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
654 mono_error_set_pending_exception (&error);
660 ves_icall_System_Array_GetRank (MonoObject *arr)
662 return arr->vtable->klass->rank;
666 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
668 gint32 rank = arr->obj.vtable->klass->rank;
671 if ((dimension < 0) || (dimension >= rank)) {
672 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
676 if (arr->bounds == NULL)
677 length = arr->max_length;
679 length = arr->bounds [dimension].length;
681 #ifdef MONO_BIG_ARRAYS
682 if (length > G_MAXINT32) {
683 mono_set_pending_exception (mono_get_exception_overflow ());
691 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
693 gint32 rank = arr->obj.vtable->klass->rank;
695 if ((dimension < 0) || (dimension >= rank)) {
696 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
700 if (arr->bounds == NULL)
701 return arr->max_length;
703 return arr->bounds [dimension].length;
707 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
709 gint32 rank = arr->obj.vtable->klass->rank;
711 if ((dimension < 0) || (dimension >= rank)) {
712 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
716 if (arr->bounds == NULL)
719 return arr->bounds [dimension].lower_bound;
723 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
725 int sz = mono_array_element_size (mono_object_class (arr));
726 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
729 ICALL_EXPORT MonoArray*
730 ves_icall_System_Array_Clone (MonoArray *arr)
733 MonoArray *result = mono_array_clone_checked (arr, &error);
734 mono_error_set_pending_exception (&error);
738 ICALL_EXPORT gboolean
739 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
744 MonoVTable *src_vtable;
745 MonoVTable *dest_vtable;
746 MonoClass *src_class;
747 MonoClass *dest_class;
749 src_vtable = source->obj.vtable;
750 dest_vtable = dest->obj.vtable;
752 if (src_vtable->rank != dest_vtable->rank)
755 if (source->bounds || dest->bounds)
758 /* there's no integer overflow since mono_array_length returns an unsigned integer */
759 if ((dest_idx + length > mono_array_length_fast (dest)) ||
760 (source_idx + length > mono_array_length_fast (source)))
763 src_class = src_vtable->klass->element_class;
764 dest_class = dest_vtable->klass->element_class;
767 * Handle common cases.
770 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
771 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
773 if (src_class == mono_defaults.object_class && dest_class->valuetype)
776 /* Check if we're copying a char[] <==> (u)short[] */
777 if (src_class != dest_class) {
778 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
781 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
782 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
786 if (dest_class->valuetype) {
787 element_size = mono_array_element_size (source->obj.vtable->klass);
788 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
789 if (dest_class->has_references) {
790 mono_value_copy_array (dest, dest_idx, source_addr, length);
792 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
793 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
796 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
803 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
809 ac = (MonoClass *)arr->obj.vtable->klass;
811 esize = mono_array_element_size (ac);
812 ea = (gpointer*)((char*)arr->vector + (pos * esize));
814 mono_gc_memmove_atomic (value, ea, esize);
818 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
824 ac = (MonoClass *)arr->obj.vtable->klass;
825 ec = ac->element_class;
827 esize = mono_array_element_size (ac);
828 ea = (gpointer*)((char*)arr->vector + (pos * esize));
830 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
831 g_assert (esize == sizeof (gpointer));
832 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
834 g_assert (ec->inited);
835 g_assert (esize == mono_class_value_size (ec, NULL));
836 if (ec->has_references)
837 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
839 mono_gc_memmove_atomic (ea, value, esize);
844 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
846 MonoClass *klass = array->obj.vtable->klass;
847 guint32 size = mono_array_element_size (klass);
848 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
850 const char *field_data;
852 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
853 MonoException *exc = mono_get_exception_argument("array",
854 "Cannot initialize array of non-primitive type.");
855 mono_set_pending_exception (exc);
859 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
860 MonoException *exc = mono_get_exception_argument("field_handle",
861 "Field doesn't have an RVA");
862 mono_set_pending_exception (exc);
866 size *= array->max_length;
867 field_data = mono_field_get_data (field_handle);
869 if (size > mono_type_size (field_handle->type, &align)) {
870 MonoException *exc = mono_get_exception_argument("field_handle",
871 "Field not large enough to fill array");
872 mono_set_pending_exception (exc);
876 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
878 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
879 guint ## n *src = (guint ## n *) field_data; \
881 nEnt = (size / sizeof(guint ## n)); \
883 for (i = 0; i < nEnt; i++) { \
884 data[i] = read ## n (&src[i]); \
888 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
890 switch (type->type) {
907 memcpy (mono_array_addr (array, char, 0), field_data, size);
911 memcpy (mono_array_addr (array, char, 0), field_data, size);
916 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
918 return offsetof (MonoString, chars);
921 ICALL_EXPORT MonoObject *
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
924 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
928 MonoObject *ret = mono_object_clone_checked (obj, &error);
929 mono_error_set_pending_exception (&error);
936 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
942 MONO_CHECK_ARG_NULL (handle,);
944 klass = mono_class_from_mono_type (handle);
945 MONO_CHECK_ARG (handle, klass,);
947 if (mono_class_is_gtd (klass))
950 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
951 if (!is_ok (&error)) {
952 mono_error_set_pending_exception (&error);
956 /* This will call the type constructor */
957 if (!mono_runtime_class_init_full (vtable, &error))
958 mono_error_set_pending_exception (&error);
962 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
966 mono_image_check_for_module_cctor (image);
967 if (image->has_module_cctor) {
968 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
969 if (!mono_error_ok (&error)) {
970 mono_error_set_pending_exception (&error);
973 /*It's fine to raise the exception here*/
974 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
975 if (!is_ok (&error)) {
976 mono_error_set_pending_exception (&error);
979 if (!mono_runtime_class_init_full (vtable, &error))
980 mono_error_set_pending_exception (&error);
984 ICALL_EXPORT MonoBoolean
985 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
987 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
988 // It does not work on win32
994 MonoInternalThread *thread;
996 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
997 /* if we have no info we are optimistic and assume there is enough room */
1001 thread = mono_thread_internal_current ();
1002 // .net seems to check that at least 50% of stack is available
1003 min_size = thread->stack_size / 2;
1005 current = (guint8 *)&stack_addr;
1006 if (current > stack_addr) {
1007 if ((current - stack_addr) < min_size)
1010 if (current - (stack_addr - stack_size) < min_size)
1017 ICALL_EXPORT MonoObject *
1018 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1021 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1022 mono_error_set_pending_exception (&error);
1028 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1032 MonoObject **values = NULL;
1035 gint32 result = (int)(gsize)mono_defaults.int32_class;
1036 MonoClassField* field;
1039 klass = mono_object_class (this_obj);
1041 if (mono_class_num_fields (klass) == 0)
1045 * Compute the starting value of the hashcode for fields of primitive
1046 * types, and return the remaining fields in an array to the managed side.
1047 * This way, we can avoid costly reflection operations in managed code.
1050 while ((field = mono_class_get_fields (klass, &iter))) {
1051 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1053 if (mono_field_is_deleted (field))
1055 /* FIXME: Add more types */
1056 switch (field->type->type) {
1058 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1060 case MONO_TYPE_STRING: {
1062 s = *(MonoString**)((guint8*)this_obj + field->offset);
1064 result ^= mono_string_hash (s);
1069 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1070 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1071 if (!is_ok (&error)) {
1072 mono_error_set_pending_exception (&error);
1075 values [count++] = o;
1081 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1082 if (mono_error_set_pending_exception (&error))
1084 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1085 for (i = 0; i < count; ++i)
1086 mono_array_setref (*fields, i, values [i]);
1093 ICALL_EXPORT MonoBoolean
1094 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1098 MonoObject **values = NULL;
1100 MonoClassField* field;
1104 MONO_CHECK_ARG_NULL (that, FALSE);
1106 if (this_obj->vtable != that->vtable)
1109 klass = mono_object_class (this_obj);
1111 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1112 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1115 * Do the comparison for fields of primitive type and return a result if
1116 * possible. Otherwise, return the remaining fields in an array to the
1117 * managed side. This way, we can avoid costly reflection operations in
1122 while ((field = mono_class_get_fields (klass, &iter))) {
1123 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1125 if (mono_field_is_deleted (field))
1127 /* FIXME: Add more types */
1128 switch (field->type->type) {
1131 case MONO_TYPE_BOOLEAN:
1132 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1137 case MONO_TYPE_CHAR:
1138 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1143 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1148 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1152 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1156 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1161 case MONO_TYPE_STRING: {
1162 MonoString *s1, *s2;
1163 guint32 s1len, s2len;
1164 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1165 s2 = *(MonoString**)((guint8*)that + field->offset);
1168 if ((s1 == NULL) || (s2 == NULL))
1170 s1len = mono_string_length (s1);
1171 s2len = mono_string_length (s2);
1175 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1181 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1182 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1183 if (!is_ok (&error)) {
1184 mono_error_set_pending_exception (&error);
1187 values [count++] = o;
1188 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1189 if (!is_ok (&error)) {
1190 mono_error_set_pending_exception (&error);
1193 values [count++] = o;
1196 if (klass->enumtype)
1197 /* enums only have one non-static field */
1203 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1204 if (mono_error_set_pending_exception (&error))
1206 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1207 for (i = 0; i < count; ++i)
1208 mono_array_setref_fast (*fields, i, values [i]);
1215 ICALL_EXPORT MonoReflectionType *
1216 ves_icall_System_Object_GetType (MonoObject *obj)
1219 MonoReflectionType *ret;
1220 #ifndef DISABLE_REMOTING
1221 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1222 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1225 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1227 mono_error_set_pending_exception (&error);
1232 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1234 MonoMethod **dest = (MonoMethod **)data;
1236 /* skip unmanaged frames */
1241 if (!strcmp (m->klass->name_space, "System.Reflection"))
1250 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1252 MonoMethod **dest = (MonoMethod **)data;
1254 /* skip unmanaged frames */
1258 if (m->wrapper_type != MONO_WRAPPER_NONE)
1266 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1277 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1279 MonoMethod **dest = (MonoMethod **)data;
1281 /* skip unmanaged frames */
1285 if (m->wrapper_type != MONO_WRAPPER_NONE)
1293 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1294 || (!strcmp (m->klass->name_space, "System"))))
1304 static MonoReflectionType *
1305 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoAssembly **caller_assembly, MonoError *error)
1307 MonoMethod *m, *dest;
1309 MonoType *type = NULL;
1310 MonoAssembly *assembly = NULL;
1311 gboolean type_resolve = FALSE;
1312 MonoImage *rootimage = NULL;
1314 mono_error_init (error);
1317 * We must compute the calling assembly as type loading must happen under a metadata context.
1318 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1319 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1321 m = mono_method_get_last_managed ();
1323 if (m && m->klass->image != mono_defaults.corlib) {
1324 /* Happens with inlining */
1326 /* Ugly hack: type_from_parsed_name is called from
1327 * System.Type.internal_from_name, which is called most
1328 * directly from System.Type.GetType(string,bool,bool) but
1329 * also indirectly from places such as
1330 * System.Type.GetType(string,func,func) (via
1331 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1332 * so we need to skip over all of those to find the true caller.
1334 * It would be nice if we had stack marks.
1336 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1342 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1343 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1344 * to crash. This only seems to happen in some strange remoting
1345 * scenarios and I was unable to figure out what's happening there.
1346 * Dec 10, 2005 - Martin.
1350 assembly = dest->klass->image->assembly;
1351 type_resolve = TRUE;
1352 rootimage = assembly->image;
1354 g_warning (G_STRLOC);
1356 *caller_assembly = assembly;
1358 if (info->assembly.name)
1359 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1362 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1363 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1364 return_val_if_nok (error, NULL);
1368 // Say we're looking for System.Generic.Dict<int, Local>
1369 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1370 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1371 // is messed up when we go to construct the Local as the type arg...
1373 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1374 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1375 if (!info->assembly.name && !type) {
1377 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1378 return_val_if_nok (error, NULL);
1380 if (assembly && !type && type_resolve) {
1381 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1382 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1383 return_val_if_nok (error, NULL);
1389 return mono_type_get_object_checked (mono_domain_get (), type, error);
1392 ICALL_EXPORT MonoReflectionType*
1393 ves_icall_System_Type_internal_from_name (MonoString *name,
1394 MonoBoolean throwOnError,
1395 MonoBoolean ignoreCase)
1398 MonoTypeNameParse info;
1399 MonoReflectionType *type = NULL;
1401 MonoAssembly *caller_assembly;
1403 char *str = mono_string_to_utf8_checked (name, &error);
1404 if (!is_ok (&error))
1407 parsedOk = mono_reflection_parse_type (str, &info);
1409 /* mono_reflection_parse_type() mangles the string */
1411 mono_reflection_free_type_info (&info);
1413 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1417 type = type_from_parsed_name (&info, ignoreCase, &caller_assembly, &error);
1419 if (!is_ok (&error)) {
1420 mono_reflection_free_type_info (&info);
1426 char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name);
1428 if (info.assembly.name)
1429 aname = mono_stringify_assembly_name (&info.assembly);
1430 else if (caller_assembly)
1431 aname = mono_stringify_assembly_name (mono_assembly_get_name (caller_assembly));
1433 aname = g_strdup ("");
1434 mono_error_set_type_load_name (&error, tname, aname, "");
1436 mono_reflection_free_type_info (&info);
1442 if (!is_ok (&error)) {
1444 mono_error_set_pending_exception (&error);
1446 mono_error_cleanup (&error);
1454 ICALL_EXPORT MonoReflectionType*
1455 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1458 MonoReflectionType *ret;
1459 MonoDomain *domain = mono_domain_get ();
1461 ret = mono_type_get_object_checked (domain, handle, &error);
1462 mono_error_set_pending_exception (&error);
1467 ICALL_EXPORT MonoType*
1468 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1470 return mono_class_get_type (klass);
1474 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1476 g_ptr_array_free (ptr_array, TRUE);
1480 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1486 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1489 char *res = mono_string_to_utf8_checked (s, &error);
1490 mono_error_set_pending_exception (&error);
1494 /* System.TypeCode */
1513 TYPECODE_STRING = 18
1516 ICALL_EXPORT guint32
1517 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1519 int t = type->type->type;
1521 if (type->type->byref)
1522 return TYPECODE_OBJECT;
1526 case MONO_TYPE_VOID:
1527 return TYPECODE_OBJECT;
1528 case MONO_TYPE_BOOLEAN:
1529 return TYPECODE_BOOLEAN;
1531 return TYPECODE_BYTE;
1533 return TYPECODE_SBYTE;
1535 return TYPECODE_UINT16;
1537 return TYPECODE_INT16;
1538 case MONO_TYPE_CHAR:
1539 return TYPECODE_CHAR;
1543 return TYPECODE_OBJECT;
1545 return TYPECODE_UINT32;
1547 return TYPECODE_INT32;
1549 return TYPECODE_UINT64;
1551 return TYPECODE_INT64;
1553 return TYPECODE_SINGLE;
1555 return TYPECODE_DOUBLE;
1556 case MONO_TYPE_VALUETYPE: {
1557 MonoClass *klass = type->type->data.klass;
1559 if (klass->enumtype) {
1560 t = mono_class_enum_basetype (klass)->type;
1562 } else if (mono_is_corlib_image (klass->image)) {
1563 if (strcmp (klass->name_space, "System") == 0) {
1564 if (strcmp (klass->name, "Decimal") == 0)
1565 return TYPECODE_DECIMAL;
1566 else if (strcmp (klass->name, "DateTime") == 0)
1567 return TYPECODE_DATETIME;
1570 return TYPECODE_OBJECT;
1572 case MONO_TYPE_STRING:
1573 return TYPECODE_STRING;
1574 case MONO_TYPE_SZARRAY:
1575 case MONO_TYPE_ARRAY:
1576 case MONO_TYPE_OBJECT:
1578 case MONO_TYPE_MVAR:
1579 case MONO_TYPE_TYPEDBYREF:
1580 return TYPECODE_OBJECT;
1581 case MONO_TYPE_CLASS:
1583 MonoClass *klass = type->type->data.klass;
1584 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1585 if (strcmp (klass->name, "DBNull") == 0)
1586 return TYPECODE_DBNULL;
1589 return TYPECODE_OBJECT;
1590 case MONO_TYPE_GENERICINST:
1591 return TYPECODE_OBJECT;
1593 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1599 mono_type_is_primitive (MonoType *type)
1601 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1602 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1606 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1608 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1609 return mono_class_enum_basetype (type->data.klass);
1610 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1611 return mono_class_enum_basetype (type->data.generic_class->container_class);
1615 ICALL_EXPORT guint32
1616 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1621 g_assert (type != NULL);
1623 klass = mono_class_from_mono_type (type->type);
1624 klassc = mono_class_from_mono_type (c->type);
1626 if (type->type->byref ^ c->type->byref)
1629 if (type->type->byref) {
1630 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1631 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1633 klass = mono_class_from_mono_type (t);
1634 klassc = mono_class_from_mono_type (ot);
1636 if (mono_type_is_primitive (t)) {
1637 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1638 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1639 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1640 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1641 return t->type == ot->type;
1643 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1646 if (klass->valuetype)
1647 return klass == klassc;
1648 return klass->valuetype == klassc->valuetype;
1651 return mono_class_is_assignable_from (klass, klassc);
1654 ICALL_EXPORT guint32
1655 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1658 MonoClass *klass = mono_class_from_mono_type (type->type);
1659 mono_class_init_checked (klass, &error);
1660 if (!is_ok (&error)) {
1661 mono_error_set_pending_exception (&error);
1664 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1665 mono_error_set_pending_exception (&error);
1669 ICALL_EXPORT guint32
1670 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1672 MonoClass *klass = mono_class_from_mono_type (type->type);
1673 return mono_class_get_flags (klass);
1676 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1677 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1680 MonoClass *klass = field->field->parent;
1681 MonoMarshalType *info;
1685 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1686 if (mono_class_is_gtd (klass) ||
1687 (gklass && gklass->context.class_inst->is_open))
1690 ftype = mono_field_get_type (field->field);
1691 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1694 info = mono_marshal_load_type_info (klass);
1696 for (i = 0; i < info->num_fields; ++i) {
1697 if (info->fields [i].field == field->field) {
1698 if (!info->fields [i].mspec)
1701 MonoReflectionMarshalAsAttribute* obj;
1702 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1703 if (!mono_error_ok (&error))
1704 mono_error_set_pending_exception (&error);
1713 ICALL_EXPORT MonoReflectionField*
1714 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1717 gboolean found = FALSE;
1723 klass = handle->parent;
1725 klass = mono_class_from_mono_type (type);
1727 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1730 /* The managed code will throw the exception */
1734 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1735 mono_error_set_pending_exception (&error);
1739 ICALL_EXPORT MonoReflectionEvent*
1740 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1748 klass = handle->parent;
1750 klass = mono_class_from_mono_type (type);
1752 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1754 /* Managed code will throw an exception */
1758 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1759 mono_error_set_pending_exception (&error);
1764 ICALL_EXPORT MonoReflectionProperty*
1765 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1773 klass = handle->parent;
1775 klass = mono_class_from_mono_type (type);
1777 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1779 /* Managed code will throw an exception */
1783 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1784 mono_error_set_pending_exception (&error);
1788 ICALL_EXPORT MonoArray*
1789 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1792 MonoType *type = mono_field_get_type_checked (field->field, &error);
1795 if (!mono_error_ok (&error)) {
1796 mono_error_set_pending_exception (&error);
1800 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1801 mono_error_set_pending_exception (&error);
1806 vell_icall_get_method_attributes (MonoMethod *method)
1808 return method->flags;
1812 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1815 MonoReflectionType *rt;
1816 MonoDomain *domain = mono_domain_get ();
1817 MonoMethodSignature* sig;
1819 sig = mono_method_signature_checked (method, &error);
1820 if (!mono_error_ok (&error)) {
1821 mono_error_set_pending_exception (&error);
1825 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1826 if (!mono_error_ok (&error)) {
1827 mono_error_set_pending_exception (&error);
1831 MONO_STRUCT_SETREF (info, parent, rt);
1833 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1834 if (!mono_error_ok (&error)) {
1835 mono_error_set_pending_exception (&error);
1839 MONO_STRUCT_SETREF (info, ret, rt);
1841 info->attrs = method->flags;
1842 info->implattrs = method->iflags;
1843 if (sig->call_convention == MONO_CALL_DEFAULT)
1844 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1846 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1851 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1854 ICALL_EXPORT MonoArray*
1855 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1858 MonoDomain *domain = mono_domain_get ();
1860 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1861 mono_error_set_pending_exception (&error);
1865 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1866 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1869 MonoDomain *domain = mono_domain_get ();
1870 MonoReflectionMarshalAsAttribute* res = NULL;
1871 MonoMarshalSpec **mspecs;
1874 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1875 mono_method_get_marshal_info (method, mspecs);
1878 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1879 if (!mono_error_ok (&error)) {
1880 mono_error_set_pending_exception (&error);
1885 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1887 mono_metadata_free_marshal_spec (mspecs [i]);
1894 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1896 MonoClass *parent = field->field->parent;
1897 mono_class_setup_fields (parent);
1899 return field->field->offset - sizeof (MonoObject);
1902 ICALL_EXPORT MonoReflectionType*
1903 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1906 MonoReflectionType *ret;
1909 parent = declaring? field->field->parent: field->klass;
1911 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1912 mono_error_set_pending_exception (&error);
1918 ICALL_EXPORT MonoObject *
1919 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1922 MonoClass *fklass = field->klass;
1923 MonoClassField *cf = field->field;
1924 MonoDomain *domain = mono_object_domain (field);
1926 if (fklass->image->assembly->ref_only) {
1927 mono_set_pending_exception (mono_get_exception_invalid_operation (
1928 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1932 if (mono_security_core_clr_enabled () &&
1933 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1934 mono_error_set_pending_exception (&error);
1938 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1939 mono_error_set_pending_exception (&error);
1944 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1947 MonoClassField *cf = field->field;
1951 if (field->klass->image->assembly->ref_only) {
1952 mono_set_pending_exception (mono_get_exception_invalid_operation (
1953 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1957 if (mono_security_core_clr_enabled () &&
1958 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1959 mono_error_set_pending_exception (&error);
1963 type = mono_field_get_type_checked (cf, &error);
1964 if (!mono_error_ok (&error)) {
1965 mono_error_set_pending_exception (&error);
1969 v = (gchar *) value;
1971 switch (type->type) {
1974 case MONO_TYPE_BOOLEAN:
1977 case MONO_TYPE_CHAR:
1986 case MONO_TYPE_VALUETYPE:
1989 v += sizeof (MonoObject);
1991 case MONO_TYPE_STRING:
1992 case MONO_TYPE_OBJECT:
1993 case MONO_TYPE_CLASS:
1994 case MONO_TYPE_ARRAY:
1995 case MONO_TYPE_SZARRAY:
1998 case MONO_TYPE_GENERICINST: {
1999 MonoGenericClass *gclass = type->data.generic_class;
2000 g_assert (!gclass->context.class_inst->is_open);
2002 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2003 MonoClass *nklass = mono_class_from_mono_type (type);
2004 MonoObject *nullable;
2007 * Convert the boxed vtype into a Nullable structure.
2008 * This is complicated by the fact that Nullables have
2009 * a variable structure.
2011 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2012 if (!mono_error_ok (&error)) {
2013 mono_error_set_pending_exception (&error);
2017 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2019 v = (gchar *)mono_object_unbox (nullable);
2022 if (gclass->container_class->valuetype && (v != NULL))
2023 v += sizeof (MonoObject);
2027 g_error ("type 0x%x not handled in "
2028 "ves_icall_FieldInfo_SetValueInternal", type->type);
2033 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2034 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2035 if (!is_ok (&error)) {
2036 mono_error_set_pending_exception (&error);
2039 if (!vtable->initialized) {
2040 if (!mono_runtime_class_init_full (vtable, &error)) {
2041 mono_error_set_pending_exception (&error);
2045 mono_field_static_set_value (vtable, cf, v);
2047 mono_field_set_value (obj, cf, v);
2052 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2061 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2062 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2066 if (MONO_TYPE_IS_REFERENCE (f->type))
2067 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2069 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2072 ICALL_EXPORT MonoObject *
2073 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2075 MonoObject *o = NULL;
2076 MonoClassField *field = rfield->field;
2078 MonoDomain *domain = mono_object_domain (rfield);
2080 MonoTypeEnum def_type;
2081 const char *def_value;
2085 mono_class_init (field->parent);
2087 t = mono_field_get_type_checked (field, &error);
2088 if (!mono_error_ok (&error)) {
2089 mono_error_set_pending_exception (&error);
2093 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2094 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2098 if (image_is_dynamic (field->parent->image)) {
2099 MonoClass *klass = field->parent;
2100 int fidx = field - klass->fields;
2101 MonoClassExt *ext = mono_class_get_ext (klass);
2104 g_assert (ext->field_def_values);
2105 def_type = ext->field_def_values [fidx].def_type;
2106 def_value = ext->field_def_values [fidx].data;
2108 if (def_type == MONO_TYPE_END) {
2109 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2113 def_value = mono_class_get_field_default_value (field, &def_type);
2114 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2116 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2121 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2125 case MONO_TYPE_BOOLEAN:
2128 case MONO_TYPE_CHAR:
2136 case MONO_TYPE_R8: {
2139 /* boxed value type */
2140 t = g_new0 (MonoType, 1);
2142 klass = mono_class_from_mono_type (t);
2144 o = mono_object_new_checked (domain, klass, &error);
2145 if (!mono_error_ok (&error)) {
2146 mono_error_set_pending_exception (&error);
2149 v = ((gchar *) o) + sizeof (MonoObject);
2150 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2151 if (mono_error_set_pending_exception (&error))
2155 case MONO_TYPE_STRING:
2156 case MONO_TYPE_CLASS:
2157 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2158 if (mono_error_set_pending_exception (&error))
2162 g_assert_not_reached ();
2168 ICALL_EXPORT MonoReflectionType*
2169 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2172 MonoReflectionType *ret;
2175 type = mono_field_get_type_checked (ref_field->field, &error);
2176 if (!mono_error_ok (&error)) {
2177 mono_error_set_pending_exception (&error);
2181 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2182 if (!mono_error_ok (&error)) {
2183 mono_error_set_pending_exception (&error);
2190 /* From MonoProperty.cs */
2192 PInfo_Attributes = 1,
2193 PInfo_GetMethod = 1 << 1,
2194 PInfo_SetMethod = 1 << 2,
2195 PInfo_ReflectedType = 1 << 3,
2196 PInfo_DeclaringType = 1 << 4,
2201 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2204 MonoReflectionType *rt;
2205 MonoReflectionMethod *rm;
2206 MonoDomain *domain = mono_object_domain (property);
2207 const MonoProperty *pproperty = property->property;
2209 if ((req_info & PInfo_ReflectedType) != 0) {
2210 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2211 if (mono_error_set_pending_exception (&error))
2214 MONO_STRUCT_SETREF (info, parent, rt);
2216 if ((req_info & PInfo_DeclaringType) != 0) {
2217 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2218 if (mono_error_set_pending_exception (&error))
2221 MONO_STRUCT_SETREF (info, declaring_type, rt);
2224 if ((req_info & PInfo_Name) != 0)
2225 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2227 if ((req_info & PInfo_Attributes) != 0)
2228 info->attrs = pproperty->attrs;
2230 if ((req_info & PInfo_GetMethod) != 0) {
2231 if (pproperty->get &&
2232 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2233 pproperty->get->klass == property->klass)) {
2234 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2235 if (mono_error_set_pending_exception (&error))
2241 MONO_STRUCT_SETREF (info, get, rm);
2243 if ((req_info & PInfo_SetMethod) != 0) {
2244 if (pproperty->set &&
2245 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2246 pproperty->set->klass == property->klass)) {
2247 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2248 if (mono_error_set_pending_exception (&error))
2254 MONO_STRUCT_SETREF (info, set, rm);
2257 * There may be other methods defined for properties, though, it seems they are not exposed
2258 * in the reflection API
2263 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2266 MonoReflectionType *rt;
2267 MonoReflectionMethod *rm;
2268 MonoDomain *domain = mono_object_domain (event);
2270 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2271 if (mono_error_set_pending_exception (&error))
2274 MONO_STRUCT_SETREF (info, reflected_type, rt);
2276 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2277 if (mono_error_set_pending_exception (&error))
2280 MONO_STRUCT_SETREF (info, declaring_type, rt);
2282 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2283 info->attrs = event->event->attrs;
2285 if (event->event->add) {
2286 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2287 if (mono_error_set_pending_exception (&error))
2293 MONO_STRUCT_SETREF (info, add_method, rm);
2295 if (event->event->remove) {
2296 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2297 if (mono_error_set_pending_exception (&error))
2303 MONO_STRUCT_SETREF (info, remove_method, rm);
2305 if (event->event->raise) {
2306 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2307 if (mono_error_set_pending_exception (&error))
2313 MONO_STRUCT_SETREF (info, raise_method, rm);
2315 #ifndef MONO_SMALL_CONFIG
2316 if (event->event->other) {
2318 while (event->event->other [n])
2320 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2321 if (mono_error_set_pending_exception (&error))
2323 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2325 for (i = 0; i < n; i++) {
2326 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2327 if (mono_error_set_pending_exception (&error))
2329 mono_array_setref (info->other_methods, i, rm);
2336 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2341 mono_class_setup_interfaces (klass, error);
2342 if (!mono_error_ok (error))
2345 for (i = 0; i < klass->interface_count; i++) {
2346 ic = klass->interfaces [i];
2347 g_hash_table_insert (ifaces, ic, ic);
2349 collect_interfaces (ic, ifaces, error);
2350 if (!mono_error_ok (error))
2356 MonoArray *iface_array;
2357 MonoGenericContext *context;
2361 } FillIfaceArrayData;
2364 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2366 MonoReflectionType *rt;
2367 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2368 MonoClass *ic = (MonoClass *)key;
2369 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2371 if (!mono_error_ok (data->error))
2374 if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
2375 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2376 if (!mono_error_ok (data->error))
2380 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2381 if (!mono_error_ok (data->error))
2384 mono_array_setref (data->iface_array, data->next_idx++, rt);
2387 mono_metadata_free_type (inflated);
2391 get_interfaces_hash (gconstpointer v1)
2393 MonoClass *k = (MonoClass*)v1;
2395 return k->type_token;
2398 ICALL_EXPORT MonoArray*
2399 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2402 MonoClass *klass = mono_class_from_mono_type (type->type);
2404 FillIfaceArrayData data = { 0 };
2407 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2409 if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
2410 data.context = mono_class_get_context (klass);
2411 klass = mono_class_get_generic_class (klass)->container_class;
2414 for (parent = klass; parent; parent = parent->parent) {
2415 mono_class_setup_interfaces (parent, &error);
2416 if (!mono_error_ok (&error))
2418 collect_interfaces (parent, iface_hash, &error);
2419 if (!mono_error_ok (&error))
2423 data.error = &error;
2424 data.domain = mono_object_domain (type);
2426 len = g_hash_table_size (iface_hash);
2428 g_hash_table_destroy (iface_hash);
2429 if (!data.domain->empty_types) {
2430 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2431 if (!is_ok (&error))
2434 return data.domain->empty_types;
2437 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2438 if (!is_ok (&error))
2440 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2441 if (!mono_error_ok (&error))
2444 g_hash_table_destroy (iface_hash);
2445 return data.iface_array;
2448 g_hash_table_destroy (iface_hash);
2449 mono_error_set_pending_exception (&error);
2454 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2456 gboolean variance_used;
2457 MonoClass *klass = mono_class_from_mono_type (type->type);
2458 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2459 MonoReflectionMethod *member;
2462 int i = 0, len, ioffset;
2466 mono_class_init_checked (klass, &error);
2467 if (mono_error_set_pending_exception (&error))
2469 mono_class_init_checked (iclass, &error);
2470 if (mono_error_set_pending_exception (&error))
2473 mono_class_setup_vtable (klass);
2475 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2479 len = mono_class_num_methods (iclass);
2480 domain = mono_object_domain (type);
2481 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2482 if (mono_error_set_pending_exception (&error))
2484 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2485 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2486 if (mono_error_set_pending_exception (&error))
2488 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2490 while ((method = mono_class_get_methods (iclass, &iter))) {
2491 member = mono_method_get_object_checked (domain, method, iclass, &error);
2492 if (mono_error_set_pending_exception (&error))
2494 mono_array_setref (*methods, i, member);
2495 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2496 if (mono_error_set_pending_exception (&error))
2498 mono_array_setref (*targets, i, member);
2505 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2508 MonoClass *klass = mono_class_from_mono_type (type->type);
2510 mono_class_init_checked (klass, &error);
2511 if (mono_error_set_pending_exception (&error))
2514 if (image_is_dynamic (klass->image)) {
2515 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2516 *packing = tb->packing_size;
2517 *size = tb->class_size;
2519 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2523 ICALL_EXPORT MonoReflectionType*
2524 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2527 MonoReflectionType *ret;
2530 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2531 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2532 mono_error_set_pending_exception (&error);
2536 klass = mono_class_from_mono_type (type->type);
2537 mono_class_init_checked (klass, &error);
2538 if (mono_error_set_pending_exception (&error))
2542 // GetElementType should only return a type for:
2543 // Array Pointer PassedByRef
2544 if (type->type->byref)
2545 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2546 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2547 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2548 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2549 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2553 mono_error_set_pending_exception (&error);
2558 ICALL_EXPORT MonoReflectionType*
2559 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2562 MonoReflectionType *ret;
2564 if (type->type->byref)
2567 MonoClass *klass = mono_class_from_mono_type (type->type);
2571 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2572 mono_error_set_pending_exception (&error);
2577 ICALL_EXPORT MonoBoolean
2578 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2580 return type->type->type == MONO_TYPE_PTR;
2583 ICALL_EXPORT MonoBoolean
2584 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2586 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)));
2589 ICALL_EXPORT MonoBoolean
2590 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2592 return type->type->byref;
2595 ICALL_EXPORT MonoBoolean
2596 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2599 MonoClass *klass = mono_class_from_mono_type (type->type);
2600 mono_class_init_checked (klass, &error);
2601 if (mono_error_set_pending_exception (&error))
2604 return mono_class_is_com_object (klass);
2607 ICALL_EXPORT guint32
2608 ves_icall_reflection_get_token (MonoObject* obj)
2611 guint32 result = mono_reflection_get_token_checked (obj, &error);
2612 mono_error_set_pending_exception (&error);
2616 ICALL_EXPORT MonoReflectionModule*
2617 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2620 MonoReflectionModule *result = NULL;
2621 MonoClass *klass = mono_class_from_mono_type (type->type);
2622 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2623 mono_error_set_pending_exception (&error);
2627 ICALL_EXPORT MonoReflectionAssembly*
2628 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2631 MonoDomain *domain = mono_domain_get ();
2632 MonoClass *klass = mono_class_from_mono_type (type->type);
2633 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2634 mono_error_set_pending_exception (&error);
2638 ICALL_EXPORT MonoReflectionType*
2639 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2642 MonoReflectionType *ret;
2643 MonoDomain *domain = mono_domain_get ();
2646 if (type->type->byref)
2648 if (type->type->type == MONO_TYPE_VAR) {
2649 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2650 klass = param ? param->owner.klass : NULL;
2651 } else if (type->type->type == MONO_TYPE_MVAR) {
2652 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2653 klass = param ? param->owner.method->klass : NULL;
2655 klass = mono_class_from_mono_type (type->type)->nested_in;
2661 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2662 mono_error_set_pending_exception (&error);
2667 ICALL_EXPORT MonoStringHandle
2668 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2670 MonoDomain *domain = mono_domain_get ();
2671 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2672 MonoClass *klass = mono_class_from_mono_type (type);
2675 char *n = g_strdup_printf ("%s&", klass->name);
2676 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2682 return mono_string_new_handle (domain, klass->name, error);
2686 ICALL_EXPORT MonoStringHandle
2687 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2689 MonoDomain *domain = mono_domain_get ();
2690 MonoClass *klass = mono_class_from_mono_type_handle (type);
2692 while (klass->nested_in)
2693 klass = klass->nested_in;
2695 if (klass->name_space [0] == '\0')
2696 return NULL_HANDLE_STRING;
2698 return mono_string_new_handle (domain, klass->name_space, error);
2702 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2706 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2707 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2711 klass = mono_class_from_mono_type (type->type);
2717 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2719 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2722 ICALL_EXPORT MonoArray*
2723 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2726 MonoReflectionType *rt;
2728 MonoClass *klass, *pklass;
2729 MonoDomain *domain = mono_object_domain (type);
2732 klass = mono_class_from_mono_type (type->type);
2734 if (mono_class_is_gtd (klass)) {
2735 MonoGenericContainer *container = mono_class_get_generic_container (klass);
2736 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2737 if (mono_error_set_pending_exception (&error))
2739 for (i = 0; i < container->type_argc; ++i) {
2740 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2742 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2743 if (mono_error_set_pending_exception (&error))
2746 mono_array_setref (res, i, rt);
2748 } else if (mono_class_is_ginst (klass)) {
2749 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
2750 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2751 if (mono_error_set_pending_exception (&error))
2753 for (i = 0; i < inst->type_argc; ++i) {
2754 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2755 if (mono_error_set_pending_exception (&error))
2758 mono_array_setref (res, i, rt);
2766 ICALL_EXPORT gboolean
2767 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2771 if (!IS_MONOTYPE (type))
2774 if (type->type->byref)
2777 klass = mono_class_from_mono_type (type->type);
2778 return mono_class_is_gtd (klass);
2781 ICALL_EXPORT MonoReflectionType*
2782 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2785 MonoReflectionType *ret;
2788 if (type->type->byref)
2791 klass = mono_class_from_mono_type (type->type);
2793 if (mono_class_is_gtd (klass)) {
2794 return type; /* check this one */
2796 if (mono_class_is_ginst (klass)) {
2797 MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
2800 tb = mono_class_get_ref_info (generic_class);
2802 if (generic_class->wastypebuilder && tb)
2803 return (MonoReflectionType *)tb;
2805 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2806 mono_error_set_pending_exception (&error);
2814 ICALL_EXPORT MonoReflectionType*
2815 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2818 MonoReflectionType *ret;
2820 MonoType *geninst, **types;
2823 g_assert (IS_MONOTYPE (type));
2824 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2825 if (mono_error_set_pending_exception (&error))
2828 count = mono_array_length (type_array);
2829 types = g_new0 (MonoType *, count);
2831 for (i = 0; i < count; i++) {
2832 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2833 types [i] = t->type;
2836 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2839 mono_error_set_pending_exception (&error);
2843 klass = mono_class_from_mono_type (geninst);
2845 /*we might inflate to the GTD*/
2846 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2847 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2851 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2852 mono_error_set_pending_exception (&error);
2857 ICALL_EXPORT gboolean
2858 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2862 if (!IS_MONOTYPE (type))
2865 if (type->type->byref)
2868 klass = mono_class_from_mono_type (type->type);
2869 return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
2873 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2875 if (!IS_MONOTYPE (type))
2878 if (is_generic_parameter (type->type))
2879 return mono_type_get_generic_param_num (type->type);
2883 ICALL_EXPORT MonoGenericParamInfo *
2884 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2886 return mono_generic_param_info (type->type->data.generic_param);
2889 ICALL_EXPORT MonoBoolean
2890 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2892 return is_generic_parameter (type->type);
2895 ICALL_EXPORT MonoReflectionMethod*
2896 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2897 MonoReflectionMethod* generic)
2904 MonoReflectionMethod *ret = NULL;
2906 domain = ((MonoObject *)type)->vtable->domain;
2908 klass = mono_class_from_mono_type (type->type);
2909 mono_class_init_checked (klass, &error);
2910 if (mono_error_set_pending_exception (&error))
2914 while ((method = mono_class_get_methods (klass, &iter))) {
2915 if (method->token == generic->method->token) {
2916 ret = mono_method_get_object_checked (domain, method, klass, &error);
2917 if (mono_error_set_pending_exception (&error))
2925 ICALL_EXPORT MonoReflectionMethod *
2926 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2929 MonoType *type = ref_type->type;
2931 MonoReflectionMethod *ret = NULL;
2933 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2934 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2937 if (type->type == MONO_TYPE_VAR)
2940 method = mono_type_get_generic_param_owner (type)->owner.method;
2943 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2944 if (!mono_error_ok (&error))
2945 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2949 ICALL_EXPORT MonoBoolean
2950 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2952 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2956 ICALL_EXPORT MonoBoolean
2957 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2959 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2964 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2966 MonoDomain *domain = mono_domain_get ();
2967 MonoImage *image = method->method->klass->image;
2968 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2969 MonoTableInfo *tables = image->tables;
2970 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2971 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2972 guint32 im_cols [MONO_IMPLMAP_SIZE];
2973 guint32 scope_token;
2974 const char *import = NULL;
2975 const char *scope = NULL;
2977 if (image_is_dynamic (image)) {
2978 MonoReflectionMethodAux *method_aux =
2979 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2981 import = method_aux->dllentry;
2982 scope = method_aux->dll;
2985 if (!import || !scope) {
2986 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2991 if (piinfo->implmap_idx) {
2992 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2994 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2995 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2996 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2997 scope = mono_metadata_string_heap (image, scope_token);
3001 *flags = piinfo->piflags;
3002 *entry_point = mono_string_new (domain, import);
3003 *dll_name = mono_string_new (domain, scope);
3006 ICALL_EXPORT MonoReflectionMethod *
3007 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3009 MonoMethodInflated *imethod;
3011 MonoReflectionMethod *ret = NULL;
3014 if (method->method->is_generic)
3017 if (!method->method->is_inflated)
3020 imethod = (MonoMethodInflated *) method->method;
3022 result = imethod->declaring;
3023 /* Not a generic method. */
3024 if (!result->is_generic)
3027 if (image_is_dynamic (method->method->klass->image)) {
3028 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3029 MonoReflectionMethod *res;
3032 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3033 * the dynamic case as well ?
3035 mono_image_lock ((MonoImage*)image);
3036 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3037 mono_image_unlock ((MonoImage*)image);
3043 if (imethod->context.class_inst) {
3044 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3045 /*Generic methods gets the context of the GTD.*/
3046 if (mono_class_get_context (klass)) {
3047 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3048 if (!mono_error_ok (&error))
3053 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3055 if (!mono_error_ok (&error))
3056 mono_error_set_pending_exception (&error);
3060 ICALL_EXPORT gboolean
3061 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3063 return mono_method_signature (method->method)->generic_param_count != 0;
3066 ICALL_EXPORT gboolean
3067 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3069 return method->method->is_generic;
3072 ICALL_EXPORT MonoArray*
3073 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3076 MonoReflectionType *rt;
3081 domain = mono_object_domain (method);
3083 if (method->method->is_inflated) {
3084 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3087 count = inst->type_argc;
3088 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3089 if (mono_error_set_pending_exception (&error))
3092 for (i = 0; i < count; i++) {
3093 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3094 if (mono_error_set_pending_exception (&error))
3097 mono_array_setref (res, i, rt);
3104 count = mono_method_signature (method->method)->generic_param_count;
3105 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3106 if (mono_error_set_pending_exception (&error))
3109 for (i = 0; i < count; i++) {
3110 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3111 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3112 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3114 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3115 if (mono_error_set_pending_exception (&error))
3118 mono_array_setref (res, i, rt);
3124 ICALL_EXPORT MonoObject *
3125 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3129 * Invoke from reflection is supposed to always be a virtual call (the API
3130 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3131 * greater flexibility.
3133 MonoMethod *m = method->method;
3134 MonoMethodSignature *sig = mono_method_signature (m);
3137 void *obj = this_arg;
3141 if (mono_security_core_clr_enabled () &&
3142 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3143 mono_error_set_pending_exception (&error);
3147 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3148 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3149 mono_error_cleanup (&error); /* FIXME does this make sense? */
3150 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3155 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3156 if (!is_ok (&error)) {
3157 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3160 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3161 char *target_name = mono_type_get_full_name (m->klass);
3162 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3163 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3165 g_free (target_name);
3169 m = mono_object_get_virtual_method (this_arg, m);
3170 /* must pass the pointer to the value for valuetype methods */
3171 if (m->klass->valuetype)
3172 obj = mono_object_unbox (this_arg);
3173 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3174 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3179 if (sig->ret->byref) {
3180 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
3184 pcount = params? mono_array_length (params): 0;
3185 if (pcount != sig->param_count) {
3186 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3190 if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
3191 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."));
3195 image = m->klass->image;
3196 if (image->assembly->ref_only) {
3197 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."));
3201 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3202 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3206 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3210 intptr_t *lower_bounds;
3211 pcount = mono_array_length (params);
3212 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3213 /* Note: the synthetized array .ctors have int32 as argument type */
3214 for (i = 0; i < pcount; ++i)
3215 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3217 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3218 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3219 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3220 if (!mono_error_ok (&error)) {
3221 mono_error_set_pending_exception (&error);
3225 for (i = 0; i < mono_array_length (arr); ++i) {
3226 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3227 if (!mono_error_ok (&error)) {
3228 mono_error_set_pending_exception (&error);
3231 mono_array_setref_fast (arr, i, subarray);
3233 return (MonoObject*)arr;
3236 if (m->klass->rank == pcount) {
3237 /* Only lengths provided. */
3238 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3239 if (!mono_error_ok (&error)) {
3240 mono_error_set_pending_exception (&error);
3244 return (MonoObject*)arr;
3246 g_assert (pcount == (m->klass->rank * 2));
3247 /* The arguments are lower-bound-length pairs */
3248 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3250 for (i = 0; i < pcount / 2; ++i) {
3251 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3252 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3255 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3256 if (!mono_error_ok (&error)) {
3257 mono_error_set_pending_exception (&error);
3261 return (MonoObject*)arr;
3264 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3265 mono_error_set_pending_exception (&error);
3269 #ifndef DISABLE_REMOTING
3270 ICALL_EXPORT MonoObject *
3271 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3274 MonoDomain *domain = mono_object_domain (method);
3275 MonoMethod *m = method->method;
3276 MonoMethodSignature *sig = mono_method_signature (m);
3277 MonoArray *out_args;
3279 int i, j, outarg_count = 0;
3281 if (m->klass == mono_defaults.object_class) {
3282 if (!strcmp (m->name, "FieldGetter")) {
3283 MonoClass *k = this_arg->vtable->klass;
3287 /* If this is a proxy, then it must be a CBO */
3288 if (k == mono_defaults.transparent_proxy_class) {
3289 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3290 this_arg = tp->rp->unwrapped_server;
3291 g_assert (this_arg);
3292 k = this_arg->vtable->klass;
3295 name = mono_array_get (params, MonoString *, 1);
3296 str = mono_string_to_utf8_checked (name, &error);
3297 if (mono_error_set_pending_exception (&error))
3301 MonoClassField* field = mono_class_get_field_from_name (k, str);
3304 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3305 if (field_klass->valuetype) {
3306 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3307 if (mono_error_set_pending_exception (&error))
3310 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3312 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3313 if (mono_error_set_pending_exception (&error))
3315 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3316 mono_array_setref (out_args, 0, result);
3323 g_assert_not_reached ();
3325 } else if (!strcmp (m->name, "FieldSetter")) {
3326 MonoClass *k = this_arg->vtable->klass;
3332 /* If this is a proxy, then it must be a CBO */
3333 if (k == mono_defaults.transparent_proxy_class) {
3334 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3335 this_arg = tp->rp->unwrapped_server;
3336 g_assert (this_arg);
3337 k = this_arg->vtable->klass;
3340 name = mono_array_get (params, MonoString *, 1);
3341 str = mono_string_to_utf8_checked (name, &error);
3342 if (mono_error_set_pending_exception (&error))
3346 MonoClassField* field = mono_class_get_field_from_name (k, str);
3349 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3350 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3352 if (field_klass->valuetype) {
3353 size = mono_type_size (field->type, &align);
3354 g_assert (size == mono_class_value_size (field_klass, NULL));
3355 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3357 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3360 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3361 if (mono_error_set_pending_exception (&error))
3363 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3372 g_assert_not_reached ();
3377 for (i = 0; i < mono_array_length (params); i++) {
3378 if (sig->params [i]->byref)
3382 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3383 if (mono_error_set_pending_exception (&error))
3386 /* handle constructors only for objects already allocated */
3387 if (!strcmp (method->method->name, ".ctor"))
3388 g_assert (this_arg);
3390 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3391 g_assert (!method->method->klass->valuetype);
3392 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3393 if (mono_error_set_pending_exception (&error))
3396 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3397 if (sig->params [i]->byref) {
3399 arg = mono_array_get (params, gpointer, i);
3400 mono_array_setref (out_args, j, arg);
3405 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3412 read_enum_value (const char *mem, int type)
3415 case MONO_TYPE_BOOLEAN:
3417 return *(guint8*)mem;
3419 return *(gint8*)mem;
3420 case MONO_TYPE_CHAR:
3422 return read16 (mem);
3424 return (gint16) read16 (mem);
3426 return read32 (mem);
3428 return (gint32) read32 (mem);
3431 return read64 (mem);
3433 g_assert_not_reached ();
3439 write_enum_value (char *mem, int type, guint64 value)
3443 case MONO_TYPE_I1: {
3444 guint8 *p = (guint8*)mem;
3450 case MONO_TYPE_CHAR: {
3451 guint16 *p = (guint16 *)mem;
3456 case MONO_TYPE_I4: {
3457 guint32 *p = (guint32 *)mem;
3462 case MONO_TYPE_I8: {
3463 guint64 *p = (guint64 *)mem;
3468 g_assert_not_reached ();
3473 ICALL_EXPORT MonoObject *
3474 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3482 domain = mono_object_domain (enumType);
3483 enumc = mono_class_from_mono_type (enumType->type);
3485 mono_class_init_checked (enumc, &error);
3486 if (mono_error_set_pending_exception (&error))
3489 etype = mono_class_enum_basetype (enumc);
3491 res = mono_object_new_checked (domain, enumc, &error);
3492 if (mono_error_set_pending_exception (&error))
3494 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3499 ICALL_EXPORT MonoBoolean
3500 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3502 int size = mono_class_value_size (a->vtable->klass, NULL);
3503 guint64 a_val = 0, b_val = 0;
3505 memcpy (&a_val, mono_object_unbox (a), size);
3506 memcpy (&b_val, mono_object_unbox (b), size);
3508 return (a_val & b_val) == b_val;
3511 ICALL_EXPORT MonoObject *
3512 ves_icall_System_Enum_get_value (MonoObject *eobj)
3524 g_assert (eobj->vtable->klass->enumtype);
3526 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3527 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3528 if (mono_error_set_pending_exception (&error))
3530 dst = (char *)res + sizeof (MonoObject);
3531 src = (char *)eobj + sizeof (MonoObject);
3532 size = mono_class_value_size (enumc, NULL);
3534 memcpy (dst, src, size);
3539 ICALL_EXPORT MonoReflectionType *
3540 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3543 MonoReflectionType *ret;
3547 klass = mono_class_from_mono_type (type->type);
3548 mono_class_init_checked (klass, &error);
3549 if (mono_error_set_pending_exception (&error))
3552 etype = mono_class_enum_basetype (klass);
3554 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3558 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3559 mono_error_set_pending_exception (&error);
3565 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3567 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3568 gpointer odata = (char *)other + sizeof (MonoObject);
3569 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3570 g_assert (basetype);
3575 if (eobj->vtable->klass != other->vtable->klass)
3578 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3579 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3580 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3583 return me > other ? 1 : -1; \
3586 switch (basetype->type) {
3588 COMPARE_ENUM_VALUES (guint8);
3590 COMPARE_ENUM_VALUES (gint8);
3591 case MONO_TYPE_CHAR:
3593 COMPARE_ENUM_VALUES (guint16);
3595 COMPARE_ENUM_VALUES (gint16);
3597 COMPARE_ENUM_VALUES (guint32);
3599 COMPARE_ENUM_VALUES (gint32);
3601 COMPARE_ENUM_VALUES (guint64);
3603 COMPARE_ENUM_VALUES (gint64);
3607 #undef COMPARE_ENUM_VALUES
3608 /* indicates that the enum was of an unsupported unerlying type */
3613 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3615 gpointer data = (char *)eobj + sizeof (MonoObject);
3616 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3617 g_assert (basetype);
3619 switch (basetype->type) {
3620 case MONO_TYPE_I1: {
3621 gint8 value = *((gint8*)data);
3622 return ((int)value ^ (int)value << 8);
3625 return *((guint8*)data);
3626 case MONO_TYPE_CHAR:
3628 return *((guint16*)data);
3630 case MONO_TYPE_I2: {
3631 gint16 value = *((gint16*)data);
3632 return ((int)(guint16)value | (((int)value) << 16));
3635 return *((guint32*)data);
3637 return *((gint32*)data);
3639 case MONO_TYPE_I8: {
3640 gint64 value = *((gint64*)data);
3641 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3644 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3649 ICALL_EXPORT MonoBoolean
3650 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3653 MonoDomain *domain = mono_object_domain (type);
3654 MonoClass *enumc = mono_class_from_mono_type (type->type);
3655 guint j = 0, nvalues;
3657 MonoClassField *field;
3659 guint64 field_value, previous_value = 0;
3660 gboolean sorted = TRUE;
3662 mono_class_init_checked (enumc, &error);
3663 if (mono_error_set_pending_exception (&error))
3667 if (!enumc->enumtype) {
3668 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3672 base_type = mono_class_enum_basetype (enumc)->type;
3674 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3675 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3676 if (mono_error_set_pending_exception (&error))
3678 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3679 if (mono_error_set_pending_exception (&error))
3683 while ((field = mono_class_get_fields (enumc, &iter))) {
3685 MonoTypeEnum def_type;
3687 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3689 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3691 if (mono_field_is_deleted (field))
3693 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3695 p = mono_class_get_field_default_value (field, &def_type);
3696 /* len = */ mono_metadata_decode_blob_size (p, &p);
3698 field_value = read_enum_value (p, base_type);
3699 mono_array_set (*values, guint64, j, field_value);
3701 if (previous_value > field_value)
3704 previous_value = field_value;
3712 BFLAGS_IgnoreCase = 1,
3713 BFLAGS_DeclaredOnly = 2,
3714 BFLAGS_Instance = 4,
3716 BFLAGS_Public = 0x10,
3717 BFLAGS_NonPublic = 0x20,
3718 BFLAGS_FlattenHierarchy = 0x40,
3719 BFLAGS_InvokeMethod = 0x100,
3720 BFLAGS_CreateInstance = 0x200,
3721 BFLAGS_GetField = 0x400,
3722 BFLAGS_SetField = 0x800,
3723 BFLAGS_GetProperty = 0x1000,
3724 BFLAGS_SetProperty = 0x2000,
3725 BFLAGS_ExactBinding = 0x10000,
3726 BFLAGS_SuppressChangeType = 0x20000,
3727 BFLAGS_OptionalParamBinding = 0x40000
3730 ICALL_EXPORT GPtrArray*
3731 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3734 MonoClass *startklass, *klass;
3737 int (*compare_func) (const char *s1, const char *s2) = NULL;
3738 MonoClassField *field;
3740 if (type->type->byref) {
3741 return g_ptr_array_new ();
3744 mono_error_init (&error);
3746 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3748 klass = startklass = mono_class_from_mono_type (type->type);
3750 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3753 if (mono_class_has_failure (klass)) {
3754 mono_error_set_for_class_failure (&error, klass);
3759 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3760 guint32 flags = mono_field_get_flags (field);
3762 if (mono_field_is_deleted_with_flags (field, flags))
3764 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3765 if (bflags & BFLAGS_Public)
3767 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3768 if (bflags & BFLAGS_NonPublic) {
3775 if (flags & FIELD_ATTRIBUTE_STATIC) {
3776 if (bflags & BFLAGS_Static)
3777 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3780 if (bflags & BFLAGS_Instance)
3787 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3790 g_ptr_array_add (ptr_array, field);
3792 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3798 g_ptr_array_free (ptr_array, TRUE);
3799 mono_error_set_pending_exception (&error);
3804 method_nonpublic (MonoMethod* method, gboolean start_klass)
3806 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3807 case METHOD_ATTRIBUTE_ASSEM:
3808 return (start_klass || mono_defaults.generic_ilist_class);
3809 case METHOD_ATTRIBUTE_PRIVATE:
3811 case METHOD_ATTRIBUTE_PUBLIC:
3819 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3822 MonoClass *startklass;
3826 /*FIXME, use MonoBitSet*/
3827 guint32 method_slots_default [8];
3828 guint32 *method_slots = NULL;
3829 int (*compare_func) (const char *s1, const char *s2) = NULL;
3831 array = g_ptr_array_new ();
3833 mono_error_init (error);
3836 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3838 /* An optimization for calls made from Delegate:CreateDelegate () */
3839 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3840 method = mono_get_delegate_invoke (klass);
3843 g_ptr_array_add (array, method);
3847 mono_class_setup_methods (klass);
3848 mono_class_setup_vtable (klass);
3849 if (mono_class_has_failure (klass))
3852 if (is_generic_parameter (&klass->byval_arg))
3853 nslots = mono_class_get_vtable_size (klass->parent);
3855 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3856 if (nslots >= sizeof (method_slots_default) * 8) {
3857 method_slots = g_new0 (guint32, nslots / 32 + 1);
3859 method_slots = method_slots_default;
3860 memset (method_slots, 0, sizeof (method_slots_default));
3863 mono_class_setup_methods (klass);
3864 mono_class_setup_vtable (klass);
3865 if (mono_class_has_failure (klass))
3869 while ((method = mono_class_get_methods (klass, &iter))) {
3871 if (method->slot != -1) {
3872 g_assert (method->slot < nslots);
3873 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3875 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3876 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3879 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3881 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3882 if (bflags & BFLAGS_Public)
3884 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3890 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3891 if (bflags & BFLAGS_Static)
3892 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3895 if (bflags & BFLAGS_Instance)
3903 if (compare_func (name, method->name))
3908 g_ptr_array_add (array, method);
3910 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3912 if (method_slots != method_slots_default)
3913 g_free (method_slots);
3918 if (method_slots != method_slots_default)
3919 g_free (method_slots);
3920 g_ptr_array_free (array, TRUE);
3922 g_assert (mono_class_has_failure (klass));
3923 mono_error_set_for_class_failure (error, klass);
3927 ICALL_EXPORT GPtrArray*
3928 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3931 GPtrArray *method_array;
3934 klass = mono_class_from_mono_type (type->type);
3935 if (type->type->byref) {
3936 return g_ptr_array_new ();
3939 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3940 mono_error_set_pending_exception (&error);
3941 return method_array;
3944 ICALL_EXPORT GPtrArray*
3945 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3947 MonoClass *startklass, *klass;
3950 gpointer iter = NULL;
3951 GPtrArray *res_array;
3954 if (type->type->byref) {
3955 return g_ptr_array_new ();
3958 klass = startklass = mono_class_from_mono_type (type->type);
3960 mono_class_setup_methods (klass);
3961 if (mono_class_has_failure (klass)) {
3962 mono_error_init (&error);
3963 mono_error_set_for_class_failure (&error, klass);
3964 mono_error_set_pending_exception (&error);
3968 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3971 while ((method = mono_class_get_methods (klass, &iter))) {
3973 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3975 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3976 if (bflags & BFLAGS_Public)
3979 if (bflags & BFLAGS_NonPublic)
3985 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3986 if (bflags & BFLAGS_Static)
3987 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3990 if (bflags & BFLAGS_Instance)
3996 g_ptr_array_add (res_array, method);
4003 property_hash (gconstpointer data)
4005 MonoProperty *prop = (MonoProperty*)data;
4007 return g_str_hash (prop->name);
4011 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4013 if (method1->slot != -1 && method1->slot == method2->slot)
4016 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4017 if (method1->is_inflated)
4018 method1 = ((MonoMethodInflated*) method1)->declaring;
4019 if (method2->is_inflated)
4020 method2 = ((MonoMethodInflated*) method2)->declaring;
4023 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4027 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4029 // Properties are hide-by-name-and-signature
4030 if (!g_str_equal (prop1->name, prop2->name))
4033 /* If we see a property in a generic method, we want to
4034 compare the generic signatures, not the inflated signatures
4035 because we might conflate two properties that were
4039 public T this[T t] { getter { return t; } } // method 1
4040 public U this[U u] { getter { return u; } } // method 2
4043 If we see int Foo<int,int>::Item[int] we need to know if
4044 the indexer came from method 1 or from method 2, and we
4045 shouldn't conflate them. (Bugzilla 36283)
4047 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4050 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4057 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4062 return method_nonpublic (accessor, start_klass);
4065 ICALL_EXPORT GPtrArray*
4066 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4069 MonoClass *startklass, *klass;
4074 int (*compare_func) (const char *s1, const char *s2) = NULL;
4076 GHashTable *properties = NULL;
4077 GPtrArray *res_array;
4079 if (type->type->byref) {
4080 return g_ptr_array_new ();
4083 mono_error_init (&error);
4085 klass = startklass = mono_class_from_mono_type (type->type);
4087 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4089 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4091 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4093 mono_class_setup_methods (klass);
4094 mono_class_setup_vtable (klass);
4095 if (mono_class_has_failure (klass)) {
4096 mono_error_set_for_class_failure (&error, klass);
4101 while ((prop = mono_class_get_properties (klass, &iter))) {
4107 flags = method->flags;
4110 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4111 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4112 if (bflags & BFLAGS_Public)
4114 } else if (bflags & BFLAGS_NonPublic) {
4115 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4116 property_accessor_nonpublic(prop->set, startklass == klass)) {
4123 if (flags & METHOD_ATTRIBUTE_STATIC) {
4124 if (bflags & BFLAGS_Static)
4125 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4128 if (bflags & BFLAGS_Instance)
4136 if (propname != NULL && compare_func (propname, prop->name))
4139 if (g_hash_table_lookup (properties, prop))
4142 g_ptr_array_add (res_array, prop);
4144 g_hash_table_insert (properties, prop, prop);
4146 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4149 g_hash_table_destroy (properties);
4156 g_hash_table_destroy (properties);
4157 g_ptr_array_free (res_array, TRUE);
4159 mono_error_set_pending_exception (&error);
4165 event_hash (gconstpointer data)
4167 MonoEvent *event = (MonoEvent*)data;
4169 return g_str_hash (event->name);
4173 event_equal (MonoEvent *event1, MonoEvent *event2)
4175 // Events are hide-by-name
4176 return g_str_equal (event1->name, event2->name);
4179 ICALL_EXPORT GPtrArray*
4180 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4183 MonoClass *startklass, *klass;
4188 int (*compare_func) (const char *s1, const char *s2) = NULL;
4189 GHashTable *events = NULL;
4190 GPtrArray *res_array;
4192 if (type->type->byref) {
4193 return g_ptr_array_new ();
4196 mono_error_init (&error);
4198 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4200 res_array = g_ptr_array_sized_new (4);
4202 klass = startklass = mono_class_from_mono_type (type->type);
4204 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4206 mono_class_setup_methods (klass);
4207 mono_class_setup_vtable (klass);
4208 if (mono_class_has_failure (klass)) {
4209 mono_error_set_for_class_failure (&error, klass);
4214 while ((event = mono_class_get_events (klass, &iter))) {
4216 method = event->add;
4218 method = event->remove;
4220 method = event->raise;
4222 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4223 if (bflags & BFLAGS_Public)
4225 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4226 if (bflags & BFLAGS_NonPublic)
4231 if (bflags & BFLAGS_NonPublic)
4237 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4238 if (bflags & BFLAGS_Static)
4239 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4242 if (bflags & BFLAGS_Instance)
4247 if (bflags & BFLAGS_Instance)
4252 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4255 if (g_hash_table_lookup (events, event))
4258 g_ptr_array_add (res_array, event);
4260 g_hash_table_insert (events, event, event);
4262 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4265 g_hash_table_destroy (events);
4271 g_hash_table_destroy (events);
4273 g_ptr_array_free (res_array, TRUE);
4275 mono_error_set_pending_exception (&error);
4279 ICALL_EXPORT GPtrArray *
4280 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4286 GPtrArray *res_array;
4288 if (type->type->byref) {
4289 return g_ptr_array_new ();
4292 klass = mono_class_from_mono_type (type->type);
4295 * If a nested type is generic, return its generic type definition.
4296 * Note that this means that the return value is essentially the set
4297 * of nested types of the generic type definition of @klass.
4299 * A note in MSDN claims that a generic type definition can have
4300 * nested types that aren't generic. In any case, the container of that
4301 * nested type would be the generic type definition.
4303 if (mono_class_is_ginst (klass))
4304 klass = mono_class_get_generic_class (klass)->container_class;
4306 res_array = g_ptr_array_new ();
4309 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4311 if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4312 if (bflags & BFLAGS_Public)
4315 if (bflags & BFLAGS_NonPublic)
4321 if (str != NULL && strcmp (nested->name, str))
4324 g_ptr_array_add (res_array, &nested->byval_arg);
4330 ICALL_EXPORT MonoReflectionType*
4331 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4334 MonoReflectionType *ret;
4336 MonoType *type = NULL;
4337 MonoTypeNameParse info;
4338 gboolean type_resolve;
4340 /* On MS.NET, this does not fire a TypeResolve event */
4341 type_resolve = TRUE;
4342 str = mono_string_to_utf8_checked (name, &error);
4343 if (mono_error_set_pending_exception (&error))
4345 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4346 if (!mono_reflection_parse_type (str, &info)) {
4348 mono_reflection_free_type_info (&info);
4350 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4353 /*g_print ("failed parse\n");*/
4357 if (info.assembly.name) {
4359 mono_reflection_free_type_info (&info);
4361 /* 1.0 and 2.0 throw different exceptions */
4362 if (mono_defaults.generic_ilist_class)
4363 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4365 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4371 if (module != NULL) {
4372 if (module->image) {
4373 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4374 if (!is_ok (&error)) {
4376 mono_reflection_free_type_info (&info);
4377 mono_error_set_pending_exception (&error);
4384 if (assembly_is_dynamic (assembly->assembly)) {
4385 /* Enumerate all modules */
4386 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4390 if (abuilder->modules) {
4391 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4392 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4393 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4394 if (!is_ok (&error)) {
4396 mono_reflection_free_type_info (&info);
4397 mono_error_set_pending_exception (&error);
4405 if (!type && abuilder->loaded_modules) {
4406 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4407 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4408 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4409 if (!is_ok (&error)) {
4411 mono_reflection_free_type_info (&info);
4412 mono_error_set_pending_exception (&error);
4421 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4422 if (!is_ok (&error)) {
4424 mono_reflection_free_type_info (&info);
4425 mono_error_set_pending_exception (&error);
4430 mono_reflection_free_type_info (&info);
4432 MonoException *e = NULL;
4435 e = mono_get_exception_type_load (name, NULL);
4438 mono_set_pending_exception (e);
4442 if (type->type == MONO_TYPE_CLASS) {
4443 MonoClass *klass = mono_type_get_class (type);
4445 /* need to report exceptions ? */
4446 if (throwOnError && mono_class_has_failure (klass)) {
4447 /* report SecurityException (or others) that occured when loading the assembly */
4448 mono_error_set_for_class_failure (&error, klass);
4449 mono_error_set_pending_exception (&error);
4454 /* g_print ("got it\n"); */
4455 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4456 mono_error_set_pending_exception (&error);
4462 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4465 gchar *shadow_ini_file;
4468 /* Check for shadow-copied assembly */
4469 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4470 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4472 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4473 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4479 g_free (shadow_ini_file);
4480 if (content != NULL) {
4483 *filename = content;
4490 ICALL_EXPORT MonoString *
4491 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4493 MonoDomain *domain = mono_object_domain (assembly);
4494 MonoAssembly *mass = assembly->assembly;
4495 MonoString *res = NULL;
4500 if (g_path_is_absolute (mass->image->name)) {
4501 absolute = g_strdup (mass->image->name);
4502 dirname = g_path_get_dirname (absolute);
4504 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4505 dirname = g_strdup (mass->basedir);
4508 replace_shadow_path (domain, dirname, &absolute);
4511 mono_icall_make_platform_path (absolute);
4514 uri = g_filename_to_uri (absolute, NULL, NULL);
4516 const gchar *prepend = mono_icall_get_file_path_prefix (absolute);
4517 uri = g_strconcat (prepend, absolute, NULL);
4521 res = mono_string_new (domain, uri);
4528 ICALL_EXPORT MonoBoolean
4529 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4531 MonoAssembly *mass = assembly->assembly;
4533 return mass->in_gac;
4536 ICALL_EXPORT MonoReflectionAssembly*
4537 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4542 MonoImageOpenStatus status;
4543 MonoReflectionAssembly* result = NULL;
4545 name = mono_string_to_utf8_checked (mname, &error);
4546 if (mono_error_set_pending_exception (&error))
4548 res = mono_assembly_load_with_partial_name (name, &status);
4554 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4556 mono_error_set_pending_exception (&error);
4560 ICALL_EXPORT MonoStringHandle
4561 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4563 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4564 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4565 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4568 ICALL_EXPORT MonoBoolean
4569 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4571 return assembly->assembly->ref_only;
4574 ICALL_EXPORT MonoStringHandle
4575 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4577 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4578 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4580 return mono_string_new_handle (domain, assembly->image->version, error);
4583 ICALL_EXPORT MonoReflectionMethod*
4584 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4587 MonoReflectionMethod *res = NULL;
4590 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4594 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4595 if (!mono_error_ok (&error))
4598 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4601 if (!mono_error_ok (&error))
4602 mono_error_set_pending_exception (&error);
4606 ICALL_EXPORT MonoReflectionModule*
4607 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4610 MonoReflectionModule *result = NULL;
4611 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4612 if (!mono_error_ok (&error))
4613 mono_error_set_pending_exception (&error);
4617 ICALL_EXPORT MonoArray*
4618 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4621 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4622 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4623 if (mono_error_set_pending_exception (&error))
4628 for (i = 0; i < table->rows; ++i) {
4629 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4630 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4635 ICALL_EXPORT MonoStringHandle
4636 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4639 guint8 aotid_sum = 0;
4640 MonoDomain* domain = mono_domain_get ();
4642 if (!domain->entry_assembly || !domain->entry_assembly->image)
4645 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4647 for (i = 0; i < 16; ++i)
4648 aotid_sum |= (*aotid)[i];
4653 gchar *guid = mono_guid_to_string((guint8*) aotid);
4654 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4660 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4662 static MonoMethod *create_version = NULL;
4666 mono_error_init (error);
4669 if (!create_version) {
4670 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4671 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4672 g_assert (create_version);
4673 mono_method_desc_free (desc);
4679 args [3] = &revision;
4680 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4681 return_val_if_nok (error, NULL);
4683 mono_runtime_invoke_checked (create_version, result, args, error);
4684 return_val_if_nok (error, NULL);
4689 ICALL_EXPORT MonoArray*
4690 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4694 MonoDomain *domain = mono_object_domain (assembly);
4696 static MonoMethod *create_culture = NULL;
4697 MonoImage *image = assembly->assembly->image;
4701 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4704 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4705 if (mono_error_set_pending_exception (&error))
4709 if (count > 0 && !create_culture) {
4710 MonoMethodDesc *desc = mono_method_desc_new (
4711 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4712 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4713 g_assert (create_culture);
4714 mono_method_desc_free (desc);
4717 for (i = 0; i < count; i++) {
4718 MonoObject *version;
4719 MonoReflectionAssemblyName *aname;
4720 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4722 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4724 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4725 domain, mono_class_get_assembly_name_class (), &error);
4726 if (mono_error_set_pending_exception (&error))
4729 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4731 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4732 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4733 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4734 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4735 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4736 aname->versioncompat = 1; /* SameMachine (default) */
4737 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4739 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4740 if (mono_error_set_pending_exception (&error))
4743 MONO_OBJECT_SETREF (aname, version, version);
4745 if (create_culture) {
4747 MonoBoolean assembly_ref = 1;
4748 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4749 args [1] = &assembly_ref;
4751 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4752 if (mono_error_set_pending_exception (&error))
4755 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4758 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4759 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4760 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4762 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4763 /* public key token isn't copied - the class library will
4764 automatically generate it from the public key if required */
4765 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4766 if (mono_error_set_pending_exception (&error))
4769 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4770 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4772 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4773 if (mono_error_set_pending_exception (&error))
4776 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4777 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4780 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4781 if (mono_error_set_pending_exception (&error))
4784 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4787 /* note: this function doesn't return the codebase on purpose (i.e. it can
4788 be used under partial trust as path information isn't present). */
4790 mono_array_setref (result, i, aname);
4795 /* move this in some file in mono/util/ */
4797 g_concat_dir_and_file (const char *dir, const char *file)
4799 g_return_val_if_fail (dir != NULL, NULL);
4800 g_return_val_if_fail (file != NULL, NULL);
4803 * If the directory name doesn't have a / on the end, we need
4804 * to add one so we get a proper path to the file
4806 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4807 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4809 return g_strconcat (dir, file, NULL);
4813 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4816 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4818 guint32 cols [MONO_MANIFEST_SIZE];
4819 guint32 impl, file_idx;
4823 char *n = mono_string_to_utf8_checked (name, &error);
4824 if (mono_error_set_pending_exception (&error))
4827 for (i = 0; i < table->rows; ++i) {
4828 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4829 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4830 if (strcmp (val, n) == 0)
4834 if (i == table->rows)
4837 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4840 * this code should only be called after obtaining the
4841 * ResourceInfo and handling the other cases.
4843 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4844 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4846 module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
4847 if (mono_error_set_pending_exception (&error) || !module)
4851 module = assembly->assembly->image;
4854 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4855 if (mono_error_set_pending_exception (&error))
4857 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4859 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4862 ICALL_EXPORT gboolean
4863 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4866 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4868 guint32 cols [MONO_MANIFEST_SIZE];
4869 guint32 file_cols [MONO_FILE_SIZE];
4873 n = mono_string_to_utf8_checked (name, &error);
4874 if (mono_error_set_pending_exception (&error))
4876 for (i = 0; i < table->rows; ++i) {
4877 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4878 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4879 if (strcmp (val, n) == 0)
4883 if (i == table->rows)
4886 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4887 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4890 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4891 case MONO_IMPLEMENTATION_FILE:
4892 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4893 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4894 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4895 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4896 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4897 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4900 info->location = RESOURCE_LOCATION_EMBEDDED;
4903 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4904 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4905 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4906 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4907 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4908 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4910 mono_set_pending_exception (ex);
4913 MonoReflectionAssembly *assm_obj;
4914 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4916 mono_error_set_pending_exception (&error);
4919 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4921 /* Obtain info recursively */
4922 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4923 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4926 case MONO_IMPLEMENTATION_EXP_TYPE:
4927 g_assert_not_reached ();
4935 ICALL_EXPORT MonoObject*
4936 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4939 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4940 MonoArray *result = NULL;
4945 /* check hash if needed */
4947 n = mono_string_to_utf8_checked (name, &error);
4948 if (mono_error_set_pending_exception (&error))
4951 for (i = 0; i < table->rows; ++i) {
4952 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4953 if (strcmp (val, n) == 0) {
4956 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4957 fn = mono_string_new (mono_object_domain (assembly), n);
4959 return (MonoObject*)fn;
4967 for (i = 0; i < table->rows; ++i) {
4968 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4972 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4973 if (mono_error_set_pending_exception (&error))
4978 for (i = 0; i < table->rows; ++i) {
4979 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4980 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4981 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4982 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4987 return (MonoObject*)result;
4990 ICALL_EXPORT MonoArray*
4991 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4994 MonoDomain *domain = mono_domain_get();
4997 int i, j, file_count = 0;
4998 MonoImage **modules;
4999 guint32 module_count, real_module_count;
5000 MonoTableInfo *table;
5001 guint32 cols [MONO_FILE_SIZE];
5002 MonoImage *image = assembly->assembly->image;
5004 g_assert (image != NULL);
5005 g_assert (!assembly_is_dynamic (assembly->assembly));
5007 table = &image->tables [MONO_TABLE_FILE];
5008 file_count = table->rows;
5010 modules = image->modules;
5011 module_count = image->module_count;
5013 real_module_count = 0;
5014 for (i = 0; i < module_count; ++i)
5016 real_module_count ++;
5018 klass = mono_class_get_module_class ();
5019 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5020 if (mono_error_set_pending_exception (&error))
5023 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5024 if (mono_error_set_pending_exception (&error))
5027 mono_array_setref (res, 0, image_obj);
5029 for (i = 0; i < module_count; ++i)
5031 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5032 if (mono_error_set_pending_exception (&error))
5034 mono_array_setref (res, j, rm);
5038 for (i = 0; i < file_count; ++i, ++j) {
5039 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5040 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5041 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5042 if (mono_error_set_pending_exception (&error))
5044 mono_array_setref (res, j, rm);
5047 MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
5048 if (mono_error_set_pending_exception (&error))
5051 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5052 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5055 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5056 if (mono_error_set_pending_exception (&error))
5058 mono_array_setref (res, j, rm);
5065 ICALL_EXPORT MonoReflectionMethod*
5066 ves_icall_GetCurrentMethod (void)
5068 MonoReflectionMethod *res = NULL;
5071 MonoMethod *m = mono_method_get_last_managed ();
5074 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5078 while (m->is_inflated)
5079 m = ((MonoMethodInflated*)m)->declaring;
5081 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5082 mono_error_set_pending_exception (&error);
5088 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5091 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5094 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5095 //method is inflated, we should inflate it on the other class
5096 MonoGenericContext ctx;
5097 ctx.method_inst = inflated->context.method_inst;
5098 ctx.class_inst = inflated->context.class_inst;
5099 if (mono_class_is_ginst (klass))
5100 ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
5101 else if (mono_class_is_gtd (klass))
5102 ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
5103 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5104 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5108 mono_class_setup_methods (method->klass);
5109 if (mono_class_has_failure (method->klass))
5111 int mcount = mono_class_get_method_count (method->klass);
5112 for (i = 0; i < mcount; ++i) {
5113 if (method->klass->methods [i] == method) {
5118 mono_class_setup_methods (klass);
5119 if (mono_class_has_failure (klass))
5121 g_assert (offset >= 0 && offset < mono_class_get_method_count (klass));
5122 return klass->methods [offset];
5125 ICALL_EXPORT MonoReflectionMethod*
5126 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5128 MonoReflectionMethod *res = NULL;
5131 if (type && generic_check) {
5132 klass = mono_class_from_mono_type (type);
5133 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5136 if (method->klass != klass) {
5137 method = mono_method_get_equivalent_method (method, klass);
5142 klass = mono_class_from_mono_type (type);
5144 klass = method->klass;
5145 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5146 mono_error_set_pending_exception (&error);
5150 ICALL_EXPORT MonoReflectionMethodBody*
5151 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5154 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5155 mono_error_set_pending_exception (&error);
5159 ICALL_EXPORT MonoReflectionAssembly*
5160 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5163 MonoReflectionAssembly *result;
5164 MonoMethod *dest = NULL;
5166 mono_stack_walk_no_il (get_executing, &dest);
5168 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5170 mono_error_set_pending_exception (&error);
5175 ICALL_EXPORT MonoReflectionAssembly*
5176 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5179 MonoReflectionAssembly *result;
5180 MonoDomain* domain = mono_domain_get ();
5182 if (!domain->entry_assembly)
5185 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5187 mono_error_set_pending_exception (&error);
5191 ICALL_EXPORT MonoReflectionAssembly*
5192 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5197 MonoReflectionAssembly *result;
5200 mono_stack_walk_no_il (get_executing, &dest);
5202 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5206 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5209 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5211 mono_error_set_pending_exception (&error);
5215 ICALL_EXPORT MonoStringHandle
5216 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5217 gboolean assembly_qualified, MonoError *error)
5219 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5220 MonoType *type = MONO_HANDLE_RAW (object)->type;
5221 MonoTypeNameFormat format;
5222 MonoStringHandle res;
5226 format = assembly_qualified ?
5227 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5228 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5230 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5232 name = mono_type_get_name_full (type, format);
5234 return NULL_HANDLE_STRING;
5236 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5238 return NULL_HANDLE_STRING;
5241 res = mono_string_new_handle (domain, name, error);
5248 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5251 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5253 mono_class_init_checked (klass, &error);
5254 mono_error_set_pending_exception (&error);
5255 return mono_security_core_clr_class_level (klass);
5259 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5261 MonoClassField *field = rfield->field;
5262 return mono_security_core_clr_field_level (field, TRUE);
5266 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5268 MonoMethod *method = rfield->method;
5269 return mono_security_core_clr_method_level (method, TRUE);
5273 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token, MonoError *error)
5275 static MonoMethod *create_culture = NULL;
5279 const char *pkey_ptr;
5281 MonoBoolean assembly_ref = 0;
5283 mono_error_init (error);
5285 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5286 aname->major = name->major;
5287 aname->minor = name->minor;
5288 aname->build = name->build;
5289 aname->flags = name->flags;
5290 aname->revision = name->revision;
5291 aname->hashalg = name->hash_alg;
5292 aname->versioncompat = 1; /* SameMachine (default) */
5293 aname->processor_architecture = name->arch;
5295 if (by_default_version) {
5296 MonoObject *version;
5298 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5299 return_if_nok (error);
5301 MONO_OBJECT_SETREF (aname, version, version);
5305 if (absolute != NULL && *absolute != '\0') {
5308 codebase = g_strdup (absolute);
5310 mono_icall_make_platform_path (codebase);
5312 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5314 result = g_strconcat (prepend, codebase, NULL);
5320 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5324 if (!create_culture) {
5325 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5326 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5327 g_assert (create_culture);
5328 mono_method_desc_free (desc);
5331 if (name->culture) {
5332 args [0] = mono_string_new (domain, name->culture);
5333 args [1] = &assembly_ref;
5335 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5336 return_if_nok (error);
5338 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5341 if (name->public_key) {
5342 pkey_ptr = (char*)name->public_key;
5343 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5345 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5346 return_if_nok (error);
5347 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5348 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5349 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5350 } else if (default_publickey) {
5351 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5352 return_if_nok (error);
5353 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5354 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5357 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5358 if (name->public_key_token [0]) {
5362 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5363 return_if_nok (error);
5365 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5366 p = mono_array_addr (keyToken, char, 0);
5368 for (i = 0, j = 0; i < 8; i++) {
5369 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5370 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5373 } else if (default_token) {
5374 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5375 return_if_nok (error);
5376 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5380 ICALL_EXPORT MonoString *
5381 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5383 MonoDomain *domain = mono_object_domain (assembly);
5384 MonoAssembly *mass = assembly->assembly;
5388 name = mono_stringify_assembly_name (&mass->aname);
5389 res = mono_string_new (domain, name);
5395 ICALL_EXPORT MonoAssemblyName *
5396 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5398 return &mass->aname;
5402 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5406 MonoImageOpenStatus status = MONO_IMAGE_OK;
5409 MonoAssemblyName name;
5412 filename = mono_string_to_utf8_checked (fname, &error);
5413 if (mono_error_set_pending_exception (&error))
5416 dirname = g_path_get_dirname (filename);
5417 replace_shadow_path (mono_domain_get (), dirname, &filename);
5420 image = mono_image_open (filename, &status);
5426 if (status == MONO_IMAGE_IMAGE_INVALID)
5427 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5429 exc = mono_get_exception_file_not_found2 (NULL, fname);
5430 mono_set_pending_exception (exc);
5434 res = mono_assembly_fill_assembly_name (image, &name);
5436 mono_image_close (image);
5438 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5442 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5443 mono_error_set_pending_exception (&error);
5445 mono_image_close (image);
5449 ICALL_EXPORT MonoBoolean
5450 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5451 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5453 MonoBoolean result = FALSE;
5454 MonoDeclSecurityEntry entry;
5456 /* SecurityAction.RequestMinimum */
5457 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5458 *minimum = entry.blob;
5459 *minLength = entry.size;
5462 /* SecurityAction.RequestOptional */
5463 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5464 *optional = entry.blob;
5465 *optLength = entry.size;
5468 /* SecurityAction.RequestRefuse */
5469 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5470 *refused = entry.blob;
5471 *refLength = entry.size;
5479 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5481 guint32 attrs, visibility;
5483 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5484 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5485 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5488 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5494 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5496 MonoReflectionType *rt;
5499 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5502 mono_error_init (error);
5504 /* we start the count from 1 because we skip the special type <Module> */
5507 for (i = 1; i < tdef->rows; ++i) {
5508 if (mono_module_type_is_visible (tdef, image, i + 1))
5512 count = tdef->rows - 1;
5514 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5515 return_val_if_nok (error, NULL);
5516 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5517 return_val_if_nok (error, NULL);
5519 for (i = 1; i < tdef->rows; ++i) {
5520 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5521 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5524 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5525 return_val_if_nok (error, NULL);
5527 mono_array_setref (res, count, rt);
5529 MonoException *ex = mono_error_convert_to_exception (error);
5530 mono_array_setref (*exceptions, count, ex);
5539 ICALL_EXPORT MonoArray*
5540 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5543 MonoArray *res = NULL;
5544 MonoArray *exceptions = NULL;
5545 MonoImage *image = NULL;
5546 MonoTableInfo *table = NULL;
5549 int i, len, ex_count;
5551 domain = mono_object_domain (assembly);
5553 g_assert (!assembly_is_dynamic (assembly->assembly));
5554 image = assembly->assembly->image;
5555 table = &image->tables [MONO_TABLE_FILE];
5556 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5557 if (mono_error_set_pending_exception (&error))
5560 /* Append data from all modules in the assembly */
5561 for (i = 0; i < table->rows; ++i) {
5562 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5563 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5564 if (mono_error_set_pending_exception (&error))
5570 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5571 if (mono_error_set_pending_exception (&error))
5575 /* Append the new types to the end of the array */
5576 if (mono_array_length (res2) > 0) {
5578 MonoArray *res3, *ex3;
5580 len1 = mono_array_length (res);
5581 len2 = mono_array_length (res2);
5583 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5584 if (mono_error_set_pending_exception (&error))
5586 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5587 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5590 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5591 if (mono_error_set_pending_exception (&error))
5593 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5594 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5601 /* the ReflectionTypeLoadException must have all the types (Types property),
5602 * NULL replacing types which throws an exception. The LoaderException must
5603 * contain all exceptions for NULL items.
5606 len = mono_array_length (res);
5609 for (i = 0; i < len; i++) {
5610 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5614 klass = mono_type_get_class (t->type);
5615 if ((klass != NULL) && mono_class_has_failure (klass)) {
5616 /* keep the class in the list */
5617 list = g_list_append (list, klass);
5618 /* and replace Type with NULL */
5619 mono_array_setref (res, i, NULL);
5626 if (list || ex_count) {
5628 MonoException *exc = NULL;
5629 MonoArray *exl = NULL;
5630 int j, length = g_list_length (list) + ex_count;
5632 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5633 if (mono_error_set_pending_exception (&error)) {
5637 /* Types for which mono_class_get_checked () succeeded */
5638 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5639 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5640 mono_array_setref (exl, i, exc);
5642 /* Types for which it don't */
5643 for (j = 0; j < mono_array_length (exceptions); ++j) {
5644 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5646 g_assert (i < length);
5647 mono_array_setref (exl, i, exc);
5654 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5655 if (!is_ok (&error)) {
5656 mono_error_set_pending_exception (&error);
5659 mono_set_pending_exception (exc);
5667 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5669 mono_assembly_name_free (aname);
5672 ICALL_EXPORT gboolean
5673 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5675 *is_version_definited = *is_token_defined = FALSE;
5677 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5680 ICALL_EXPORT MonoReflectionType*
5681 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5684 MonoReflectionType *ret;
5685 MonoDomain *domain = mono_object_domain (module);
5688 g_assert (module->image);
5690 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5691 /* These images do not have a global type */
5694 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5695 if (!mono_error_ok (&error)) {
5696 mono_error_set_pending_exception (&error);
5700 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5701 if (!mono_error_ok (&error)) {
5702 mono_error_set_pending_exception (&error);
5710 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5712 /*if (module->image)
5713 mono_image_close (module->image);*/
5716 ICALL_EXPORT MonoStringHandle
5717 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5719 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5720 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5723 return mono_string_new_handle (domain, image->guid, error);
5727 static inline gpointer
5728 mono_icall_module_get_hinstance (MonoReflectionModule *module)
5730 return (gpointer) (-1);
5732 #endif /* HOST_WIN32 */
5734 ICALL_EXPORT gpointer
5735 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5737 return mono_icall_module_get_hinstance (module);
5741 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5743 if (image_is_dynamic (image)) {
5744 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5745 *pe_kind = dyn->pe_kind;
5746 *machine = dyn->machine;
5749 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5750 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5755 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5757 return (image->md_version_major << 16) | (image->md_version_minor);
5760 ICALL_EXPORT MonoArray*
5761 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5764 MonoArray *exceptions;
5767 if (!module->image) {
5768 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5769 mono_error_set_pending_exception (&error);
5774 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5775 if (mono_error_set_pending_exception (&error))
5778 for (i = 0; i < mono_array_length (exceptions); ++i) {
5779 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5781 mono_set_pending_exception (ex);
5790 mono_memberref_is_method (MonoImage *image, guint32 token)
5792 if (!image_is_dynamic (image)) {
5793 guint32 cols [MONO_MEMBERREF_SIZE];
5795 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5796 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5797 mono_metadata_decode_blob_size (sig, &sig);
5798 return (*sig != 0x6);
5801 MonoClass *handle_class;
5803 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5804 mono_error_cleanup (&error); /* just probing, ignore error */
5808 return mono_defaults.methodhandle_class == handle_class;
5813 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5816 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5817 mono_array_addr (type_args, MonoType*, 0));
5819 context->class_inst = NULL;
5821 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5822 mono_array_addr (method_args, MonoType*, 0));
5824 context->method_inst = NULL;
5827 ICALL_EXPORT MonoType*
5828 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5831 int table = mono_metadata_token_table (token);
5832 int index = mono_metadata_token_index (token);
5833 MonoGenericContext context;
5836 *resolve_error = ResolveTokenError_Other;
5838 /* Validate token */
5839 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5840 (table != MONO_TABLE_TYPESPEC)) {
5841 *resolve_error = ResolveTokenError_BadTable;
5845 if (image_is_dynamic (image)) {
5846 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5847 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5848 mono_error_cleanup (&error);
5849 return klass ? &klass->byval_arg : NULL;
5852 init_generic_context_from_args (&context, type_args, method_args);
5853 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5854 mono_error_cleanup (&error);
5855 return klass ? &klass->byval_arg : NULL;
5858 if ((index <= 0) || (index > image->tables [table].rows)) {
5859 *resolve_error = ResolveTokenError_OutOfRange;
5863 init_generic_context_from_args (&context, type_args, method_args);
5864 klass = mono_class_get_checked (image, token, &error);
5866 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5867 if (!mono_error_ok (&error)) {
5868 mono_error_set_pending_exception (&error);
5873 return &klass->byval_arg;
5878 ICALL_EXPORT MonoMethod*
5879 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5882 int table = mono_metadata_token_table (token);
5883 int index = mono_metadata_token_index (token);
5884 MonoGenericContext context;
5887 *resolve_error = ResolveTokenError_Other;
5889 /* Validate token */
5890 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5891 (table != MONO_TABLE_MEMBERREF)) {
5892 *resolve_error = ResolveTokenError_BadTable;
5896 if (image_is_dynamic (image)) {
5897 if (table == MONO_TABLE_METHOD) {
5898 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5899 mono_error_cleanup (&error);
5903 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5904 *resolve_error = ResolveTokenError_BadTable;
5908 init_generic_context_from_args (&context, type_args, method_args);
5909 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5910 mono_error_cleanup (&error);
5914 if ((index <= 0) || (index > image->tables [table].rows)) {
5915 *resolve_error = ResolveTokenError_OutOfRange;
5918 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5919 *resolve_error = ResolveTokenError_BadTable;
5923 init_generic_context_from_args (&context, type_args, method_args);
5924 method = mono_get_method_checked (image, token, NULL, &context, &error);
5925 mono_error_set_pending_exception (&error);
5930 ICALL_EXPORT MonoString*
5931 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5934 int index = mono_metadata_token_index (token);
5936 *resolve_error = ResolveTokenError_Other;
5938 /* Validate token */
5939 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5940 *resolve_error = ResolveTokenError_BadTable;
5944 if (image_is_dynamic (image)) {
5945 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5946 mono_error_cleanup (&error);
5950 if ((index <= 0) || (index >= image->heap_us.size)) {
5951 *resolve_error = ResolveTokenError_OutOfRange;
5955 /* FIXME: What to do if the index points into the middle of a string ? */
5957 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5958 mono_error_set_pending_exception (&error);
5962 ICALL_EXPORT MonoClassField*
5963 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5967 int table = mono_metadata_token_table (token);
5968 int index = mono_metadata_token_index (token);
5969 MonoGenericContext context;
5970 MonoClassField *field;
5972 *resolve_error = ResolveTokenError_Other;
5974 /* Validate token */
5975 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5976 *resolve_error = ResolveTokenError_BadTable;
5980 if (image_is_dynamic (image)) {
5981 if (table == MONO_TABLE_FIELD) {
5982 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5983 mono_error_cleanup (&error);
5987 if (mono_memberref_is_method (image, token)) {
5988 *resolve_error = ResolveTokenError_BadTable;
5992 init_generic_context_from_args (&context, type_args, method_args);
5993 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5994 mono_error_cleanup (&error);
5998 if ((index <= 0) || (index > image->tables [table].rows)) {
5999 *resolve_error = ResolveTokenError_OutOfRange;
6002 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6003 *resolve_error = ResolveTokenError_BadTable;
6007 init_generic_context_from_args (&context, type_args, method_args);
6008 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6009 mono_error_set_pending_exception (&error);
6015 ICALL_EXPORT MonoObject*
6016 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6020 int table = mono_metadata_token_table (token);
6022 *error = ResolveTokenError_Other;
6025 case MONO_TABLE_TYPEDEF:
6026 case MONO_TABLE_TYPEREF:
6027 case MONO_TABLE_TYPESPEC: {
6028 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6030 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6031 mono_error_set_pending_exception (&merror);
6038 case MONO_TABLE_METHOD:
6039 case MONO_TABLE_METHODSPEC: {
6040 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6042 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6043 mono_error_set_pending_exception (&merror);
6049 case MONO_TABLE_FIELD: {
6050 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6052 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6053 mono_error_set_pending_exception (&merror);
6059 case MONO_TABLE_MEMBERREF:
6060 if (mono_memberref_is_method (image, token)) {
6061 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6063 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6064 mono_error_set_pending_exception (&merror);
6071 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6073 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6074 mono_error_set_pending_exception (&merror);
6083 *error = ResolveTokenError_BadTable;
6089 ICALL_EXPORT MonoArray*
6090 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6093 int table = mono_metadata_token_table (token);
6094 int idx = mono_metadata_token_index (token);
6095 MonoTableInfo *tables = image->tables;
6100 *resolve_error = ResolveTokenError_OutOfRange;
6102 /* FIXME: Support other tables ? */
6103 if (table != MONO_TABLE_STANDALONESIG)
6106 if (image_is_dynamic (image))
6109 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6112 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6114 ptr = mono_metadata_blob_heap (image, sig);
6115 len = mono_metadata_decode_blob_size (ptr, &ptr);
6117 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6118 if (mono_error_set_pending_exception (&error))
6120 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6124 ICALL_EXPORT MonoBoolean
6125 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6131 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6137 check_for_invalid_type (MonoClass *klass, MonoError *error)
6141 mono_error_init (error);
6143 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6146 name = mono_type_get_full_name (klass);
6147 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6149 ICALL_EXPORT MonoReflectionType *
6150 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6153 MonoReflectionType *ret;
6154 MonoClass *klass, *aklass;
6156 klass = mono_class_from_mono_type (type->type);
6157 check_for_invalid_type (klass, &error);
6158 if (mono_error_set_pending_exception (&error))
6161 if (rank == 0) //single dimentional array
6162 aklass = mono_array_class_get (klass, 1);
6164 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6166 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6167 mono_error_set_pending_exception (&error);
6172 ICALL_EXPORT MonoReflectionType *
6173 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6176 MonoReflectionType *ret;
6179 klass = mono_class_from_mono_type (type->type);
6180 mono_class_init_checked (klass, &error);
6181 if (mono_error_set_pending_exception (&error))
6184 check_for_invalid_type (klass, &error);
6185 if (mono_error_set_pending_exception (&error))
6188 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6189 mono_error_set_pending_exception (&error);
6194 ICALL_EXPORT MonoReflectionType *
6195 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6198 MonoReflectionType *ret;
6199 MonoClass *klass, *pklass;
6201 klass = mono_class_from_mono_type (type->type);
6202 mono_class_init_checked (klass, &error);
6203 if (mono_error_set_pending_exception (&error))
6205 check_for_invalid_type (klass, &error);
6206 if (mono_error_set_pending_exception (&error))
6209 pklass = mono_ptr_class_get (type->type);
6211 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6212 mono_error_set_pending_exception (&error);
6217 ICALL_EXPORT MonoObject *
6218 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6219 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6222 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6223 MonoObject *delegate;
6225 MonoMethod *method = info->method;
6226 MonoMethodSignature *sig = mono_method_signature(method);
6228 mono_class_init_checked (delegate_class, &error);
6229 if (mono_error_set_pending_exception (&error))
6232 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6233 /* FIXME improve this exception message */
6234 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6236 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6237 mono_error_set_pending_exception (&error);
6241 if (mono_security_core_clr_enabled ()) {
6242 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6243 if (throwOnBindFailure)
6244 mono_error_set_pending_exception (&error);
6246 mono_error_cleanup (&error);
6251 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6252 if (!method->is_inflated) {
6253 mono_set_pending_exception(mono_get_exception_argument("method", " Cannot bind to the target method because its signature differs from that of the delegate type"));
6258 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6259 if (mono_error_set_pending_exception (&error))
6262 if (method_is_dynamic (method)) {
6263 /* Creating a trampoline would leak memory */
6264 func = mono_compile_method_checked (method, &error);
6265 if (mono_error_set_pending_exception (&error))
6268 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6269 method = mono_object_get_virtual_method (target, method);
6270 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6271 if (mono_error_set_pending_exception (&error))
6273 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6276 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6277 if (mono_error_set_pending_exception (&error))
6282 ICALL_EXPORT MonoMulticastDelegate *
6283 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6286 MonoMulticastDelegate *ret;
6288 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6290 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6291 if (mono_error_set_pending_exception (&error))
6294 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6299 ICALL_EXPORT MonoReflectionMethod*
6300 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6302 MonoReflectionMethod *ret = NULL;
6304 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6305 mono_error_set_pending_exception (&error);
6311 static inline gint32
6312 mono_array_get_byte_length (MonoArray *array)
6318 klass = array->obj.vtable->klass;
6320 if (array->bounds == NULL)
6321 length = array->max_length;
6324 for (i = 0; i < klass->rank; ++ i)
6325 length *= array->bounds [i].length;
6328 switch (klass->element_class->byval_arg.type) {
6331 case MONO_TYPE_BOOLEAN:
6335 case MONO_TYPE_CHAR:
6343 return length * sizeof (gpointer);
6354 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6356 return mono_array_get_byte_length (array);
6360 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6362 return mono_array_get (array, gint8, idx);
6366 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6368 mono_array_set (array, gint8, idx, value);
6371 ICALL_EXPORT MonoBoolean
6372 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6374 guint8 *src_buf, *dest_buf;
6377 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6381 g_assert (count >= 0);
6383 /* This is called directly from the class libraries without going through the managed wrapper */
6384 MONO_CHECK_ARG_NULL (src, FALSE);
6385 MONO_CHECK_ARG_NULL (dest, FALSE);
6387 /* watch out for integer overflow */
6388 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6391 src_buf = (guint8 *)src->vector + src_offset;
6392 dest_buf = (guint8 *)dest->vector + dest_offset;
6395 memcpy (dest_buf, src_buf, count);
6397 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6402 #ifndef DISABLE_REMOTING
6403 ICALL_EXPORT MonoObject *
6404 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6407 MonoDomain *domain = mono_object_domain (this_obj);
6409 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6410 MonoTransparentProxy *tp;
6414 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6415 if (mono_error_set_pending_exception (&error))
6418 tp = (MonoTransparentProxy*) res;
6420 MONO_OBJECT_SETREF (tp, rp, rp);
6421 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6422 klass = mono_class_from_mono_type (type);
6424 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6425 mono_class_setup_vtable (klass);
6426 if (mono_class_has_failure (klass)) {
6427 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6431 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6432 if (mono_error_set_pending_exception (&error))
6434 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6435 if (mono_error_set_pending_exception (&error))
6438 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6439 if (mono_error_set_pending_exception (&error))
6444 ICALL_EXPORT MonoReflectionType *
6445 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6448 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6449 mono_error_set_pending_exception (&error);
6455 /* System.Environment */
6458 ves_icall_System_Environment_get_UserName (void)
6460 /* using glib is more portable */
6461 return mono_string_new (mono_domain_get (), g_get_user_name ());
6466 mono_icall_get_machine_name (void)
6468 #if !defined(DISABLE_SOCKETS)
6472 #if defined _SC_HOST_NAME_MAX
6473 n = sysconf (_SC_HOST_NAME_MAX);
6477 buf = g_malloc (n+1);
6479 if (gethostname (buf, n) == 0){
6481 result = mono_string_new (mono_domain_get (), buf);
6488 return mono_string_new (mono_domain_get (), "mono");
6491 #endif /* !HOST_WIN32 */
6493 ICALL_EXPORT MonoString *
6494 ves_icall_System_Environment_get_MachineName (void)
6496 return mono_icall_get_machine_name ();
6501 mono_icall_get_platform (void)
6503 #if defined(__MACH__)
6506 // Notice that the value is hidden from user code, and only exposed
6507 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6508 // define and making assumptions based on Unix/128/4 values before there
6509 // was a MacOS define. Lots of code would assume that not-Unix meant
6510 // Windows, but in this case, it would be OSX.
6518 #endif /* !HOST_WIN32 */
6521 ves_icall_System_Environment_get_Platform (void)
6523 return mono_icall_get_platform ();
6527 static inline MonoString *
6528 mono_icall_get_new_line (void)
6530 return mono_string_new (mono_domain_get (), "\n");
6532 #endif /* !HOST_WIN32 */
6534 ICALL_EXPORT MonoString *
6535 ves_icall_System_Environment_get_NewLine (void)
6537 return mono_icall_get_new_line ();
6541 static inline MonoBoolean
6542 mono_icall_is_64bit_os (void)
6544 #if SIZEOF_VOID_P == 8
6547 #if defined(HAVE_SYS_UTSNAME_H)
6548 struct utsname name;
6550 if (uname (&name) >= 0) {
6551 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6557 #endif /* !HOST_WIN32 */
6559 ICALL_EXPORT MonoBoolean
6560 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6562 return mono_icall_is_64bit_os ();
6565 ICALL_EXPORT MonoStringHandle
6566 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6570 if (utf8_name == NULL)
6571 return NULL_HANDLE_STRING;
6573 value = g_getenv (utf8_name);
6576 return NULL_HANDLE_STRING;
6578 return mono_string_new_handle (mono_domain_get (), value, error);
6582 * There is no standard way to get at environ.
6585 #ifndef __MINGW32_VERSION
6586 #if defined(__APPLE__)
6587 #if defined (TARGET_OSX)
6588 /* Apple defines this in crt_externs.h but doesn't provide that header for
6589 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6590 * in fact exist on all implementations (so far)
6592 gchar ***_NSGetEnviron(void);
6593 #define environ (*_NSGetEnviron())
6595 static char *mono_environ[1] = { NULL };
6596 #define environ mono_environ
6597 #endif /* defined (TARGET_OSX) */
6605 ICALL_EXPORT MonoArray *
6606 ves_icall_System_Environment_GetCoomandLineArgs (void)
6609 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6610 mono_error_set_pending_exception (&error);
6616 mono_icall_get_environment_variable_names (void)
6626 for (e = environ; *e != 0; ++ e)
6629 domain = mono_domain_get ();
6630 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6631 if (mono_error_set_pending_exception (&error))
6635 for (e = environ; *e != 0; ++ e) {
6636 parts = g_strsplit (*e, "=", 2);
6638 str = mono_string_new (domain, *parts);
6639 mono_array_setref (names, n, str);
6649 #endif /* !HOST_WIN32 */
6651 ICALL_EXPORT MonoArray *
6652 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6654 return mono_icall_get_environment_variable_names ();
6659 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6661 gchar *utf8_name, *utf8_value;
6664 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6665 if (mono_error_set_pending_exception (&error))
6668 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6669 g_unsetenv (utf8_name);
6674 utf8_value = mono_string_to_utf8_checked (value, &error);
6675 if (!mono_error_ok (&error)) {
6677 mono_error_set_pending_exception (&error);
6680 g_setenv (utf8_name, utf8_value, TRUE);
6683 g_free (utf8_value);
6685 #endif /* !HOST_WIN32 */
6688 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6690 mono_icall_set_environment_variable (name, value);
6694 ves_icall_System_Environment_Exit (int result)
6696 mono_environment_exitcode_set (result);
6698 /* FIXME: There are some cleanup hangs that should be worked out, but
6699 * if the program is going to exit, everything will be cleaned up when
6700 * NaCl exits anyway.
6702 #ifndef __native_client__
6703 if (!mono_runtime_try_shutdown ())
6704 mono_thread_exit ();
6706 /* Suspend all managed threads since the runtime is going away */
6707 mono_thread_suspend_all_other_threads ();
6709 mono_runtime_quit ();
6712 /* we may need to do some cleanup here... */
6716 ICALL_EXPORT MonoStringHandle
6717 ves_icall_System_Environment_GetGacPath (MonoError *error)
6719 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6723 static inline MonoString *
6724 mono_icall_get_windows_folder_path (int folder)
6726 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6727 return mono_string_new (mono_domain_get (), "");
6729 #endif /* !HOST_WIN32 */
6731 ICALL_EXPORT MonoString*
6732 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6734 return mono_icall_get_windows_folder_path (folder);
6737 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6739 mono_icall_get_logical_drives (void)
6742 gunichar2 buf [256], *ptr, *dname;
6744 guint initial_size = 127, size = 128;
6747 MonoString *drivestr;
6748 MonoDomain *domain = mono_domain_get ();
6754 while (size > initial_size) {
6755 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6756 if (size > initial_size) {
6759 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6760 initial_size = size;
6774 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6775 if (mono_error_set_pending_exception (&error))
6782 while (*u16) { u16++; len ++; }
6783 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6784 if (mono_error_set_pending_exception (&error))
6787 mono_array_setref (result, ndrives++, drivestr);
6797 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6799 ICALL_EXPORT MonoArray *
6800 ves_icall_System_Environment_GetLogicalDrives (void)
6802 return mono_icall_get_logical_drives ();
6805 ICALL_EXPORT MonoString *
6806 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6809 gunichar2 volume_name [MAX_PATH + 1];
6811 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6813 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6814 mono_error_set_pending_exception (&error);
6818 ICALL_EXPORT MonoStringHandle
6819 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6821 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6824 static const char *encodings [] = {
6826 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6827 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6828 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6830 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6831 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6832 "x_unicode_2_0_utf_7",
6834 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6835 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6837 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6840 "unicodefffe", "utf_16be",
6847 * Returns the internal codepage, if the value of "int_code_page" is
6848 * 1 at entry, and we can not compute a suitable code page number,
6849 * returns the code page as a string
6851 ICALL_EXPORT MonoString*
6852 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6857 char *codepage = NULL;
6859 int want_name = *int_code_page;
6862 *int_code_page = -1;
6864 g_get_charset (&cset);
6865 c = codepage = g_strdup (cset);
6866 for (c = codepage; *c; c++){
6867 if (isascii (*c) && isalpha (*c))
6872 /* g_print ("charset: %s\n", cset); */
6874 /* handle some common aliases */
6877 for (i = 0; p != 0; ){
6880 p = encodings [++i];
6883 if (strcmp (p, codepage) == 0){
6884 *int_code_page = code;
6887 p = encodings [++i];
6890 if (strstr (codepage, "utf_8") != NULL)
6891 *int_code_page |= 0x10000000;
6894 if (want_name && *int_code_page == -1)
6895 return mono_string_new (mono_domain_get (), cset);
6900 ICALL_EXPORT MonoBoolean
6901 ves_icall_System_Environment_get_HasShutdownStarted (void)
6903 if (mono_runtime_is_shutting_down ())
6906 if (mono_domain_is_unloading (mono_domain_get ()))
6914 mono_icall_broadcast_setting_change (void)
6918 #endif /* !HOST_WIN32 */
6921 ves_icall_System_Environment_BroadcastSettingChange (void)
6923 mono_icall_broadcast_setting_change ();
6928 ves_icall_System_Environment_get_TickCount (void)
6930 /* this will overflow after ~24 days */
6931 return (gint32) (mono_msec_boottime () & 0xffffffff);
6935 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6940 #ifndef DISABLE_REMOTING
6941 ICALL_EXPORT MonoBoolean
6942 ves_icall_IsTransparentProxy (MonoObject *proxy)
6947 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6953 ICALL_EXPORT MonoReflectionMethod *
6954 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6955 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6957 MonoReflectionMethod *ret = NULL;
6962 MonoMethod **vtable;
6963 MonoMethod *res = NULL;
6965 MONO_CHECK_ARG_NULL (rtype, NULL);
6966 MONO_CHECK_ARG_NULL (rmethod, NULL);
6968 method = rmethod->method;
6969 klass = mono_class_from_mono_type (rtype->type);
6970 mono_class_init_checked (klass, &error);
6971 if (mono_error_set_pending_exception (&error))
6974 if (MONO_CLASS_IS_INTERFACE (klass))
6977 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6980 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6981 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6987 mono_class_setup_vtable (klass);
6988 vtable = klass->vtable;
6990 if (mono_class_is_interface (method->klass)) {
6991 gboolean variance_used = FALSE;
6992 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6993 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6995 res = vtable [offs + method->slot];
6997 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7000 if (method->slot != -1)
7001 res = vtable [method->slot];
7007 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7008 mono_error_set_pending_exception (&error);
7013 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7019 klass = mono_class_from_mono_type (type->type);
7020 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7021 if (!is_ok (&error)) {
7022 mono_error_set_pending_exception (&error);
7026 mono_vtable_set_is_remote (vtable, enable);
7029 #else /* DISABLE_REMOTING */
7032 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7034 g_assert_not_reached ();
7039 ICALL_EXPORT MonoObject *
7040 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7047 domain = mono_object_domain (type);
7048 klass = mono_class_from_mono_type (type->type);
7049 mono_class_init_checked (klass, &error);
7050 if (mono_error_set_pending_exception (&error))
7053 if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
7054 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7058 if (klass->rank >= 1) {
7059 g_assert (klass->rank == 1);
7060 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7061 mono_error_set_pending_exception (&error);
7064 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7065 if (!is_ok (&error)) {
7066 mono_error_set_pending_exception (&error);
7069 /* Bypass remoting object creation check */
7070 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7071 mono_error_set_pending_exception (&error);
7077 ICALL_EXPORT MonoStringHandle
7078 ves_icall_System_IO_get_temp_path (MonoError *error)
7080 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7083 #ifndef PLATFORM_NO_DRIVEINFO
7084 ICALL_EXPORT MonoBoolean
7085 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7086 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7090 ULARGE_INTEGER wapi_free_bytes_avail;
7091 ULARGE_INTEGER wapi_total_number_of_bytes;
7092 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7094 *error = ERROR_SUCCESS;
7095 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7096 &wapi_total_number_of_free_bytes);
7099 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7100 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7101 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7103 *free_bytes_avail = 0;
7104 *total_number_of_bytes = 0;
7105 *total_number_of_free_bytes = 0;
7106 *error = GetLastError ();
7112 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7113 static inline guint32
7114 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7116 return GetDriveType (mono_string_chars (root_path_name));
7118 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7120 ICALL_EXPORT guint32
7121 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7123 return mono_icall_drive_info_get_drive_type (root_path_name);
7126 #endif /* PLATFORM_NO_DRIVEINFO */
7128 ICALL_EXPORT gpointer
7129 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7132 gpointer result = mono_compile_method_checked (method, &error);
7133 mono_error_set_pending_exception (&error);
7137 ICALL_EXPORT MonoString *
7138 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7143 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7145 mono_icall_make_platform_path (path);
7147 mcpath = mono_string_new (mono_domain_get (), path);
7153 /* this is an icall */
7155 get_bundled_app_config (void)
7158 const gchar *app_config;
7161 gchar *config_file_name, *config_file_path;
7162 gsize len, config_file_path_length, config_ext_length;
7165 domain = mono_domain_get ();
7166 file = domain->setup->configuration_file;
7167 if (!file || file->length == 0)
7170 // Retrieve config file and remove the extension
7171 config_file_name = mono_string_to_utf8_checked (file, &error);
7172 if (mono_error_set_pending_exception (&error))
7174 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7175 if (!config_file_path)
7176 config_file_path = config_file_name;
7178 config_file_path_length = strlen (config_file_path);
7179 config_ext_length = strlen (".config");
7180 if (config_file_path_length <= config_ext_length)
7183 len = config_file_path_length - config_ext_length;
7184 module = (gchar *)g_malloc0 (len + 1);
7185 memcpy (module, config_file_path, len);
7186 // Get the config file from the module name
7187 app_config = mono_config_string_for_assembly_file (module);
7190 if (config_file_name != config_file_path)
7191 g_free (config_file_name);
7192 g_free (config_file_path);
7197 return mono_string_new (mono_domain_get (), app_config);
7200 static MonoStringHandle
7201 get_bundled_machine_config (MonoError *error)
7203 const gchar *machine_config;
7205 machine_config = mono_get_machine_config ();
7207 if (!machine_config)
7208 return NULL_HANDLE_STRING;
7210 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7213 ICALL_EXPORT MonoStringHandle
7214 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7216 return get_bundled_machine_config (error);
7220 ICALL_EXPORT MonoStringHandle
7221 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7223 return get_bundled_machine_config (error);
7226 ICALL_EXPORT MonoStringHandle
7227 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7229 return get_bundled_machine_config (error);
7233 ICALL_EXPORT MonoString *
7234 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7239 path = g_path_get_dirname (mono_get_config_dir ());
7241 mono_icall_make_platform_path (path);
7243 ipath = mono_string_new (mono_domain_get (), path);
7249 ICALL_EXPORT gboolean
7250 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7252 MonoPEResourceDataEntry *entry;
7255 if (!assembly || !result || !size)
7260 image = assembly->assembly->image;
7261 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7265 *result = mono_image_rva_map (image, entry->rde_data_offset);
7270 *size = entry->rde_size;
7275 ICALL_EXPORT MonoBoolean
7276 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7278 return mono_is_debugger_attached ();
7281 ICALL_EXPORT MonoBoolean
7282 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7284 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7285 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7291 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7293 if (mono_get_runtime_callbacks ()->debug_log)
7294 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7299 mono_icall_write_windows_debug_string (MonoString *message)
7301 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7303 #endif /* !HOST_WIN32 */
7306 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7308 mono_icall_write_windows_debug_string (message);
7311 /* Only used for value types */
7312 ICALL_EXPORT MonoObject *
7313 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7320 domain = mono_object_domain (type);
7321 klass = mono_class_from_mono_type (type->type);
7322 mono_class_init_checked (klass, &error);
7323 if (mono_error_set_pending_exception (&error))
7326 if (mono_class_is_nullable (klass))
7327 /* No arguments -> null */
7330 result = mono_object_new_checked (domain, klass, &error);
7331 mono_error_set_pending_exception (&error);
7335 ICALL_EXPORT MonoReflectionMethod *
7336 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7338 MonoReflectionMethod *ret = NULL;
7341 MonoClass *klass, *parent;
7342 MonoGenericContext *generic_inst = NULL;
7343 MonoMethod *method = m->method;
7344 MonoMethod *result = NULL;
7347 if (method->klass == NULL)
7350 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7351 MONO_CLASS_IS_INTERFACE (method->klass) ||
7352 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7355 slot = mono_method_get_vtable_slot (method);
7359 klass = method->klass;
7360 if (mono_class_is_ginst (klass)) {
7361 generic_inst = mono_class_get_context (klass);
7362 klass = mono_class_get_generic_class (klass)->container_class;
7367 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7368 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7369 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7370 or klass is the generic container class and generic_inst is the instantiation.
7372 when we go to the parent, if the parent is an open constructed type, we need to
7373 replace the type parameters by the definitions from the generic_inst, and then take it
7374 apart again into the klass and the generic_inst.
7376 For cases like this:
7377 class C<T> : B<T, int> {
7378 public override void Foo () { ... }
7380 class B<U,V> : A<HashMap<U,V>> {
7381 public override void Foo () { ... }
7384 public virtual void Foo () { ... }
7387 if at each iteration the parent isn't open, we can skip inflating it. if at some
7388 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7391 MonoGenericContext *parent_inst = NULL;
7392 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7393 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7394 if (!mono_error_ok (&error)) {
7395 mono_error_set_pending_exception (&error);
7399 if (mono_class_is_ginst (parent)) {
7400 parent_inst = mono_class_get_context (parent);
7401 parent = mono_class_get_generic_class (parent)->container_class;
7404 mono_class_setup_vtable (parent);
7405 if (parent->vtable_size <= slot)
7408 generic_inst = parent_inst;
7411 klass = klass->parent;
7414 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7415 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7416 if (!mono_error_ok (&error)) {
7417 mono_error_set_pending_exception (&error);
7421 generic_inst = NULL;
7423 if (mono_class_is_ginst (klass)) {
7424 generic_inst = mono_class_get_context (klass);
7425 klass = mono_class_get_generic_class (klass)->container_class;
7431 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7432 if (!mono_error_ok (&error)) {
7433 mono_error_set_pending_exception (&error);
7438 if (klass == method->klass)
7441 /*This is possible if definition == FALSE.
7442 * Do it here to be really sure we don't read invalid memory.
7444 if (slot >= klass->vtable_size)
7447 mono_class_setup_vtable (klass);
7449 result = klass->vtable [slot];
7450 if (result == NULL) {
7451 /* It is an abstract method */
7452 gboolean found = FALSE;
7453 gpointer iter = NULL;
7454 while ((result = mono_class_get_methods (klass, &iter))) {
7455 if (result->slot == slot) {
7460 /* found might be FALSE if we looked in an abstract class
7461 * that doesn't override an abstract method of its
7463 * abstract class Base {
7464 * public abstract void Foo ();
7466 * abstract class Derived : Base { }
7467 * class Child : Derived {
7468 * public override void Foo () { }
7471 * if m was Child.Foo and we ask for the base method,
7472 * then we get here with klass == Derived and found == FALSE
7474 /* but it shouldn't be the case that if we're looking
7475 * for the definition and didn't find a result; the
7476 * loop above should've taken us as far as we could
7478 g_assert (!(definition && !found));
7483 g_assert (result != NULL);
7485 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7486 mono_error_set_pending_exception (&error);
7490 ICALL_EXPORT MonoString*
7491 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7493 MonoMethod *method = m->method;
7495 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7500 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7502 iter->sig = *(MonoMethodSignature**)argsp;
7504 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7505 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7508 /* FIXME: it's not documented what start is exactly... */
7512 iter->args = argsp + sizeof (gpointer);
7514 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7516 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7519 ICALL_EXPORT MonoTypedRef
7520 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7522 guint32 i, arg_size;
7526 i = iter->sig->sentinelpos + iter->next_arg;
7528 g_assert (i < iter->sig->param_count);
7530 res.type = iter->sig->params [i];
7531 res.klass = mono_class_from_mono_type (res.type);
7532 arg_size = mono_type_stack_size (res.type, &align);
7533 #if defined(__arm__) || defined(__mips__)
7534 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7536 res.value = iter->args;
7537 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7538 /* Values are stored as 8 byte register sized objects, but 'value'
7539 * is dereferenced as a pointer in other routines.
7541 res.value = (char*)res.value + 4;
7543 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7544 if (arg_size <= sizeof (gpointer)) {
7546 int padding = arg_size - mono_type_size (res.type, &dummy);
7547 res.value = (guint8*)res.value + padding;
7550 iter->args = (char*)iter->args + arg_size;
7553 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7558 ICALL_EXPORT MonoTypedRef
7559 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7561 guint32 i, arg_size;
7565 i = iter->sig->sentinelpos + iter->next_arg;
7567 g_assert (i < iter->sig->param_count);
7569 while (i < iter->sig->param_count) {
7570 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7572 res.type = iter->sig->params [i];
7573 res.klass = mono_class_from_mono_type (res.type);
7574 /* FIXME: endianess issue... */
7575 arg_size = mono_type_stack_size (res.type, &align);
7576 #if defined(__arm__) || defined(__mips__)
7577 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7579 res.value = iter->args;
7580 iter->args = (char*)iter->args + arg_size;
7582 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7585 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7593 ICALL_EXPORT MonoType*
7594 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7598 i = iter->sig->sentinelpos + iter->next_arg;
7600 g_assert (i < iter->sig->param_count);
7602 return iter->sig->params [i];
7605 ICALL_EXPORT MonoObject*
7606 mono_TypedReference_ToObject (MonoTypedRef* tref)
7609 MonoObject *result = NULL;
7610 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7611 MonoObject** objp = (MonoObject **)tref->value;
7615 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7616 mono_error_set_pending_exception (&error);
7620 ICALL_EXPORT MonoTypedRef
7621 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7624 MonoReflectionField *f;
7626 MonoType *ftype = NULL;
7630 memset (&res, 0, sizeof (res));
7633 g_assert (mono_array_length (fields) > 0);
7635 klass = target->vtable->klass;
7637 for (i = 0; i < mono_array_length (fields); ++i) {
7638 f = mono_array_get (fields, MonoReflectionField*, i);
7640 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7643 if (f->field->parent != klass) {
7644 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7648 p = (guint8*)target + f->field->offset;
7650 p += f->field->offset - sizeof (MonoObject);
7651 klass = mono_class_from_mono_type (f->field->type);
7652 ftype = f->field->type;
7656 res.klass = mono_class_from_mono_type (ftype);
7663 prelink_method (MonoMethod *method, MonoError *error)
7665 const char *exc_class, *exc_arg;
7667 mono_error_init (error);
7668 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7670 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7672 mono_error_set_exception_instance (error,
7673 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7676 /* create the wrapper, too? */
7680 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7684 prelink_method (method->method, &error);
7685 mono_error_set_pending_exception (&error);
7689 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7692 MonoClass *klass = mono_class_from_mono_type (type->type);
7694 gpointer iter = NULL;
7696 mono_class_init_checked (klass, &error);
7697 if (mono_error_set_pending_exception (&error))
7700 while ((m = mono_class_get_methods (klass, &iter))) {
7701 prelink_method (m, &error);
7702 if (mono_error_set_pending_exception (&error))
7707 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7709 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7710 gint32 const **exponents,
7711 gunichar2 const **digitLowerTable,
7712 gunichar2 const **digitUpperTable,
7713 gint64 const **tenPowersList,
7714 gint32 const **decHexDigits)
7716 *mantissas = Formatter_MantissaBitsTable;
7717 *exponents = Formatter_TensExponentTable;
7718 *digitLowerTable = Formatter_DigitLowerTable;
7719 *digitUpperTable = Formatter_DigitUpperTable;
7720 *tenPowersList = Formatter_TenPowersList;
7721 *decHexDigits = Formatter_DecHexDigits;
7725 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7726 * and avoid useless allocations.
7729 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7731 MonoReflectionType *rt;
7735 mono_error_init (error);
7736 for (i = 0; i < type->num_mods; ++i) {
7737 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7742 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7743 return_val_if_nok (error, NULL);
7745 for (i = 0; i < type->num_mods; ++i) {
7746 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7747 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7748 return_val_if_nok (error, NULL);
7750 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7751 return_val_if_nok (error, NULL);
7753 mono_array_setref (res, count, rt);
7760 ICALL_EXPORT MonoArray*
7761 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7764 MonoType *type = param->ClassImpl->type;
7765 MonoClass *member_class = mono_object_class (param->MemberImpl);
7766 MonoMethod *method = NULL;
7769 MonoMethodSignature *sig;
7772 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7773 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7774 method = rmethod->method;
7775 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7776 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7777 if (!(method = prop->property->get))
7778 method = prop->property->set;
7781 char *type_name = mono_type_get_full_name (member_class);
7782 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7783 MonoException *ex = mono_get_exception_not_supported (msg);
7786 mono_set_pending_exception (ex);
7790 image = method->klass->image;
7791 pos = param->PositionImpl;
7792 sig = mono_method_signature (method);
7796 type = sig->params [pos];
7798 res = type_array_from_modifiers (image, type, optional, &error);
7799 mono_error_set_pending_exception (&error);
7804 get_property_type (MonoProperty *prop)
7806 MonoMethodSignature *sig;
7808 sig = mono_method_signature (prop->get);
7810 } else if (prop->set) {
7811 sig = mono_method_signature (prop->set);
7812 return sig->params [sig->param_count - 1];
7817 ICALL_EXPORT MonoArray*
7818 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7821 MonoType *type = get_property_type (property->property);
7822 MonoImage *image = property->klass->image;
7827 res = type_array_from_modifiers (image, type, optional, &error);
7828 mono_error_set_pending_exception (&error);
7833 *Construct a MonoType suited to be used to decode a constant blob object.
7835 * @type is the target type which will be constructed
7836 * @blob_type is the blob type, for example, that comes from the constant table
7837 * @real_type is the expected constructed type.
7840 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7842 type->type = blob_type;
7843 type->data.klass = NULL;
7844 if (blob_type == MONO_TYPE_CLASS)
7845 type->data.klass = mono_defaults.object_class;
7846 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7847 /* For enums, we need to use the base type */
7848 type->type = MONO_TYPE_VALUETYPE;
7849 type->data.klass = mono_class_from_mono_type (real_type);
7851 type->data.klass = mono_class_from_mono_type (real_type);
7854 ICALL_EXPORT MonoObject*
7855 property_info_get_default_value (MonoReflectionProperty *property)
7859 MonoProperty *prop = property->property;
7860 MonoType *type = get_property_type (prop);
7861 MonoDomain *domain = mono_object_domain (property);
7862 MonoTypeEnum def_type;
7863 const char *def_value;
7866 mono_class_init (prop->parent);
7868 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7869 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7873 def_value = mono_class_get_property_default_value (prop, &def_type);
7875 mono_type_from_blob_type (&blob_type, def_type, type);
7876 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7878 mono_error_set_pending_exception (&error);
7882 ICALL_EXPORT MonoBoolean
7883 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7886 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7887 MonoCustomAttrInfo *cinfo;
7890 mono_class_init_checked (attr_class, &error);
7891 if (mono_error_set_pending_exception (&error))
7894 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7895 if (!is_ok (&error)) {
7896 mono_error_set_pending_exception (&error);
7901 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7903 mono_custom_attrs_free (cinfo);
7907 ICALL_EXPORT MonoArray*
7908 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7910 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7915 mono_class_init_checked (attr_class, &error);
7916 if (mono_error_set_pending_exception (&error))
7920 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7921 if (!mono_error_ok (&error)) {
7922 mono_error_set_pending_exception (&error);
7929 ICALL_EXPORT MonoArray*
7930 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7934 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7935 mono_error_set_pending_exception (&error);
7940 ICALL_EXPORT MonoString*
7941 ves_icall_Mono_Runtime_GetDisplayName (void)
7944 MonoString *display_name;
7946 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7947 display_name = mono_string_new (mono_domain_get (), info);
7949 return display_name;
7952 ICALL_EXPORT MonoString*
7953 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7956 MonoString *message;
7960 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7961 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7964 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7966 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7967 if (mono_error_set_pending_exception (&error))
7975 static inline gint32
7976 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
7978 return WAIT_TIMEOUT;
7980 #endif /* !HOST_WIN32 */
7983 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7985 return mono_icall_wait_for_input_idle (handle, milliseconds);
7989 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7991 return mono_process_current_pid ();
7994 ICALL_EXPORT MonoBoolean
7995 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
8007 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
8009 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
8013 ICALL_EXPORT MonoObject*
8014 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
8016 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
8021 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
8023 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
8027 ICALL_EXPORT MonoObject*
8028 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
8030 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
8034 ICALL_EXPORT MonoBoolean
8035 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
8037 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
8042 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
8044 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
8048 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
8050 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
8055 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
8057 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
8061 ICALL_EXPORT mono_unichar2*
8062 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
8064 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
8071 #ifndef DISABLE_ICALL_TABLES
8073 #define ICALL_TYPE(id,name,first)
8074 #define ICALL(id,name,func) Icall_ ## id,
8075 #define HANDLES(inner) inner
8078 #include "metadata/icall-def.h"
8084 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8085 #define ICALL(id,name,func)
8087 #define HANDLES(inner) inner
8089 #include "metadata/icall-def.h"
8095 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8096 #define ICALL(id,name,func)
8098 #define HANDLES(inner) inner
8100 guint16 first_icall;
8103 static const IcallTypeDesc
8104 icall_type_descs [] = {
8105 #include "metadata/icall-def.h"
8109 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8112 #define HANDLES(inner) inner
8114 #define ICALL_TYPE(id,name,first)
8117 #ifdef HAVE_ARRAY_ELEM_INIT
8118 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8119 #define MSGSTRFIELD1(line) str##line
8121 static const struct msgstrtn_t {
8122 #define ICALL(id,name,func)
8124 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8125 #include "metadata/icall-def.h"
8127 } icall_type_names_str = {
8128 #define ICALL_TYPE(id,name,first) (name),
8129 #include "metadata/icall-def.h"
8132 static const guint16 icall_type_names_idx [] = {
8133 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8134 #include "metadata/icall-def.h"
8137 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8139 static const struct msgstr_t {
8141 #define ICALL_TYPE(id,name,first)
8142 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8143 #include "metadata/icall-def.h"
8145 } icall_names_str = {
8146 #define ICALL(id,name,func) (name),
8147 #include "metadata/icall-def.h"
8150 static const guint16 icall_names_idx [] = {
8151 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8152 #include "metadata/icall-def.h"
8155 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8161 #define ICALL_TYPE(id,name,first) name,
8162 #define ICALL(id,name,func)
8163 static const char* const
8164 icall_type_names [] = {
8165 #include "metadata/icall-def.h"
8169 #define icall_type_name_get(id) (icall_type_names [(id)])
8173 #define ICALL_TYPE(id,name,first)
8174 #define ICALL(id,name,func) name,
8175 static const char* const
8177 #include "metadata/icall-def.h"
8180 #define icall_name_get(id) icall_names [(id)]
8182 #endif /* !HAVE_ARRAY_ELEM_INIT */
8185 #define HANDLES(inner) inner
8188 #define ICALL_TYPE(id,name,first)
8189 #define ICALL(id,name,func) func,
8190 static const gconstpointer
8191 icall_functions [] = {
8192 #include "metadata/icall-def.h"
8196 #ifdef ENABLE_ICALL_SYMBOL_MAP
8198 #define HANDLES(inner) inner
8201 #define ICALL_TYPE(id,name,first)
8202 #define ICALL(id,name,func) #func,
8203 static const gconstpointer
8204 icall_symbols [] = {
8205 #include "metadata/icall-def.h"
8212 #define ICALL_TYPE(id,name,first)
8213 #define ICALL(id,name,func) 0,
8215 #define HANDLES(inner) 1,
8217 icall_uses_handles [] = {
8218 #include "metadata/icall-def.h"
8223 #endif /* DISABLE_ICALL_TABLES */
8225 static mono_mutex_t icall_mutex;
8226 static GHashTable *icall_hash = NULL;
8227 static GHashTable *jit_icall_hash_name = NULL;
8228 static GHashTable *jit_icall_hash_addr = NULL;
8231 mono_icall_init (void)
8233 #ifndef DISABLE_ICALL_TABLES
8236 /* check that tables are sorted: disable in release */
8239 const char *prev_class = NULL;
8240 const char *prev_method;
8242 for (i = 0; i < Icall_type_num; ++i) {
8243 const IcallTypeDesc *desc;
8246 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8247 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8248 prev_class = icall_type_name_get (i);
8249 desc = &icall_type_descs [i];
8250 num_icalls = icall_desc_num_icalls (desc);
8251 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8252 for (j = 0; j < num_icalls; ++j) {
8253 const char *methodn = icall_name_get (desc->first_icall + j);
8254 if (prev_method && strcmp (prev_method, methodn) >= 0)
8255 g_print ("method %s should come before method %s\n", methodn, prev_method);
8256 prev_method = methodn;
8262 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8263 mono_os_mutex_init (&icall_mutex);
8267 mono_icall_lock (void)
8269 mono_locks_os_acquire (&icall_mutex, IcallLock);
8273 mono_icall_unlock (void)
8275 mono_locks_os_release (&icall_mutex, IcallLock);
8279 mono_icall_cleanup (void)
8281 g_hash_table_destroy (icall_hash);
8282 g_hash_table_destroy (jit_icall_hash_name);
8283 g_hash_table_destroy (jit_icall_hash_addr);
8284 mono_os_mutex_destroy (&icall_mutex);
8288 * mono_add_internal_call:
8289 * @name: method specification to surface to the managed world
8290 * @method: pointer to a C method to invoke when the method is called
8292 * This method surfaces the C function pointed by @method as a method
8293 * that has been surfaced in managed code with the method specified in
8294 * @name as an internal call.
8296 * Internal calls are surfaced to all app domains loaded and they are
8297 * accessibly by a type with the specified name.
8299 * You must provide a fully qualified type name, that is namespaces
8300 * and type name, followed by a colon and the method name, with an
8301 * optional signature to bind.
8303 * For example, the following are all valid declarations:
8305 * "MyApp.Services.ScriptService:Accelerate"
8306 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8308 * You use method parameters in cases where there might be more than
8309 * one surface method to managed code. That way you can register different
8310 * internal calls for different method overloads.
8312 * The internal calls are invoked with no marshalling. This means that .NET
8313 * types like System.String are exposed as `MonoString *` parameters. This is
8314 * different than the way that strings are surfaced in P/Invoke.
8316 * For more information on how the parameters are marshalled, see the
8317 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8320 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8321 * reference for more information on the format of method descriptions.
8324 mono_add_internal_call (const char *name, gconstpointer method)
8328 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8330 mono_icall_unlock ();
8333 #ifndef DISABLE_ICALL_TABLES
8335 #ifdef HAVE_ARRAY_ELEM_INIT
8337 compare_method_imap (const void *key, const void *elem)
8339 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8340 return strcmp (key, method_name);
8344 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8346 const guint16 *nameslot = (const guint16 *)mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
8349 return (nameslot - &icall_names_idx [0]);
8353 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8355 gsize slotnum = find_slot_icall (imap, name);
8358 return (gboolean)icall_uses_handles [slotnum];
8362 find_method_icall (const IcallTypeDesc *imap, const char *name)
8364 gsize slotnum = find_slot_icall (imap, name);
8367 return (gpointer)icall_functions [slotnum];
8371 compare_class_imap (const void *key, const void *elem)
8373 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8374 return strcmp (key, class_name);
8377 static const IcallTypeDesc*
8378 find_class_icalls (const char *name)
8380 const guint16 *nameslot = (const guint16 *)mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8383 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8386 #else /* HAVE_ARRAY_ELEM_INIT */
8389 compare_method_imap (const void *key, const void *elem)
8391 const char** method_name = (const char**)elem;
8392 return strcmp (key, *method_name);
8396 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8398 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8401 return nameslot - icall_names;
8405 find_method_icall (const IcallTypeDesc *imap, const char *name)
8407 gsize slotnum = find_slot_icall (imap, name);
8410 return (gpointer)icall_functions [slotnum];
8414 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8416 gsize slotnum = find_slot_icall (imap, name);
8419 return (gboolean)icall_uses_handles [slotnum];
8423 compare_class_imap (const void *key, const void *elem)
8425 const char** class_name = (const char**)elem;
8426 return strcmp (key, *class_name);
8429 static const IcallTypeDesc*
8430 find_class_icalls (const char *name)
8432 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8435 return &icall_type_descs [nameslot - icall_type_names];
8438 #endif /* HAVE_ARRAY_ELEM_INIT */
8440 #endif /* DISABLE_ICALL_TABLES */
8443 * we should probably export this as an helper (handle nested types).
8444 * Returns the number of chars written in buf.
8447 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8449 int nspacelen, cnamelen;
8450 nspacelen = strlen (klass->name_space);
8451 cnamelen = strlen (klass->name);
8452 if (nspacelen + cnamelen + 2 > bufsize)
8455 memcpy (buf, klass->name_space, nspacelen);
8456 buf [nspacelen ++] = '.';
8458 memcpy (buf + nspacelen, klass->name, cnamelen);
8459 buf [nspacelen + cnamelen] = 0;
8460 return nspacelen + cnamelen;
8463 #ifdef DISABLE_ICALL_TABLES
8465 no_icall_table (void)
8467 g_assert_not_reached ();
8472 * mono_lookup_internal_call_full:
8473 * @method: the method to look up
8474 * @uses_handles: out argument if method needs handles around managed objects.
8476 * Returns a pointer to the icall code for the given method. If
8477 * uses_handles is not NULL, it will be set to TRUE if the method
8478 * needs managed objects wrapped using the infrastructure in handle.h
8480 * If the method is not found, warns and returns NULL.
8483 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8488 int typelen = 0, mlen, siglen;
8490 #ifndef DISABLE_ICALL_TABLES
8491 const IcallTypeDesc *imap = NULL;
8494 g_assert (method != NULL);
8496 if (method->is_inflated)
8497 method = ((MonoMethodInflated *) method)->declaring;
8499 if (method->klass->nested_in) {
8500 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8504 mname [pos++] = '/';
8507 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8513 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8518 #ifndef DISABLE_ICALL_TABLES
8519 imap = find_class_icalls (mname);
8522 mname [typelen] = ':';
8523 mname [typelen + 1] = ':';
8525 mlen = strlen (method->name);
8526 memcpy (mname + typelen + 2, method->name, mlen);
8527 sigstart = mname + typelen + 2 + mlen;
8530 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8531 siglen = strlen (tmpsig);
8532 if (typelen + mlen + siglen + 6 > sizeof (mname))
8535 memcpy (sigstart + 1, tmpsig, siglen);
8536 sigstart [siglen + 1] = ')';
8537 sigstart [siglen + 2] = 0;
8542 res = g_hash_table_lookup (icall_hash, mname);
8545 *uses_handles = FALSE;
8546 mono_icall_unlock ();;
8549 /* try without signature */
8551 res = g_hash_table_lookup (icall_hash, mname);
8554 *uses_handles = FALSE;
8555 mono_icall_unlock ();
8559 #ifdef DISABLE_ICALL_TABLES
8560 mono_icall_unlock ();
8561 /* Fail only when the result is actually used */
8562 /* mono_marshal_get_native_wrapper () depends on this */
8563 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8564 return ves_icall_System_String_ctor_RedirectToCreateString;
8566 return no_icall_table;
8568 /* it wasn't found in the static call tables */
8571 *uses_handles = FALSE;
8572 mono_icall_unlock ();
8575 res = find_method_icall (imap, sigstart - mlen);
8578 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8579 mono_icall_unlock ();
8582 /* try _with_ signature */
8584 res = find_method_icall (imap, sigstart - mlen);
8587 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8588 mono_icall_unlock ();
8592 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8593 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8594 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8595 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8596 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");
8597 g_print ("If you see other errors or faults after this message they are probably related\n");
8598 g_print ("and you need to fix your mono install first.\n");
8600 mono_icall_unlock ();
8607 mono_lookup_internal_call (MonoMethod *method)
8609 return mono_lookup_internal_call_full (method, NULL);
8612 #ifdef ENABLE_ICALL_SYMBOL_MAP
8614 func_cmp (gconstpointer key, gconstpointer p)
8616 return (gsize)key - (gsize)*(gsize*)p;
8621 * mono_lookup_icall_symbol:
8623 * Given the icall METHOD, returns its C symbol.
8626 mono_lookup_icall_symbol (MonoMethod *m)
8628 #ifdef DISABLE_ICALL_TABLES
8629 g_assert_not_reached ();
8632 #ifdef ENABLE_ICALL_SYMBOL_MAP
8636 static gconstpointer *functions_sorted;
8637 static const char**symbols_sorted;
8638 static gboolean inited;
8643 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8644 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8645 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8646 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8647 /* Bubble sort the two arrays */
8651 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8652 if (functions_sorted [i] > functions_sorted [i + 1]) {
8655 tmp = functions_sorted [i];
8656 functions_sorted [i] = functions_sorted [i + 1];
8657 functions_sorted [i + 1] = tmp;
8658 tmp = symbols_sorted [i];
8659 symbols_sorted [i] = symbols_sorted [i + 1];
8660 symbols_sorted [i + 1] = tmp;
8667 func = mono_lookup_internal_call (m);
8670 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8674 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8676 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8677 g_assert_not_reached ();
8684 type_from_typename (char *type_name)
8686 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8688 if (!strcmp (type_name, "int"))
8689 klass = mono_defaults.int_class;
8690 else if (!strcmp (type_name, "ptr"))
8691 klass = mono_defaults.int_class;
8692 else if (!strcmp (type_name, "void"))
8693 klass = mono_defaults.void_class;
8694 else if (!strcmp (type_name, "int32"))
8695 klass = mono_defaults.int32_class;
8696 else if (!strcmp (type_name, "uint32"))
8697 klass = mono_defaults.uint32_class;
8698 else if (!strcmp (type_name, "int8"))
8699 klass = mono_defaults.sbyte_class;
8700 else if (!strcmp (type_name, "uint8"))
8701 klass = mono_defaults.byte_class;
8702 else if (!strcmp (type_name, "int16"))
8703 klass = mono_defaults.int16_class;
8704 else if (!strcmp (type_name, "uint16"))
8705 klass = mono_defaults.uint16_class;
8706 else if (!strcmp (type_name, "long"))
8707 klass = mono_defaults.int64_class;
8708 else if (!strcmp (type_name, "ulong"))
8709 klass = mono_defaults.uint64_class;
8710 else if (!strcmp (type_name, "float"))
8711 klass = mono_defaults.single_class;
8712 else if (!strcmp (type_name, "double"))
8713 klass = mono_defaults.double_class;
8714 else if (!strcmp (type_name, "object"))
8715 klass = mono_defaults.object_class;
8716 else if (!strcmp (type_name, "obj"))
8717 klass = mono_defaults.object_class;
8718 else if (!strcmp (type_name, "string"))
8719 klass = mono_defaults.string_class;
8720 else if (!strcmp (type_name, "bool"))
8721 klass = mono_defaults.boolean_class;
8722 else if (!strcmp (type_name, "boolean"))
8723 klass = mono_defaults.boolean_class;
8725 g_error ("%s", type_name);
8726 g_assert_not_reached ();
8728 return &klass->byval_arg;
8732 * LOCKING: Take the corlib image lock.
8734 MonoMethodSignature*
8735 mono_create_icall_signature (const char *sigstr)
8740 MonoMethodSignature *res, *res2;
8741 MonoImage *corlib = mono_defaults.corlib;
8743 mono_image_lock (corlib);
8744 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8745 mono_image_unlock (corlib);
8750 parts = g_strsplit (sigstr, " ", 256);
8759 res = mono_metadata_signature_alloc (corlib, len - 1);
8764 * Under windows, the default pinvoke calling convention is STDCALL but
8767 res->call_convention = MONO_CALL_C;
8770 res->ret = type_from_typename (parts [0]);
8771 for (i = 1; i < len; ++i) {
8772 res->params [i - 1] = type_from_typename (parts [i]);
8777 mono_image_lock (corlib);
8778 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8780 res = res2; /*Value is allocated in the image pool*/
8782 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8783 mono_image_unlock (corlib);
8789 mono_find_jit_icall_by_name (const char *name)
8791 MonoJitICallInfo *info;
8792 g_assert (jit_icall_hash_name);
8795 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8796 mono_icall_unlock ();
8801 mono_find_jit_icall_by_addr (gconstpointer addr)
8803 MonoJitICallInfo *info;
8804 g_assert (jit_icall_hash_addr);
8807 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8808 mono_icall_unlock ();
8814 * mono_get_jit_icall_info:
8816 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8817 * caller should access it while holding the icall lock.
8820 mono_get_jit_icall_info (void)
8822 return jit_icall_hash_name;
8826 * mono_lookup_jit_icall_symbol:
8828 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8831 mono_lookup_jit_icall_symbol (const char *name)
8833 MonoJitICallInfo *info;
8834 const char *res = NULL;
8837 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8839 res = info->c_symbol;
8840 mono_icall_unlock ();
8845 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8848 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8849 mono_icall_unlock ();
8853 * If NO_RAISE is set, that means the icall is not calling mono_raise_exception () directly or indirectly. The JIT might be able to call these
8854 * icalls without wrappers in some cases.
8857 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8859 MonoJitICallInfo *info;
8866 if (!jit_icall_hash_name) {
8867 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8868 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8871 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8872 g_warning ("jit icall already defined \"%s\"\n", name);
8873 g_assert_not_reached ();
8876 info = g_new0 (MonoJitICallInfo, 1);
8881 info->c_symbol = c_symbol;
8882 info->no_raise = no_raise;
8885 info->wrapper = func;
8887 info->wrapper = NULL;
8890 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8891 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8893 mono_icall_unlock ();
8898 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8900 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);