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;
2102 g_assert (fidx >= 0 && fidx < klass->field.count);
2103 g_assert (klass->ext);
2104 g_assert (klass->ext->field_def_values);
2105 def_type = klass->ext->field_def_values [fidx].def_type;
2106 def_value = klass->ext->field_def_values [fidx].data;
2107 if (def_type == MONO_TYPE_END) {
2108 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2112 def_value = mono_class_get_field_default_value (field, &def_type);
2113 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2115 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2120 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2124 case MONO_TYPE_BOOLEAN:
2127 case MONO_TYPE_CHAR:
2135 case MONO_TYPE_R8: {
2138 /* boxed value type */
2139 t = g_new0 (MonoType, 1);
2141 klass = mono_class_from_mono_type (t);
2143 o = mono_object_new_checked (domain, klass, &error);
2144 if (!mono_error_ok (&error)) {
2145 mono_error_set_pending_exception (&error);
2148 v = ((gchar *) o) + sizeof (MonoObject);
2149 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2150 if (mono_error_set_pending_exception (&error))
2154 case MONO_TYPE_STRING:
2155 case MONO_TYPE_CLASS:
2156 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2157 if (mono_error_set_pending_exception (&error))
2161 g_assert_not_reached ();
2167 ICALL_EXPORT MonoReflectionType*
2168 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2171 MonoReflectionType *ret;
2174 type = mono_field_get_type_checked (ref_field->field, &error);
2175 if (!mono_error_ok (&error)) {
2176 mono_error_set_pending_exception (&error);
2180 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2181 if (!mono_error_ok (&error)) {
2182 mono_error_set_pending_exception (&error);
2189 /* From MonoProperty.cs */
2191 PInfo_Attributes = 1,
2192 PInfo_GetMethod = 1 << 1,
2193 PInfo_SetMethod = 1 << 2,
2194 PInfo_ReflectedType = 1 << 3,
2195 PInfo_DeclaringType = 1 << 4,
2200 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2203 MonoReflectionType *rt;
2204 MonoReflectionMethod *rm;
2205 MonoDomain *domain = mono_object_domain (property);
2206 const MonoProperty *pproperty = property->property;
2208 if ((req_info & PInfo_ReflectedType) != 0) {
2209 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2210 if (mono_error_set_pending_exception (&error))
2213 MONO_STRUCT_SETREF (info, parent, rt);
2215 if ((req_info & PInfo_DeclaringType) != 0) {
2216 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2217 if (mono_error_set_pending_exception (&error))
2220 MONO_STRUCT_SETREF (info, declaring_type, rt);
2223 if ((req_info & PInfo_Name) != 0)
2224 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2226 if ((req_info & PInfo_Attributes) != 0)
2227 info->attrs = pproperty->attrs;
2229 if ((req_info & PInfo_GetMethod) != 0) {
2230 if (pproperty->get &&
2231 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2232 pproperty->get->klass == property->klass)) {
2233 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2234 if (mono_error_set_pending_exception (&error))
2240 MONO_STRUCT_SETREF (info, get, rm);
2242 if ((req_info & PInfo_SetMethod) != 0) {
2243 if (pproperty->set &&
2244 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2245 pproperty->set->klass == property->klass)) {
2246 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2247 if (mono_error_set_pending_exception (&error))
2253 MONO_STRUCT_SETREF (info, set, rm);
2256 * There may be other methods defined for properties, though, it seems they are not exposed
2257 * in the reflection API
2262 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2265 MonoReflectionType *rt;
2266 MonoReflectionMethod *rm;
2267 MonoDomain *domain = mono_object_domain (event);
2269 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2270 if (mono_error_set_pending_exception (&error))
2273 MONO_STRUCT_SETREF (info, reflected_type, rt);
2275 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2276 if (mono_error_set_pending_exception (&error))
2279 MONO_STRUCT_SETREF (info, declaring_type, rt);
2281 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2282 info->attrs = event->event->attrs;
2284 if (event->event->add) {
2285 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2286 if (mono_error_set_pending_exception (&error))
2292 MONO_STRUCT_SETREF (info, add_method, rm);
2294 if (event->event->remove) {
2295 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2296 if (mono_error_set_pending_exception (&error))
2302 MONO_STRUCT_SETREF (info, remove_method, rm);
2304 if (event->event->raise) {
2305 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2306 if (mono_error_set_pending_exception (&error))
2312 MONO_STRUCT_SETREF (info, raise_method, rm);
2314 #ifndef MONO_SMALL_CONFIG
2315 if (event->event->other) {
2317 while (event->event->other [n])
2319 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2320 if (mono_error_set_pending_exception (&error))
2322 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2324 for (i = 0; i < n; i++) {
2325 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2326 if (mono_error_set_pending_exception (&error))
2328 mono_array_setref (info->other_methods, i, rm);
2335 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2340 mono_class_setup_interfaces (klass, error);
2341 if (!mono_error_ok (error))
2344 for (i = 0; i < klass->interface_count; i++) {
2345 ic = klass->interfaces [i];
2346 g_hash_table_insert (ifaces, ic, ic);
2348 collect_interfaces (ic, ifaces, error);
2349 if (!mono_error_ok (error))
2355 MonoArray *iface_array;
2356 MonoGenericContext *context;
2360 } FillIfaceArrayData;
2363 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2365 MonoReflectionType *rt;
2366 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2367 MonoClass *ic = (MonoClass *)key;
2368 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2370 if (!mono_error_ok (data->error))
2373 if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
2374 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2375 if (!mono_error_ok (data->error))
2379 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2380 if (!mono_error_ok (data->error))
2383 mono_array_setref (data->iface_array, data->next_idx++, rt);
2386 mono_metadata_free_type (inflated);
2390 get_interfaces_hash (gconstpointer v1)
2392 MonoClass *k = (MonoClass*)v1;
2394 return k->type_token;
2397 ICALL_EXPORT MonoArray*
2398 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2401 MonoClass *klass = mono_class_from_mono_type (type->type);
2403 FillIfaceArrayData data = { 0 };
2406 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2408 if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
2409 data.context = mono_class_get_context (klass);
2410 klass = mono_class_get_generic_class (klass)->container_class;
2413 for (parent = klass; parent; parent = parent->parent) {
2414 mono_class_setup_interfaces (parent, &error);
2415 if (!mono_error_ok (&error))
2417 collect_interfaces (parent, iface_hash, &error);
2418 if (!mono_error_ok (&error))
2422 data.error = &error;
2423 data.domain = mono_object_domain (type);
2425 len = g_hash_table_size (iface_hash);
2427 g_hash_table_destroy (iface_hash);
2428 if (!data.domain->empty_types) {
2429 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2430 if (!is_ok (&error))
2433 return data.domain->empty_types;
2436 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2437 if (!is_ok (&error))
2439 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2440 if (!mono_error_ok (&error))
2443 g_hash_table_destroy (iface_hash);
2444 return data.iface_array;
2447 g_hash_table_destroy (iface_hash);
2448 mono_error_set_pending_exception (&error);
2453 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2455 gboolean variance_used;
2456 MonoClass *klass = mono_class_from_mono_type (type->type);
2457 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2458 MonoReflectionMethod *member;
2461 int i = 0, len, ioffset;
2465 mono_class_init_checked (klass, &error);
2466 if (mono_error_set_pending_exception (&error))
2468 mono_class_init_checked (iclass, &error);
2469 if (mono_error_set_pending_exception (&error))
2472 mono_class_setup_vtable (klass);
2474 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2478 len = mono_class_num_methods (iclass);
2479 domain = mono_object_domain (type);
2480 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2481 if (mono_error_set_pending_exception (&error))
2483 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2484 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2485 if (mono_error_set_pending_exception (&error))
2487 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2489 while ((method = mono_class_get_methods (iclass, &iter))) {
2490 member = mono_method_get_object_checked (domain, method, iclass, &error);
2491 if (mono_error_set_pending_exception (&error))
2493 mono_array_setref (*methods, i, member);
2494 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2495 if (mono_error_set_pending_exception (&error))
2497 mono_array_setref (*targets, i, member);
2504 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2507 MonoClass *klass = mono_class_from_mono_type (type->type);
2509 mono_class_init_checked (klass, &error);
2510 if (mono_error_set_pending_exception (&error))
2513 if (image_is_dynamic (klass->image)) {
2514 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2515 *packing = tb->packing_size;
2516 *size = tb->class_size;
2518 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2522 ICALL_EXPORT MonoReflectionType*
2523 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2526 MonoReflectionType *ret;
2529 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2530 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2531 mono_error_set_pending_exception (&error);
2535 klass = mono_class_from_mono_type (type->type);
2536 mono_class_init_checked (klass, &error);
2537 if (mono_error_set_pending_exception (&error))
2541 // GetElementType should only return a type for:
2542 // Array Pointer PassedByRef
2543 if (type->type->byref)
2544 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2545 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2546 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2547 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2548 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2552 mono_error_set_pending_exception (&error);
2557 ICALL_EXPORT MonoReflectionType*
2558 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2561 MonoReflectionType *ret;
2563 if (type->type->byref)
2566 MonoClass *klass = mono_class_from_mono_type (type->type);
2570 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2571 mono_error_set_pending_exception (&error);
2576 ICALL_EXPORT MonoBoolean
2577 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2579 return type->type->type == MONO_TYPE_PTR;
2582 ICALL_EXPORT MonoBoolean
2583 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2585 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)));
2588 ICALL_EXPORT MonoBoolean
2589 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2591 return type->type->byref;
2594 ICALL_EXPORT MonoBoolean
2595 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2598 MonoClass *klass = mono_class_from_mono_type (type->type);
2599 mono_class_init_checked (klass, &error);
2600 if (mono_error_set_pending_exception (&error))
2603 return mono_class_is_com_object (klass);
2606 ICALL_EXPORT guint32
2607 ves_icall_reflection_get_token (MonoObject* obj)
2610 guint32 result = mono_reflection_get_token_checked (obj, &error);
2611 mono_error_set_pending_exception (&error);
2615 ICALL_EXPORT MonoReflectionModule*
2616 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2619 MonoReflectionModule *result = NULL;
2620 MonoClass *klass = mono_class_from_mono_type (type->type);
2621 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2622 mono_error_set_pending_exception (&error);
2626 ICALL_EXPORT MonoReflectionAssembly*
2627 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2630 MonoDomain *domain = mono_domain_get ();
2631 MonoClass *klass = mono_class_from_mono_type (type->type);
2632 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2633 mono_error_set_pending_exception (&error);
2637 ICALL_EXPORT MonoReflectionType*
2638 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2641 MonoReflectionType *ret;
2642 MonoDomain *domain = mono_domain_get ();
2645 if (type->type->byref)
2647 if (type->type->type == MONO_TYPE_VAR) {
2648 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2649 klass = param ? param->owner.klass : NULL;
2650 } else if (type->type->type == MONO_TYPE_MVAR) {
2651 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2652 klass = param ? param->owner.method->klass : NULL;
2654 klass = mono_class_from_mono_type (type->type)->nested_in;
2660 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2661 mono_error_set_pending_exception (&error);
2666 ICALL_EXPORT MonoStringHandle
2667 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2669 MonoDomain *domain = mono_domain_get ();
2670 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2671 MonoClass *klass = mono_class_from_mono_type (type);
2674 char *n = g_strdup_printf ("%s&", klass->name);
2675 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2681 return mono_string_new_handle (domain, klass->name, error);
2685 ICALL_EXPORT MonoStringHandle
2686 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2688 MonoDomain *domain = mono_domain_get ();
2689 MonoClass *klass = mono_class_from_mono_type_handle (type);
2691 while (klass->nested_in)
2692 klass = klass->nested_in;
2694 if (klass->name_space [0] == '\0')
2695 return NULL_HANDLE_STRING;
2697 return mono_string_new_handle (domain, klass->name_space, error);
2701 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2705 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2706 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2710 klass = mono_class_from_mono_type (type->type);
2716 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2718 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2721 ICALL_EXPORT MonoArray*
2722 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2725 MonoReflectionType *rt;
2727 MonoClass *klass, *pklass;
2728 MonoDomain *domain = mono_object_domain (type);
2731 klass = mono_class_from_mono_type (type->type);
2733 if (mono_class_is_gtd (klass)) {
2734 MonoGenericContainer *container = mono_class_get_generic_container (klass);
2735 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2736 if (mono_error_set_pending_exception (&error))
2738 for (i = 0; i < container->type_argc; ++i) {
2739 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2741 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2742 if (mono_error_set_pending_exception (&error))
2745 mono_array_setref (res, i, rt);
2747 } else if (mono_class_is_ginst (klass)) {
2748 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
2749 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2750 if (mono_error_set_pending_exception (&error))
2752 for (i = 0; i < inst->type_argc; ++i) {
2753 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2754 if (mono_error_set_pending_exception (&error))
2757 mono_array_setref (res, i, rt);
2765 ICALL_EXPORT gboolean
2766 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2770 if (!IS_MONOTYPE (type))
2773 if (type->type->byref)
2776 klass = mono_class_from_mono_type (type->type);
2777 return mono_class_is_gtd (klass);
2780 ICALL_EXPORT MonoReflectionType*
2781 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2784 MonoReflectionType *ret;
2787 if (type->type->byref)
2790 klass = mono_class_from_mono_type (type->type);
2792 if (mono_class_is_gtd (klass)) {
2793 return type; /* check this one */
2795 if (mono_class_is_ginst (klass)) {
2796 MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
2799 tb = mono_class_get_ref_info (generic_class);
2801 if (generic_class->wastypebuilder && tb)
2802 return (MonoReflectionType *)tb;
2804 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2805 mono_error_set_pending_exception (&error);
2813 ICALL_EXPORT MonoReflectionType*
2814 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2817 MonoReflectionType *ret;
2819 MonoType *geninst, **types;
2822 g_assert (IS_MONOTYPE (type));
2823 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2824 if (mono_error_set_pending_exception (&error))
2827 count = mono_array_length (type_array);
2828 types = g_new0 (MonoType *, count);
2830 for (i = 0; i < count; i++) {
2831 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2832 types [i] = t->type;
2835 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2838 mono_error_set_pending_exception (&error);
2842 klass = mono_class_from_mono_type (geninst);
2844 /*we might inflate to the GTD*/
2845 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2846 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2850 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2851 mono_error_set_pending_exception (&error);
2856 ICALL_EXPORT gboolean
2857 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2861 if (!IS_MONOTYPE (type))
2864 if (type->type->byref)
2867 klass = mono_class_from_mono_type (type->type);
2868 return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
2872 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2874 if (!IS_MONOTYPE (type))
2877 if (is_generic_parameter (type->type))
2878 return mono_type_get_generic_param_num (type->type);
2882 ICALL_EXPORT MonoGenericParamInfo *
2883 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2885 return mono_generic_param_info (type->type->data.generic_param);
2888 ICALL_EXPORT MonoBoolean
2889 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2891 return is_generic_parameter (type->type);
2894 ICALL_EXPORT MonoReflectionMethod*
2895 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2896 MonoReflectionMethod* generic)
2903 MonoReflectionMethod *ret = NULL;
2905 domain = ((MonoObject *)type)->vtable->domain;
2907 klass = mono_class_from_mono_type (type->type);
2908 mono_class_init_checked (klass, &error);
2909 if (mono_error_set_pending_exception (&error))
2913 while ((method = mono_class_get_methods (klass, &iter))) {
2914 if (method->token == generic->method->token) {
2915 ret = mono_method_get_object_checked (domain, method, klass, &error);
2916 if (mono_error_set_pending_exception (&error))
2924 ICALL_EXPORT MonoReflectionMethod *
2925 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2928 MonoType *type = ref_type->type;
2930 MonoReflectionMethod *ret = NULL;
2932 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2933 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2936 if (type->type == MONO_TYPE_VAR)
2939 method = mono_type_get_generic_param_owner (type)->owner.method;
2942 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2943 if (!mono_error_ok (&error))
2944 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2948 ICALL_EXPORT MonoBoolean
2949 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2951 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2955 ICALL_EXPORT MonoBoolean
2956 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2958 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2963 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2965 MonoDomain *domain = mono_domain_get ();
2966 MonoImage *image = method->method->klass->image;
2967 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2968 MonoTableInfo *tables = image->tables;
2969 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2970 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2971 guint32 im_cols [MONO_IMPLMAP_SIZE];
2972 guint32 scope_token;
2973 const char *import = NULL;
2974 const char *scope = NULL;
2976 if (image_is_dynamic (image)) {
2977 MonoReflectionMethodAux *method_aux =
2978 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2980 import = method_aux->dllentry;
2981 scope = method_aux->dll;
2984 if (!import || !scope) {
2985 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2990 if (piinfo->implmap_idx) {
2991 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2993 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2994 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2995 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2996 scope = mono_metadata_string_heap (image, scope_token);
3000 *flags = piinfo->piflags;
3001 *entry_point = mono_string_new (domain, import);
3002 *dll_name = mono_string_new (domain, scope);
3005 ICALL_EXPORT MonoReflectionMethod *
3006 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3008 MonoMethodInflated *imethod;
3010 MonoReflectionMethod *ret = NULL;
3013 if (method->method->is_generic)
3016 if (!method->method->is_inflated)
3019 imethod = (MonoMethodInflated *) method->method;
3021 result = imethod->declaring;
3022 /* Not a generic method. */
3023 if (!result->is_generic)
3026 if (image_is_dynamic (method->method->klass->image)) {
3027 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3028 MonoReflectionMethod *res;
3031 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3032 * the dynamic case as well ?
3034 mono_image_lock ((MonoImage*)image);
3035 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3036 mono_image_unlock ((MonoImage*)image);
3042 if (imethod->context.class_inst) {
3043 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3044 /*Generic methods gets the context of the GTD.*/
3045 if (mono_class_get_context (klass)) {
3046 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3047 if (!mono_error_ok (&error))
3052 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3054 if (!mono_error_ok (&error))
3055 mono_error_set_pending_exception (&error);
3059 ICALL_EXPORT gboolean
3060 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3062 return mono_method_signature (method->method)->generic_param_count != 0;
3065 ICALL_EXPORT gboolean
3066 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3068 return method->method->is_generic;
3071 ICALL_EXPORT MonoArray*
3072 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3075 MonoReflectionType *rt;
3080 domain = mono_object_domain (method);
3082 if (method->method->is_inflated) {
3083 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3086 count = inst->type_argc;
3087 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3088 if (mono_error_set_pending_exception (&error))
3091 for (i = 0; i < count; i++) {
3092 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3093 if (mono_error_set_pending_exception (&error))
3096 mono_array_setref (res, i, rt);
3103 count = mono_method_signature (method->method)->generic_param_count;
3104 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3105 if (mono_error_set_pending_exception (&error))
3108 for (i = 0; i < count; i++) {
3109 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3110 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3111 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3113 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3114 if (mono_error_set_pending_exception (&error))
3117 mono_array_setref (res, i, rt);
3123 ICALL_EXPORT MonoObject *
3124 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3128 * Invoke from reflection is supposed to always be a virtual call (the API
3129 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3130 * greater flexibility.
3132 MonoMethod *m = method->method;
3133 MonoMethodSignature *sig = mono_method_signature (m);
3136 void *obj = this_arg;
3140 if (mono_security_core_clr_enabled () &&
3141 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3142 mono_error_set_pending_exception (&error);
3146 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3147 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3148 mono_error_cleanup (&error); /* FIXME does this make sense? */
3149 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3154 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3155 if (!is_ok (&error)) {
3156 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3159 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3160 char *target_name = mono_type_get_full_name (m->klass);
3161 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3162 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3164 g_free (target_name);
3168 m = mono_object_get_virtual_method (this_arg, m);
3169 /* must pass the pointer to the value for valuetype methods */
3170 if (m->klass->valuetype)
3171 obj = mono_object_unbox (this_arg);
3172 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3173 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3178 if (sig->ret->byref) {
3179 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"));
3183 pcount = params? mono_array_length (params): 0;
3184 if (pcount != sig->param_count) {
3185 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3189 if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
3190 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."));
3194 image = m->klass->image;
3195 if (image->assembly->ref_only) {
3196 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."));
3200 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3201 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3205 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3209 intptr_t *lower_bounds;
3210 pcount = mono_array_length (params);
3211 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3212 /* Note: the synthetized array .ctors have int32 as argument type */
3213 for (i = 0; i < pcount; ++i)
3214 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3216 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3217 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3218 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3219 if (!mono_error_ok (&error)) {
3220 mono_error_set_pending_exception (&error);
3224 for (i = 0; i < mono_array_length (arr); ++i) {
3225 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3226 if (!mono_error_ok (&error)) {
3227 mono_error_set_pending_exception (&error);
3230 mono_array_setref_fast (arr, i, subarray);
3232 return (MonoObject*)arr;
3235 if (m->klass->rank == pcount) {
3236 /* Only lengths provided. */
3237 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3238 if (!mono_error_ok (&error)) {
3239 mono_error_set_pending_exception (&error);
3243 return (MonoObject*)arr;
3245 g_assert (pcount == (m->klass->rank * 2));
3246 /* The arguments are lower-bound-length pairs */
3247 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3249 for (i = 0; i < pcount / 2; ++i) {
3250 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3251 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3254 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3255 if (!mono_error_ok (&error)) {
3256 mono_error_set_pending_exception (&error);
3260 return (MonoObject*)arr;
3263 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3264 mono_error_set_pending_exception (&error);
3268 #ifndef DISABLE_REMOTING
3269 ICALL_EXPORT MonoObject *
3270 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3273 MonoDomain *domain = mono_object_domain (method);
3274 MonoMethod *m = method->method;
3275 MonoMethodSignature *sig = mono_method_signature (m);
3276 MonoArray *out_args;
3278 int i, j, outarg_count = 0;
3280 if (m->klass == mono_defaults.object_class) {
3281 if (!strcmp (m->name, "FieldGetter")) {
3282 MonoClass *k = this_arg->vtable->klass;
3286 /* If this is a proxy, then it must be a CBO */
3287 if (k == mono_defaults.transparent_proxy_class) {
3288 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3289 this_arg = tp->rp->unwrapped_server;
3290 g_assert (this_arg);
3291 k = this_arg->vtable->klass;
3294 name = mono_array_get (params, MonoString *, 1);
3295 str = mono_string_to_utf8_checked (name, &error);
3296 if (mono_error_set_pending_exception (&error))
3300 MonoClassField* field = mono_class_get_field_from_name (k, str);
3303 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3304 if (field_klass->valuetype) {
3305 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3306 if (mono_error_set_pending_exception (&error))
3309 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3311 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3312 if (mono_error_set_pending_exception (&error))
3314 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3315 mono_array_setref (out_args, 0, result);
3322 g_assert_not_reached ();
3324 } else if (!strcmp (m->name, "FieldSetter")) {
3325 MonoClass *k = this_arg->vtable->klass;
3331 /* If this is a proxy, then it must be a CBO */
3332 if (k == mono_defaults.transparent_proxy_class) {
3333 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3334 this_arg = tp->rp->unwrapped_server;
3335 g_assert (this_arg);
3336 k = this_arg->vtable->klass;
3339 name = mono_array_get (params, MonoString *, 1);
3340 str = mono_string_to_utf8_checked (name, &error);
3341 if (mono_error_set_pending_exception (&error))
3345 MonoClassField* field = mono_class_get_field_from_name (k, str);
3348 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3349 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3351 if (field_klass->valuetype) {
3352 size = mono_type_size (field->type, &align);
3353 g_assert (size == mono_class_value_size (field_klass, NULL));
3354 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3356 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3359 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3360 if (mono_error_set_pending_exception (&error))
3362 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3371 g_assert_not_reached ();
3376 for (i = 0; i < mono_array_length (params); i++) {
3377 if (sig->params [i]->byref)
3381 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3382 if (mono_error_set_pending_exception (&error))
3385 /* handle constructors only for objects already allocated */
3386 if (!strcmp (method->method->name, ".ctor"))
3387 g_assert (this_arg);
3389 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3390 g_assert (!method->method->klass->valuetype);
3391 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3392 if (mono_error_set_pending_exception (&error))
3395 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3396 if (sig->params [i]->byref) {
3398 arg = mono_array_get (params, gpointer, i);
3399 mono_array_setref (out_args, j, arg);
3404 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3411 read_enum_value (const char *mem, int type)
3414 case MONO_TYPE_BOOLEAN:
3416 return *(guint8*)mem;
3418 return *(gint8*)mem;
3419 case MONO_TYPE_CHAR:
3421 return read16 (mem);
3423 return (gint16) read16 (mem);
3425 return read32 (mem);
3427 return (gint32) read32 (mem);
3430 return read64 (mem);
3432 g_assert_not_reached ();
3438 write_enum_value (char *mem, int type, guint64 value)
3442 case MONO_TYPE_I1: {
3443 guint8 *p = (guint8*)mem;
3449 case MONO_TYPE_CHAR: {
3450 guint16 *p = (guint16 *)mem;
3455 case MONO_TYPE_I4: {
3456 guint32 *p = (guint32 *)mem;
3461 case MONO_TYPE_I8: {
3462 guint64 *p = (guint64 *)mem;
3467 g_assert_not_reached ();
3472 ICALL_EXPORT MonoObject *
3473 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3481 domain = mono_object_domain (enumType);
3482 enumc = mono_class_from_mono_type (enumType->type);
3484 mono_class_init_checked (enumc, &error);
3485 if (mono_error_set_pending_exception (&error))
3488 etype = mono_class_enum_basetype (enumc);
3490 res = mono_object_new_checked (domain, enumc, &error);
3491 if (mono_error_set_pending_exception (&error))
3493 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3498 ICALL_EXPORT MonoBoolean
3499 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3501 int size = mono_class_value_size (a->vtable->klass, NULL);
3502 guint64 a_val = 0, b_val = 0;
3504 memcpy (&a_val, mono_object_unbox (a), size);
3505 memcpy (&b_val, mono_object_unbox (b), size);
3507 return (a_val & b_val) == b_val;
3510 ICALL_EXPORT MonoObject *
3511 ves_icall_System_Enum_get_value (MonoObject *eobj)
3523 g_assert (eobj->vtable->klass->enumtype);
3525 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3526 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3527 if (mono_error_set_pending_exception (&error))
3529 dst = (char *)res + sizeof (MonoObject);
3530 src = (char *)eobj + sizeof (MonoObject);
3531 size = mono_class_value_size (enumc, NULL);
3533 memcpy (dst, src, size);
3538 ICALL_EXPORT MonoReflectionType *
3539 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3542 MonoReflectionType *ret;
3546 klass = mono_class_from_mono_type (type->type);
3547 mono_class_init_checked (klass, &error);
3548 if (mono_error_set_pending_exception (&error))
3551 etype = mono_class_enum_basetype (klass);
3553 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3557 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3558 mono_error_set_pending_exception (&error);
3564 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3566 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3567 gpointer odata = (char *)other + sizeof (MonoObject);
3568 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3569 g_assert (basetype);
3574 if (eobj->vtable->klass != other->vtable->klass)
3577 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3578 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3579 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3582 return me > other ? 1 : -1; \
3585 switch (basetype->type) {
3587 COMPARE_ENUM_VALUES (guint8);
3589 COMPARE_ENUM_VALUES (gint8);
3590 case MONO_TYPE_CHAR:
3592 COMPARE_ENUM_VALUES (guint16);
3594 COMPARE_ENUM_VALUES (gint16);
3596 COMPARE_ENUM_VALUES (guint32);
3598 COMPARE_ENUM_VALUES (gint32);
3600 COMPARE_ENUM_VALUES (guint64);
3602 COMPARE_ENUM_VALUES (gint64);
3606 #undef COMPARE_ENUM_VALUES
3607 /* indicates that the enum was of an unsupported unerlying type */
3612 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3614 gpointer data = (char *)eobj + sizeof (MonoObject);
3615 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3616 g_assert (basetype);
3618 switch (basetype->type) {
3619 case MONO_TYPE_I1: {
3620 gint8 value = *((gint8*)data);
3621 return ((int)value ^ (int)value << 8);
3624 return *((guint8*)data);
3625 case MONO_TYPE_CHAR:
3627 return *((guint16*)data);
3629 case MONO_TYPE_I2: {
3630 gint16 value = *((gint16*)data);
3631 return ((int)(guint16)value | (((int)value) << 16));
3634 return *((guint32*)data);
3636 return *((gint32*)data);
3638 case MONO_TYPE_I8: {
3639 gint64 value = *((gint64*)data);
3640 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3643 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3648 ICALL_EXPORT MonoBoolean
3649 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3652 MonoDomain *domain = mono_object_domain (type);
3653 MonoClass *enumc = mono_class_from_mono_type (type->type);
3654 guint j = 0, nvalues;
3656 MonoClassField *field;
3658 guint64 field_value, previous_value = 0;
3659 gboolean sorted = TRUE;
3661 mono_class_init_checked (enumc, &error);
3662 if (mono_error_set_pending_exception (&error))
3666 if (!enumc->enumtype) {
3667 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3671 base_type = mono_class_enum_basetype (enumc)->type;
3673 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3674 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3675 if (mono_error_set_pending_exception (&error))
3677 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3678 if (mono_error_set_pending_exception (&error))
3682 while ((field = mono_class_get_fields (enumc, &iter))) {
3684 MonoTypeEnum def_type;
3686 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3688 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3690 if (mono_field_is_deleted (field))
3692 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3694 p = mono_class_get_field_default_value (field, &def_type);
3695 /* len = */ mono_metadata_decode_blob_size (p, &p);
3697 field_value = read_enum_value (p, base_type);
3698 mono_array_set (*values, guint64, j, field_value);
3700 if (previous_value > field_value)
3703 previous_value = field_value;
3711 BFLAGS_IgnoreCase = 1,
3712 BFLAGS_DeclaredOnly = 2,
3713 BFLAGS_Instance = 4,
3715 BFLAGS_Public = 0x10,
3716 BFLAGS_NonPublic = 0x20,
3717 BFLAGS_FlattenHierarchy = 0x40,
3718 BFLAGS_InvokeMethod = 0x100,
3719 BFLAGS_CreateInstance = 0x200,
3720 BFLAGS_GetField = 0x400,
3721 BFLAGS_SetField = 0x800,
3722 BFLAGS_GetProperty = 0x1000,
3723 BFLAGS_SetProperty = 0x2000,
3724 BFLAGS_ExactBinding = 0x10000,
3725 BFLAGS_SuppressChangeType = 0x20000,
3726 BFLAGS_OptionalParamBinding = 0x40000
3729 ICALL_EXPORT GPtrArray*
3730 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3733 MonoClass *startklass, *klass;
3736 int (*compare_func) (const char *s1, const char *s2) = NULL;
3737 MonoClassField *field;
3739 if (type->type->byref) {
3740 return g_ptr_array_new ();
3743 mono_error_init (&error);
3745 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3747 klass = startklass = mono_class_from_mono_type (type->type);
3749 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3752 if (mono_class_has_failure (klass)) {
3753 mono_error_set_for_class_failure (&error, klass);
3758 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3759 guint32 flags = mono_field_get_flags (field);
3761 if (mono_field_is_deleted_with_flags (field, flags))
3763 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3764 if (bflags & BFLAGS_Public)
3766 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3767 if (bflags & BFLAGS_NonPublic) {
3774 if (flags & FIELD_ATTRIBUTE_STATIC) {
3775 if (bflags & BFLAGS_Static)
3776 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3779 if (bflags & BFLAGS_Instance)
3786 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3789 g_ptr_array_add (ptr_array, field);
3791 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3797 g_ptr_array_free (ptr_array, TRUE);
3798 mono_error_set_pending_exception (&error);
3803 method_nonpublic (MonoMethod* method, gboolean start_klass)
3805 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3806 case METHOD_ATTRIBUTE_ASSEM:
3807 return (start_klass || mono_defaults.generic_ilist_class);
3808 case METHOD_ATTRIBUTE_PRIVATE:
3810 case METHOD_ATTRIBUTE_PUBLIC:
3818 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3821 MonoClass *startklass;
3825 /*FIXME, use MonoBitSet*/
3826 guint32 method_slots_default [8];
3827 guint32 *method_slots = NULL;
3828 int (*compare_func) (const char *s1, const char *s2) = NULL;
3830 array = g_ptr_array_new ();
3832 mono_error_init (error);
3835 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3837 /* An optimization for calls made from Delegate:CreateDelegate () */
3838 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3839 method = mono_get_delegate_invoke (klass);
3842 g_ptr_array_add (array, method);
3846 mono_class_setup_methods (klass);
3847 mono_class_setup_vtable (klass);
3848 if (mono_class_has_failure (klass))
3851 if (is_generic_parameter (&klass->byval_arg))
3852 nslots = mono_class_get_vtable_size (klass->parent);
3854 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3855 if (nslots >= sizeof (method_slots_default) * 8) {
3856 method_slots = g_new0 (guint32, nslots / 32 + 1);
3858 method_slots = method_slots_default;
3859 memset (method_slots, 0, sizeof (method_slots_default));
3862 mono_class_setup_methods (klass);
3863 mono_class_setup_vtable (klass);
3864 if (mono_class_has_failure (klass))
3868 while ((method = mono_class_get_methods (klass, &iter))) {
3870 if (method->slot != -1) {
3871 g_assert (method->slot < nslots);
3872 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3874 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3875 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3878 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3880 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3881 if (bflags & BFLAGS_Public)
3883 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3889 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3890 if (bflags & BFLAGS_Static)
3891 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3894 if (bflags & BFLAGS_Instance)
3902 if (compare_func (name, method->name))
3907 g_ptr_array_add (array, method);
3909 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3911 if (method_slots != method_slots_default)
3912 g_free (method_slots);
3917 if (method_slots != method_slots_default)
3918 g_free (method_slots);
3919 g_ptr_array_free (array, TRUE);
3921 g_assert (mono_class_has_failure (klass));
3922 mono_error_set_for_class_failure (error, klass);
3926 ICALL_EXPORT GPtrArray*
3927 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3930 GPtrArray *method_array;
3933 klass = mono_class_from_mono_type (type->type);
3934 if (type->type->byref) {
3935 return g_ptr_array_new ();
3938 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3939 mono_error_set_pending_exception (&error);
3940 return method_array;
3943 ICALL_EXPORT GPtrArray*
3944 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3946 MonoClass *startklass, *klass;
3949 gpointer iter = NULL;
3950 GPtrArray *res_array;
3953 if (type->type->byref) {
3954 return g_ptr_array_new ();
3957 klass = startklass = mono_class_from_mono_type (type->type);
3959 mono_class_setup_methods (klass);
3960 if (mono_class_has_failure (klass)) {
3961 mono_error_init (&error);
3962 mono_error_set_for_class_failure (&error, klass);
3963 mono_error_set_pending_exception (&error);
3967 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3970 while ((method = mono_class_get_methods (klass, &iter))) {
3972 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3974 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3975 if (bflags & BFLAGS_Public)
3978 if (bflags & BFLAGS_NonPublic)
3984 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3985 if (bflags & BFLAGS_Static)
3986 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3989 if (bflags & BFLAGS_Instance)
3995 g_ptr_array_add (res_array, method);
4002 property_hash (gconstpointer data)
4004 MonoProperty *prop = (MonoProperty*)data;
4006 return g_str_hash (prop->name);
4010 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4012 if (method1->slot != -1 && method1->slot == method2->slot)
4015 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4016 if (method1->is_inflated)
4017 method1 = ((MonoMethodInflated*) method1)->declaring;
4018 if (method2->is_inflated)
4019 method2 = ((MonoMethodInflated*) method2)->declaring;
4022 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4026 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4028 // Properties are hide-by-name-and-signature
4029 if (!g_str_equal (prop1->name, prop2->name))
4032 /* If we see a property in a generic method, we want to
4033 compare the generic signatures, not the inflated signatures
4034 because we might conflate two properties that were
4038 public T this[T t] { getter { return t; } } // method 1
4039 public U this[U u] { getter { return u; } } // method 2
4042 If we see int Foo<int,int>::Item[int] we need to know if
4043 the indexer came from method 1 or from method 2, and we
4044 shouldn't conflate them. (Bugzilla 36283)
4046 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4049 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4056 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4061 return method_nonpublic (accessor, start_klass);
4064 ICALL_EXPORT GPtrArray*
4065 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4068 MonoClass *startklass, *klass;
4073 int (*compare_func) (const char *s1, const char *s2) = NULL;
4075 GHashTable *properties = NULL;
4076 GPtrArray *res_array;
4078 if (type->type->byref) {
4079 return g_ptr_array_new ();
4082 mono_error_init (&error);
4084 klass = startklass = mono_class_from_mono_type (type->type);
4086 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4088 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4090 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4092 mono_class_setup_methods (klass);
4093 mono_class_setup_vtable (klass);
4094 if (mono_class_has_failure (klass)) {
4095 mono_error_set_for_class_failure (&error, klass);
4100 while ((prop = mono_class_get_properties (klass, &iter))) {
4106 flags = method->flags;
4109 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4110 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4111 if (bflags & BFLAGS_Public)
4113 } else if (bflags & BFLAGS_NonPublic) {
4114 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4115 property_accessor_nonpublic(prop->set, startklass == klass)) {
4122 if (flags & METHOD_ATTRIBUTE_STATIC) {
4123 if (bflags & BFLAGS_Static)
4124 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4127 if (bflags & BFLAGS_Instance)
4135 if (propname != NULL && compare_func (propname, prop->name))
4138 if (g_hash_table_lookup (properties, prop))
4141 g_ptr_array_add (res_array, prop);
4143 g_hash_table_insert (properties, prop, prop);
4145 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4148 g_hash_table_destroy (properties);
4155 g_hash_table_destroy (properties);
4156 g_ptr_array_free (res_array, TRUE);
4158 mono_error_set_pending_exception (&error);
4164 event_hash (gconstpointer data)
4166 MonoEvent *event = (MonoEvent*)data;
4168 return g_str_hash (event->name);
4172 event_equal (MonoEvent *event1, MonoEvent *event2)
4174 // Events are hide-by-name
4175 return g_str_equal (event1->name, event2->name);
4178 ICALL_EXPORT GPtrArray*
4179 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4182 MonoClass *startklass, *klass;
4187 int (*compare_func) (const char *s1, const char *s2) = NULL;
4188 GHashTable *events = NULL;
4189 GPtrArray *res_array;
4191 if (type->type->byref) {
4192 return g_ptr_array_new ();
4195 mono_error_init (&error);
4197 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4199 res_array = g_ptr_array_sized_new (4);
4201 klass = startklass = mono_class_from_mono_type (type->type);
4203 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4205 mono_class_setup_methods (klass);
4206 mono_class_setup_vtable (klass);
4207 if (mono_class_has_failure (klass)) {
4208 mono_error_set_for_class_failure (&error, klass);
4213 while ((event = mono_class_get_events (klass, &iter))) {
4215 method = event->add;
4217 method = event->remove;
4219 method = event->raise;
4221 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4222 if (bflags & BFLAGS_Public)
4224 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4225 if (bflags & BFLAGS_NonPublic)
4230 if (bflags & BFLAGS_NonPublic)
4236 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4237 if (bflags & BFLAGS_Static)
4238 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4241 if (bflags & BFLAGS_Instance)
4246 if (bflags & BFLAGS_Instance)
4251 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4254 if (g_hash_table_lookup (events, event))
4257 g_ptr_array_add (res_array, event);
4259 g_hash_table_insert (events, event, event);
4261 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4264 g_hash_table_destroy (events);
4270 g_hash_table_destroy (events);
4272 g_ptr_array_free (res_array, TRUE);
4274 mono_error_set_pending_exception (&error);
4278 ICALL_EXPORT GPtrArray *
4279 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4285 GPtrArray *res_array;
4287 if (type->type->byref) {
4288 return g_ptr_array_new ();
4291 klass = mono_class_from_mono_type (type->type);
4294 * If a nested type is generic, return its generic type definition.
4295 * Note that this means that the return value is essentially the set
4296 * of nested types of the generic type definition of @klass.
4298 * A note in MSDN claims that a generic type definition can have
4299 * nested types that aren't generic. In any case, the container of that
4300 * nested type would be the generic type definition.
4302 if (mono_class_is_ginst (klass))
4303 klass = mono_class_get_generic_class (klass)->container_class;
4305 res_array = g_ptr_array_new ();
4308 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4310 if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4311 if (bflags & BFLAGS_Public)
4314 if (bflags & BFLAGS_NonPublic)
4320 if (str != NULL && strcmp (nested->name, str))
4323 g_ptr_array_add (res_array, &nested->byval_arg);
4329 ICALL_EXPORT MonoReflectionType*
4330 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4333 MonoReflectionType *ret;
4335 MonoType *type = NULL;
4336 MonoTypeNameParse info;
4337 gboolean type_resolve;
4339 /* On MS.NET, this does not fire a TypeResolve event */
4340 type_resolve = TRUE;
4341 str = mono_string_to_utf8_checked (name, &error);
4342 if (mono_error_set_pending_exception (&error))
4344 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4345 if (!mono_reflection_parse_type (str, &info)) {
4347 mono_reflection_free_type_info (&info);
4349 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4352 /*g_print ("failed parse\n");*/
4356 if (info.assembly.name) {
4358 mono_reflection_free_type_info (&info);
4360 /* 1.0 and 2.0 throw different exceptions */
4361 if (mono_defaults.generic_ilist_class)
4362 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4364 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4370 if (module != NULL) {
4371 if (module->image) {
4372 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4373 if (!is_ok (&error)) {
4375 mono_reflection_free_type_info (&info);
4376 mono_error_set_pending_exception (&error);
4383 if (assembly_is_dynamic (assembly->assembly)) {
4384 /* Enumerate all modules */
4385 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4389 if (abuilder->modules) {
4390 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4391 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4392 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4393 if (!is_ok (&error)) {
4395 mono_reflection_free_type_info (&info);
4396 mono_error_set_pending_exception (&error);
4404 if (!type && abuilder->loaded_modules) {
4405 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4406 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4407 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4408 if (!is_ok (&error)) {
4410 mono_reflection_free_type_info (&info);
4411 mono_error_set_pending_exception (&error);
4420 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4421 if (!is_ok (&error)) {
4423 mono_reflection_free_type_info (&info);
4424 mono_error_set_pending_exception (&error);
4429 mono_reflection_free_type_info (&info);
4431 MonoException *e = NULL;
4434 e = mono_get_exception_type_load (name, NULL);
4437 mono_set_pending_exception (e);
4441 if (type->type == MONO_TYPE_CLASS) {
4442 MonoClass *klass = mono_type_get_class (type);
4444 /* need to report exceptions ? */
4445 if (throwOnError && mono_class_has_failure (klass)) {
4446 /* report SecurityException (or others) that occured when loading the assembly */
4447 mono_error_set_for_class_failure (&error, klass);
4448 mono_error_set_pending_exception (&error);
4453 /* g_print ("got it\n"); */
4454 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4455 mono_error_set_pending_exception (&error);
4461 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4464 gchar *shadow_ini_file;
4467 /* Check for shadow-copied assembly */
4468 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4469 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4471 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4472 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4478 g_free (shadow_ini_file);
4479 if (content != NULL) {
4482 *filename = content;
4489 ICALL_EXPORT MonoString *
4490 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4492 MonoDomain *domain = mono_object_domain (assembly);
4493 MonoAssembly *mass = assembly->assembly;
4494 MonoString *res = NULL;
4499 if (g_path_is_absolute (mass->image->name)) {
4500 absolute = g_strdup (mass->image->name);
4501 dirname = g_path_get_dirname (absolute);
4503 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4504 dirname = g_strdup (mass->basedir);
4507 replace_shadow_path (domain, dirname, &absolute);
4510 mono_icall_make_platform_path (absolute);
4513 uri = g_filename_to_uri (absolute, NULL, NULL);
4515 const gchar *prepend = mono_icall_get_file_path_prefix (absolute);
4516 uri = g_strconcat (prepend, absolute, NULL);
4520 res = mono_string_new (domain, uri);
4527 ICALL_EXPORT MonoBoolean
4528 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4530 MonoAssembly *mass = assembly->assembly;
4532 return mass->in_gac;
4535 ICALL_EXPORT MonoReflectionAssembly*
4536 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4541 MonoImageOpenStatus status;
4542 MonoReflectionAssembly* result = NULL;
4544 name = mono_string_to_utf8_checked (mname, &error);
4545 if (mono_error_set_pending_exception (&error))
4547 res = mono_assembly_load_with_partial_name (name, &status);
4553 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4555 mono_error_set_pending_exception (&error);
4559 ICALL_EXPORT MonoStringHandle
4560 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4562 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4563 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4564 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4567 ICALL_EXPORT MonoBoolean
4568 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4570 return assembly->assembly->ref_only;
4573 ICALL_EXPORT MonoStringHandle
4574 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4576 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4577 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4579 return mono_string_new_handle (domain, assembly->image->version, error);
4582 ICALL_EXPORT MonoReflectionMethod*
4583 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4586 MonoReflectionMethod *res = NULL;
4589 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4593 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4594 if (!mono_error_ok (&error))
4597 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4600 if (!mono_error_ok (&error))
4601 mono_error_set_pending_exception (&error);
4605 ICALL_EXPORT MonoReflectionModule*
4606 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4609 MonoReflectionModule *result = NULL;
4610 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4611 if (!mono_error_ok (&error))
4612 mono_error_set_pending_exception (&error);
4616 ICALL_EXPORT MonoArray*
4617 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4620 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4621 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4622 if (mono_error_set_pending_exception (&error))
4627 for (i = 0; i < table->rows; ++i) {
4628 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4629 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4634 ICALL_EXPORT MonoStringHandle
4635 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4638 guint8 aotid_sum = 0;
4639 MonoDomain* domain = mono_domain_get ();
4641 if (!domain->entry_assembly || !domain->entry_assembly->image)
4644 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4646 for (i = 0; i < 16; ++i)
4647 aotid_sum |= (*aotid)[i];
4652 gchar *guid = mono_guid_to_string((guint8*) aotid);
4653 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4659 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4661 static MonoMethod *create_version = NULL;
4665 mono_error_init (error);
4668 if (!create_version) {
4669 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4670 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4671 g_assert (create_version);
4672 mono_method_desc_free (desc);
4678 args [3] = &revision;
4679 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4680 return_val_if_nok (error, NULL);
4682 mono_runtime_invoke_checked (create_version, result, args, error);
4683 return_val_if_nok (error, NULL);
4688 ICALL_EXPORT MonoArray*
4689 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4693 MonoDomain *domain = mono_object_domain (assembly);
4695 static MonoMethod *create_culture = NULL;
4696 MonoImage *image = assembly->assembly->image;
4700 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4703 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4704 if (mono_error_set_pending_exception (&error))
4708 if (count > 0 && !create_culture) {
4709 MonoMethodDesc *desc = mono_method_desc_new (
4710 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4711 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4712 g_assert (create_culture);
4713 mono_method_desc_free (desc);
4716 for (i = 0; i < count; i++) {
4717 MonoObject *version;
4718 MonoReflectionAssemblyName *aname;
4719 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4721 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4723 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4724 domain, mono_class_get_assembly_name_class (), &error);
4725 if (mono_error_set_pending_exception (&error))
4728 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4730 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4731 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4732 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4733 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4734 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4735 aname->versioncompat = 1; /* SameMachine (default) */
4736 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4738 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4739 if (mono_error_set_pending_exception (&error))
4742 MONO_OBJECT_SETREF (aname, version, version);
4744 if (create_culture) {
4746 MonoBoolean assembly_ref = 1;
4747 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4748 args [1] = &assembly_ref;
4750 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4751 if (mono_error_set_pending_exception (&error))
4754 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4757 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4758 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4759 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4761 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4762 /* public key token isn't copied - the class library will
4763 automatically generate it from the public key if required */
4764 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4765 if (mono_error_set_pending_exception (&error))
4768 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4769 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4771 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4772 if (mono_error_set_pending_exception (&error))
4775 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4776 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4779 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4780 if (mono_error_set_pending_exception (&error))
4783 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4786 /* note: this function doesn't return the codebase on purpose (i.e. it can
4787 be used under partial trust as path information isn't present). */
4789 mono_array_setref (result, i, aname);
4794 /* move this in some file in mono/util/ */
4796 g_concat_dir_and_file (const char *dir, const char *file)
4798 g_return_val_if_fail (dir != NULL, NULL);
4799 g_return_val_if_fail (file != NULL, NULL);
4802 * If the directory name doesn't have a / on the end, we need
4803 * to add one so we get a proper path to the file
4805 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4806 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4808 return g_strconcat (dir, file, NULL);
4812 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4815 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4817 guint32 cols [MONO_MANIFEST_SIZE];
4818 guint32 impl, file_idx;
4822 char *n = mono_string_to_utf8_checked (name, &error);
4823 if (mono_error_set_pending_exception (&error))
4826 for (i = 0; i < table->rows; ++i) {
4827 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4828 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4829 if (strcmp (val, n) == 0)
4833 if (i == table->rows)
4836 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4839 * this code should only be called after obtaining the
4840 * ResourceInfo and handling the other cases.
4842 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4843 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4845 module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
4846 if (mono_error_set_pending_exception (&error) || !module)
4850 module = assembly->assembly->image;
4853 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4854 if (mono_error_set_pending_exception (&error))
4856 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4858 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4861 ICALL_EXPORT gboolean
4862 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4865 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4867 guint32 cols [MONO_MANIFEST_SIZE];
4868 guint32 file_cols [MONO_FILE_SIZE];
4872 n = mono_string_to_utf8_checked (name, &error);
4873 if (mono_error_set_pending_exception (&error))
4875 for (i = 0; i < table->rows; ++i) {
4876 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4877 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4878 if (strcmp (val, n) == 0)
4882 if (i == table->rows)
4885 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4886 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4889 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4890 case MONO_IMPLEMENTATION_FILE:
4891 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4892 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4893 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4894 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4895 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4896 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4899 info->location = RESOURCE_LOCATION_EMBEDDED;
4902 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4903 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4904 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4905 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4906 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4907 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4909 mono_set_pending_exception (ex);
4912 MonoReflectionAssembly *assm_obj;
4913 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4915 mono_error_set_pending_exception (&error);
4918 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4920 /* Obtain info recursively */
4921 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4922 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4925 case MONO_IMPLEMENTATION_EXP_TYPE:
4926 g_assert_not_reached ();
4934 ICALL_EXPORT MonoObject*
4935 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4938 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4939 MonoArray *result = NULL;
4944 /* check hash if needed */
4946 n = mono_string_to_utf8_checked (name, &error);
4947 if (mono_error_set_pending_exception (&error))
4950 for (i = 0; i < table->rows; ++i) {
4951 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4952 if (strcmp (val, n) == 0) {
4955 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4956 fn = mono_string_new (mono_object_domain (assembly), n);
4958 return (MonoObject*)fn;
4966 for (i = 0; i < table->rows; ++i) {
4967 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4971 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4972 if (mono_error_set_pending_exception (&error))
4977 for (i = 0; i < table->rows; ++i) {
4978 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4979 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4980 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4981 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4986 return (MonoObject*)result;
4989 ICALL_EXPORT MonoArray*
4990 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4993 MonoDomain *domain = mono_domain_get();
4996 int i, j, file_count = 0;
4997 MonoImage **modules;
4998 guint32 module_count, real_module_count;
4999 MonoTableInfo *table;
5000 guint32 cols [MONO_FILE_SIZE];
5001 MonoImage *image = assembly->assembly->image;
5003 g_assert (image != NULL);
5004 g_assert (!assembly_is_dynamic (assembly->assembly));
5006 table = &image->tables [MONO_TABLE_FILE];
5007 file_count = table->rows;
5009 modules = image->modules;
5010 module_count = image->module_count;
5012 real_module_count = 0;
5013 for (i = 0; i < module_count; ++i)
5015 real_module_count ++;
5017 klass = mono_class_get_module_class ();
5018 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5019 if (mono_error_set_pending_exception (&error))
5022 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5023 if (mono_error_set_pending_exception (&error))
5026 mono_array_setref (res, 0, image_obj);
5028 for (i = 0; i < module_count; ++i)
5030 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5031 if (mono_error_set_pending_exception (&error))
5033 mono_array_setref (res, j, rm);
5037 for (i = 0; i < file_count; ++i, ++j) {
5038 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5039 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5040 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5041 if (mono_error_set_pending_exception (&error))
5043 mono_array_setref (res, j, rm);
5046 MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
5047 if (mono_error_set_pending_exception (&error))
5050 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5051 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5054 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5055 if (mono_error_set_pending_exception (&error))
5057 mono_array_setref (res, j, rm);
5064 ICALL_EXPORT MonoReflectionMethod*
5065 ves_icall_GetCurrentMethod (void)
5067 MonoReflectionMethod *res = NULL;
5070 MonoMethod *m = mono_method_get_last_managed ();
5073 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5077 while (m->is_inflated)
5078 m = ((MonoMethodInflated*)m)->declaring;
5080 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5081 mono_error_set_pending_exception (&error);
5087 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5090 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5093 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5094 //method is inflated, we should inflate it on the other class
5095 MonoGenericContext ctx;
5096 ctx.method_inst = inflated->context.method_inst;
5097 ctx.class_inst = inflated->context.class_inst;
5098 if (mono_class_is_ginst (klass))
5099 ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
5100 else if (mono_class_is_gtd (klass))
5101 ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
5102 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5103 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5107 mono_class_setup_methods (method->klass);
5108 if (mono_class_has_failure (method->klass))
5110 for (i = 0; i < method->klass->method.count; ++i) {
5111 if (method->klass->methods [i] == method) {
5116 mono_class_setup_methods (klass);
5117 if (mono_class_has_failure (klass))
5119 g_assert (offset >= 0 && offset < klass->method.count);
5120 return klass->methods [offset];
5123 ICALL_EXPORT MonoReflectionMethod*
5124 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5126 MonoReflectionMethod *res = NULL;
5129 if (type && generic_check) {
5130 klass = mono_class_from_mono_type (type);
5131 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5134 if (method->klass != klass) {
5135 method = mono_method_get_equivalent_method (method, klass);
5140 klass = mono_class_from_mono_type (type);
5142 klass = method->klass;
5143 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5144 mono_error_set_pending_exception (&error);
5148 ICALL_EXPORT MonoReflectionMethodBody*
5149 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5152 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5153 mono_error_set_pending_exception (&error);
5157 ICALL_EXPORT MonoReflectionAssembly*
5158 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5161 MonoReflectionAssembly *result;
5162 MonoMethod *dest = NULL;
5164 mono_stack_walk_no_il (get_executing, &dest);
5166 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5168 mono_error_set_pending_exception (&error);
5173 ICALL_EXPORT MonoReflectionAssembly*
5174 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5177 MonoReflectionAssembly *result;
5178 MonoDomain* domain = mono_domain_get ();
5180 if (!domain->entry_assembly)
5183 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5185 mono_error_set_pending_exception (&error);
5189 ICALL_EXPORT MonoReflectionAssembly*
5190 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5195 MonoReflectionAssembly *result;
5198 mono_stack_walk_no_il (get_executing, &dest);
5200 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5204 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5207 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5209 mono_error_set_pending_exception (&error);
5213 ICALL_EXPORT MonoStringHandle
5214 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5215 gboolean assembly_qualified, MonoError *error)
5217 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5218 MonoType *type = MONO_HANDLE_RAW (object)->type;
5219 MonoTypeNameFormat format;
5220 MonoStringHandle res;
5224 format = assembly_qualified ?
5225 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5226 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5228 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5230 name = mono_type_get_name_full (type, format);
5232 return NULL_HANDLE_STRING;
5234 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5236 return NULL_HANDLE_STRING;
5239 res = mono_string_new_handle (domain, name, error);
5246 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5249 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5251 mono_class_init_checked (klass, &error);
5252 mono_error_set_pending_exception (&error);
5253 return mono_security_core_clr_class_level (klass);
5257 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5259 MonoClassField *field = rfield->field;
5260 return mono_security_core_clr_field_level (field, TRUE);
5264 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5266 MonoMethod *method = rfield->method;
5267 return mono_security_core_clr_method_level (method, TRUE);
5271 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)
5273 static MonoMethod *create_culture = NULL;
5277 const char *pkey_ptr;
5279 MonoBoolean assembly_ref = 0;
5281 mono_error_init (error);
5283 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5284 aname->major = name->major;
5285 aname->minor = name->minor;
5286 aname->build = name->build;
5287 aname->flags = name->flags;
5288 aname->revision = name->revision;
5289 aname->hashalg = name->hash_alg;
5290 aname->versioncompat = 1; /* SameMachine (default) */
5291 aname->processor_architecture = name->arch;
5293 if (by_default_version) {
5294 MonoObject *version;
5296 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5297 return_if_nok (error);
5299 MONO_OBJECT_SETREF (aname, version, version);
5303 if (absolute != NULL && *absolute != '\0') {
5306 codebase = g_strdup (absolute);
5308 mono_icall_make_platform_path (codebase);
5310 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5312 result = g_strconcat (prepend, codebase, NULL);
5318 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5322 if (!create_culture) {
5323 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5324 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5325 g_assert (create_culture);
5326 mono_method_desc_free (desc);
5329 if (name->culture) {
5330 args [0] = mono_string_new (domain, name->culture);
5331 args [1] = &assembly_ref;
5333 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5334 return_if_nok (error);
5336 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5339 if (name->public_key) {
5340 pkey_ptr = (char*)name->public_key;
5341 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5343 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5344 return_if_nok (error);
5345 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5346 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5347 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5348 } else if (default_publickey) {
5349 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5350 return_if_nok (error);
5351 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5352 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5355 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5356 if (name->public_key_token [0]) {
5360 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5361 return_if_nok (error);
5363 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5364 p = mono_array_addr (keyToken, char, 0);
5366 for (i = 0, j = 0; i < 8; i++) {
5367 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5368 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5371 } else if (default_token) {
5372 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5373 return_if_nok (error);
5374 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5378 ICALL_EXPORT MonoString *
5379 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5381 MonoDomain *domain = mono_object_domain (assembly);
5382 MonoAssembly *mass = assembly->assembly;
5386 name = mono_stringify_assembly_name (&mass->aname);
5387 res = mono_string_new (domain, name);
5393 ICALL_EXPORT MonoAssemblyName *
5394 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5396 return &mass->aname;
5400 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5404 MonoImageOpenStatus status = MONO_IMAGE_OK;
5407 MonoAssemblyName name;
5410 filename = mono_string_to_utf8_checked (fname, &error);
5411 if (mono_error_set_pending_exception (&error))
5414 dirname = g_path_get_dirname (filename);
5415 replace_shadow_path (mono_domain_get (), dirname, &filename);
5418 image = mono_image_open (filename, &status);
5424 if (status == MONO_IMAGE_IMAGE_INVALID)
5425 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5427 exc = mono_get_exception_file_not_found2 (NULL, fname);
5428 mono_set_pending_exception (exc);
5432 res = mono_assembly_fill_assembly_name (image, &name);
5434 mono_image_close (image);
5436 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5440 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5441 mono_error_set_pending_exception (&error);
5443 mono_image_close (image);
5447 ICALL_EXPORT MonoBoolean
5448 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5449 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5451 MonoBoolean result = FALSE;
5452 MonoDeclSecurityEntry entry;
5454 /* SecurityAction.RequestMinimum */
5455 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5456 *minimum = entry.blob;
5457 *minLength = entry.size;
5460 /* SecurityAction.RequestOptional */
5461 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5462 *optional = entry.blob;
5463 *optLength = entry.size;
5466 /* SecurityAction.RequestRefuse */
5467 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5468 *refused = entry.blob;
5469 *refLength = entry.size;
5477 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5479 guint32 attrs, visibility;
5481 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5482 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5483 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5486 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5492 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5494 MonoReflectionType *rt;
5497 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5500 mono_error_init (error);
5502 /* we start the count from 1 because we skip the special type <Module> */
5505 for (i = 1; i < tdef->rows; ++i) {
5506 if (mono_module_type_is_visible (tdef, image, i + 1))
5510 count = tdef->rows - 1;
5512 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5513 return_val_if_nok (error, NULL);
5514 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5515 return_val_if_nok (error, NULL);
5517 for (i = 1; i < tdef->rows; ++i) {
5518 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5519 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5522 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5523 return_val_if_nok (error, NULL);
5525 mono_array_setref (res, count, rt);
5527 MonoException *ex = mono_error_convert_to_exception (error);
5528 mono_array_setref (*exceptions, count, ex);
5537 ICALL_EXPORT MonoArray*
5538 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5541 MonoArray *res = NULL;
5542 MonoArray *exceptions = NULL;
5543 MonoImage *image = NULL;
5544 MonoTableInfo *table = NULL;
5547 int i, len, ex_count;
5549 domain = mono_object_domain (assembly);
5551 g_assert (!assembly_is_dynamic (assembly->assembly));
5552 image = assembly->assembly->image;
5553 table = &image->tables [MONO_TABLE_FILE];
5554 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5555 if (mono_error_set_pending_exception (&error))
5558 /* Append data from all modules in the assembly */
5559 for (i = 0; i < table->rows; ++i) {
5560 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5561 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5562 if (mono_error_set_pending_exception (&error))
5568 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5569 if (mono_error_set_pending_exception (&error))
5573 /* Append the new types to the end of the array */
5574 if (mono_array_length (res2) > 0) {
5576 MonoArray *res3, *ex3;
5578 len1 = mono_array_length (res);
5579 len2 = mono_array_length (res2);
5581 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5582 if (mono_error_set_pending_exception (&error))
5584 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5585 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5588 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5589 if (mono_error_set_pending_exception (&error))
5591 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5592 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5599 /* the ReflectionTypeLoadException must have all the types (Types property),
5600 * NULL replacing types which throws an exception. The LoaderException must
5601 * contain all exceptions for NULL items.
5604 len = mono_array_length (res);
5607 for (i = 0; i < len; i++) {
5608 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5612 klass = mono_type_get_class (t->type);
5613 if ((klass != NULL) && mono_class_has_failure (klass)) {
5614 /* keep the class in the list */
5615 list = g_list_append (list, klass);
5616 /* and replace Type with NULL */
5617 mono_array_setref (res, i, NULL);
5624 if (list || ex_count) {
5626 MonoException *exc = NULL;
5627 MonoArray *exl = NULL;
5628 int j, length = g_list_length (list) + ex_count;
5630 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5631 if (mono_error_set_pending_exception (&error)) {
5635 /* Types for which mono_class_get_checked () succeeded */
5636 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5637 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5638 mono_array_setref (exl, i, exc);
5640 /* Types for which it don't */
5641 for (j = 0; j < mono_array_length (exceptions); ++j) {
5642 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5644 g_assert (i < length);
5645 mono_array_setref (exl, i, exc);
5652 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5653 if (!is_ok (&error)) {
5654 mono_error_set_pending_exception (&error);
5657 mono_set_pending_exception (exc);
5665 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5667 mono_assembly_name_free (aname);
5670 ICALL_EXPORT gboolean
5671 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5673 *is_version_definited = *is_token_defined = FALSE;
5675 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5678 ICALL_EXPORT MonoReflectionType*
5679 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5682 MonoReflectionType *ret;
5683 MonoDomain *domain = mono_object_domain (module);
5686 g_assert (module->image);
5688 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5689 /* These images do not have a global type */
5692 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5693 if (!mono_error_ok (&error)) {
5694 mono_error_set_pending_exception (&error);
5698 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5699 if (!mono_error_ok (&error)) {
5700 mono_error_set_pending_exception (&error);
5708 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5710 /*if (module->image)
5711 mono_image_close (module->image);*/
5714 ICALL_EXPORT MonoStringHandle
5715 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5717 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5718 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5721 return mono_string_new_handle (domain, image->guid, error);
5725 static inline gpointer
5726 mono_icall_module_get_hinstance (MonoReflectionModule *module)
5728 return (gpointer) (-1);
5730 #endif /* HOST_WIN32 */
5732 ICALL_EXPORT gpointer
5733 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5735 return mono_icall_module_get_hinstance (module);
5739 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5741 if (image_is_dynamic (image)) {
5742 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5743 *pe_kind = dyn->pe_kind;
5744 *machine = dyn->machine;
5747 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5748 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5753 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5755 return (image->md_version_major << 16) | (image->md_version_minor);
5758 ICALL_EXPORT MonoArray*
5759 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5762 MonoArray *exceptions;
5765 if (!module->image) {
5766 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5767 mono_error_set_pending_exception (&error);
5772 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5773 if (mono_error_set_pending_exception (&error))
5776 for (i = 0; i < mono_array_length (exceptions); ++i) {
5777 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5779 mono_set_pending_exception (ex);
5788 mono_memberref_is_method (MonoImage *image, guint32 token)
5790 if (!image_is_dynamic (image)) {
5791 guint32 cols [MONO_MEMBERREF_SIZE];
5793 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5794 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5795 mono_metadata_decode_blob_size (sig, &sig);
5796 return (*sig != 0x6);
5799 MonoClass *handle_class;
5801 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5802 mono_error_cleanup (&error); /* just probing, ignore error */
5806 return mono_defaults.methodhandle_class == handle_class;
5811 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5814 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5815 mono_array_addr (type_args, MonoType*, 0));
5817 context->class_inst = NULL;
5819 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5820 mono_array_addr (method_args, MonoType*, 0));
5822 context->method_inst = NULL;
5825 ICALL_EXPORT MonoType*
5826 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5829 int table = mono_metadata_token_table (token);
5830 int index = mono_metadata_token_index (token);
5831 MonoGenericContext context;
5834 *resolve_error = ResolveTokenError_Other;
5836 /* Validate token */
5837 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5838 (table != MONO_TABLE_TYPESPEC)) {
5839 *resolve_error = ResolveTokenError_BadTable;
5843 if (image_is_dynamic (image)) {
5844 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5845 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5846 mono_error_cleanup (&error);
5847 return klass ? &klass->byval_arg : NULL;
5850 init_generic_context_from_args (&context, type_args, method_args);
5851 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5852 mono_error_cleanup (&error);
5853 return klass ? &klass->byval_arg : NULL;
5856 if ((index <= 0) || (index > image->tables [table].rows)) {
5857 *resolve_error = ResolveTokenError_OutOfRange;
5861 init_generic_context_from_args (&context, type_args, method_args);
5862 klass = mono_class_get_checked (image, token, &error);
5864 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5865 if (!mono_error_ok (&error)) {
5866 mono_error_set_pending_exception (&error);
5871 return &klass->byval_arg;
5876 ICALL_EXPORT MonoMethod*
5877 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5880 int table = mono_metadata_token_table (token);
5881 int index = mono_metadata_token_index (token);
5882 MonoGenericContext context;
5885 *resolve_error = ResolveTokenError_Other;
5887 /* Validate token */
5888 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5889 (table != MONO_TABLE_MEMBERREF)) {
5890 *resolve_error = ResolveTokenError_BadTable;
5894 if (image_is_dynamic (image)) {
5895 if (table == MONO_TABLE_METHOD) {
5896 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5897 mono_error_cleanup (&error);
5901 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5902 *resolve_error = ResolveTokenError_BadTable;
5906 init_generic_context_from_args (&context, type_args, method_args);
5907 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5908 mono_error_cleanup (&error);
5912 if ((index <= 0) || (index > image->tables [table].rows)) {
5913 *resolve_error = ResolveTokenError_OutOfRange;
5916 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5917 *resolve_error = ResolveTokenError_BadTable;
5921 init_generic_context_from_args (&context, type_args, method_args);
5922 method = mono_get_method_checked (image, token, NULL, &context, &error);
5923 mono_error_set_pending_exception (&error);
5928 ICALL_EXPORT MonoString*
5929 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5932 int index = mono_metadata_token_index (token);
5934 *resolve_error = ResolveTokenError_Other;
5936 /* Validate token */
5937 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5938 *resolve_error = ResolveTokenError_BadTable;
5942 if (image_is_dynamic (image)) {
5943 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5944 mono_error_cleanup (&error);
5948 if ((index <= 0) || (index >= image->heap_us.size)) {
5949 *resolve_error = ResolveTokenError_OutOfRange;
5953 /* FIXME: What to do if the index points into the middle of a string ? */
5955 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5956 mono_error_set_pending_exception (&error);
5960 ICALL_EXPORT MonoClassField*
5961 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5965 int table = mono_metadata_token_table (token);
5966 int index = mono_metadata_token_index (token);
5967 MonoGenericContext context;
5968 MonoClassField *field;
5970 *resolve_error = ResolveTokenError_Other;
5972 /* Validate token */
5973 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5974 *resolve_error = ResolveTokenError_BadTable;
5978 if (image_is_dynamic (image)) {
5979 if (table == MONO_TABLE_FIELD) {
5980 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5981 mono_error_cleanup (&error);
5985 if (mono_memberref_is_method (image, token)) {
5986 *resolve_error = ResolveTokenError_BadTable;
5990 init_generic_context_from_args (&context, type_args, method_args);
5991 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5992 mono_error_cleanup (&error);
5996 if ((index <= 0) || (index > image->tables [table].rows)) {
5997 *resolve_error = ResolveTokenError_OutOfRange;
6000 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6001 *resolve_error = ResolveTokenError_BadTable;
6005 init_generic_context_from_args (&context, type_args, method_args);
6006 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6007 mono_error_set_pending_exception (&error);
6013 ICALL_EXPORT MonoObject*
6014 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6018 int table = mono_metadata_token_table (token);
6020 *error = ResolveTokenError_Other;
6023 case MONO_TABLE_TYPEDEF:
6024 case MONO_TABLE_TYPEREF:
6025 case MONO_TABLE_TYPESPEC: {
6026 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6028 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6029 mono_error_set_pending_exception (&merror);
6036 case MONO_TABLE_METHOD:
6037 case MONO_TABLE_METHODSPEC: {
6038 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6040 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6041 mono_error_set_pending_exception (&merror);
6047 case MONO_TABLE_FIELD: {
6048 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6050 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6051 mono_error_set_pending_exception (&merror);
6057 case MONO_TABLE_MEMBERREF:
6058 if (mono_memberref_is_method (image, token)) {
6059 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6061 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6062 mono_error_set_pending_exception (&merror);
6069 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6071 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6072 mono_error_set_pending_exception (&merror);
6081 *error = ResolveTokenError_BadTable;
6087 ICALL_EXPORT MonoArray*
6088 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6091 int table = mono_metadata_token_table (token);
6092 int idx = mono_metadata_token_index (token);
6093 MonoTableInfo *tables = image->tables;
6098 *resolve_error = ResolveTokenError_OutOfRange;
6100 /* FIXME: Support other tables ? */
6101 if (table != MONO_TABLE_STANDALONESIG)
6104 if (image_is_dynamic (image))
6107 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6110 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6112 ptr = mono_metadata_blob_heap (image, sig);
6113 len = mono_metadata_decode_blob_size (ptr, &ptr);
6115 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6116 if (mono_error_set_pending_exception (&error))
6118 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6122 ICALL_EXPORT MonoBoolean
6123 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6129 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6135 check_for_invalid_type (MonoClass *klass, MonoError *error)
6139 mono_error_init (error);
6141 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6144 name = mono_type_get_full_name (klass);
6145 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6147 ICALL_EXPORT MonoReflectionType *
6148 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6151 MonoReflectionType *ret;
6152 MonoClass *klass, *aklass;
6154 klass = mono_class_from_mono_type (type->type);
6155 check_for_invalid_type (klass, &error);
6156 if (mono_error_set_pending_exception (&error))
6159 if (rank == 0) //single dimentional array
6160 aklass = mono_array_class_get (klass, 1);
6162 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6164 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6165 mono_error_set_pending_exception (&error);
6170 ICALL_EXPORT MonoReflectionType *
6171 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6174 MonoReflectionType *ret;
6177 klass = mono_class_from_mono_type (type->type);
6178 mono_class_init_checked (klass, &error);
6179 if (mono_error_set_pending_exception (&error))
6182 check_for_invalid_type (klass, &error);
6183 if (mono_error_set_pending_exception (&error))
6186 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6187 mono_error_set_pending_exception (&error);
6192 ICALL_EXPORT MonoReflectionType *
6193 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6196 MonoReflectionType *ret;
6197 MonoClass *klass, *pklass;
6199 klass = mono_class_from_mono_type (type->type);
6200 mono_class_init_checked (klass, &error);
6201 if (mono_error_set_pending_exception (&error))
6203 check_for_invalid_type (klass, &error);
6204 if (mono_error_set_pending_exception (&error))
6207 pklass = mono_ptr_class_get (type->type);
6209 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6210 mono_error_set_pending_exception (&error);
6215 ICALL_EXPORT MonoObject *
6216 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6217 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6220 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6221 MonoObject *delegate;
6223 MonoMethod *method = info->method;
6224 MonoMethodSignature *sig = mono_method_signature(method);
6226 mono_class_init_checked (delegate_class, &error);
6227 if (mono_error_set_pending_exception (&error))
6230 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6231 /* FIXME improve this exception message */
6232 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6234 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6235 mono_error_set_pending_exception (&error);
6239 if (mono_security_core_clr_enabled ()) {
6240 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6241 if (throwOnBindFailure)
6242 mono_error_set_pending_exception (&error);
6244 mono_error_cleanup (&error);
6249 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6250 if (!method->is_inflated) {
6251 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"));
6256 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6257 if (mono_error_set_pending_exception (&error))
6260 if (method_is_dynamic (method)) {
6261 /* Creating a trampoline would leak memory */
6262 func = mono_compile_method_checked (method, &error);
6263 if (mono_error_set_pending_exception (&error))
6266 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6267 method = mono_object_get_virtual_method (target, method);
6268 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6269 if (mono_error_set_pending_exception (&error))
6271 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6274 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6275 if (mono_error_set_pending_exception (&error))
6280 ICALL_EXPORT MonoMulticastDelegate *
6281 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6284 MonoMulticastDelegate *ret;
6286 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6288 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6289 if (mono_error_set_pending_exception (&error))
6292 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6297 ICALL_EXPORT MonoReflectionMethod*
6298 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6300 MonoReflectionMethod *ret = NULL;
6302 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6303 mono_error_set_pending_exception (&error);
6309 static inline gint32
6310 mono_array_get_byte_length (MonoArray *array)
6316 klass = array->obj.vtable->klass;
6318 if (array->bounds == NULL)
6319 length = array->max_length;
6322 for (i = 0; i < klass->rank; ++ i)
6323 length *= array->bounds [i].length;
6326 switch (klass->element_class->byval_arg.type) {
6329 case MONO_TYPE_BOOLEAN:
6333 case MONO_TYPE_CHAR:
6341 return length * sizeof (gpointer);
6352 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6354 return mono_array_get_byte_length (array);
6358 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6360 return mono_array_get (array, gint8, idx);
6364 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6366 mono_array_set (array, gint8, idx, value);
6369 ICALL_EXPORT MonoBoolean
6370 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6372 guint8 *src_buf, *dest_buf;
6375 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6379 g_assert (count >= 0);
6381 /* This is called directly from the class libraries without going through the managed wrapper */
6382 MONO_CHECK_ARG_NULL (src, FALSE);
6383 MONO_CHECK_ARG_NULL (dest, FALSE);
6385 /* watch out for integer overflow */
6386 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6389 src_buf = (guint8 *)src->vector + src_offset;
6390 dest_buf = (guint8 *)dest->vector + dest_offset;
6393 memcpy (dest_buf, src_buf, count);
6395 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6400 #ifndef DISABLE_REMOTING
6401 ICALL_EXPORT MonoObject *
6402 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6405 MonoDomain *domain = mono_object_domain (this_obj);
6407 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6408 MonoTransparentProxy *tp;
6412 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6413 if (mono_error_set_pending_exception (&error))
6416 tp = (MonoTransparentProxy*) res;
6418 MONO_OBJECT_SETREF (tp, rp, rp);
6419 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6420 klass = mono_class_from_mono_type (type);
6422 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6423 mono_class_setup_vtable (klass);
6424 if (mono_class_has_failure (klass)) {
6425 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6429 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6430 if (mono_error_set_pending_exception (&error))
6432 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6433 if (mono_error_set_pending_exception (&error))
6436 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6437 if (mono_error_set_pending_exception (&error))
6442 ICALL_EXPORT MonoReflectionType *
6443 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6446 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6447 mono_error_set_pending_exception (&error);
6453 /* System.Environment */
6456 ves_icall_System_Environment_get_UserName (void)
6458 /* using glib is more portable */
6459 return mono_string_new (mono_domain_get (), g_get_user_name ());
6464 mono_icall_get_machine_name (void)
6466 #if !defined(DISABLE_SOCKETS)
6470 #if defined _SC_HOST_NAME_MAX
6471 n = sysconf (_SC_HOST_NAME_MAX);
6475 buf = g_malloc (n+1);
6477 if (gethostname (buf, n) == 0){
6479 result = mono_string_new (mono_domain_get (), buf);
6486 return mono_string_new (mono_domain_get (), "mono");
6489 #endif /* !HOST_WIN32 */
6491 ICALL_EXPORT MonoString *
6492 ves_icall_System_Environment_get_MachineName (void)
6494 return mono_icall_get_machine_name ();
6499 mono_icall_get_platform (void)
6501 #if defined(__MACH__)
6504 // Notice that the value is hidden from user code, and only exposed
6505 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6506 // define and making assumptions based on Unix/128/4 values before there
6507 // was a MacOS define. Lots of code would assume that not-Unix meant
6508 // Windows, but in this case, it would be OSX.
6516 #endif /* !HOST_WIN32 */
6519 ves_icall_System_Environment_get_Platform (void)
6521 return mono_icall_get_platform ();
6525 static inline MonoString *
6526 mono_icall_get_new_line (void)
6528 return mono_string_new (mono_domain_get (), "\n");
6530 #endif /* !HOST_WIN32 */
6532 ICALL_EXPORT MonoString *
6533 ves_icall_System_Environment_get_NewLine (void)
6535 return mono_icall_get_new_line ();
6539 static inline MonoBoolean
6540 mono_icall_is_64bit_os (void)
6542 #if SIZEOF_VOID_P == 8
6545 #if defined(HAVE_SYS_UTSNAME_H)
6546 struct utsname name;
6548 if (uname (&name) >= 0) {
6549 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6555 #endif /* !HOST_WIN32 */
6557 ICALL_EXPORT MonoBoolean
6558 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6560 return mono_icall_is_64bit_os ();
6563 ICALL_EXPORT MonoStringHandle
6564 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6568 if (utf8_name == NULL)
6569 return NULL_HANDLE_STRING;
6571 value = g_getenv (utf8_name);
6574 return NULL_HANDLE_STRING;
6576 return mono_string_new_handle (mono_domain_get (), value, error);
6580 * There is no standard way to get at environ.
6583 #ifndef __MINGW32_VERSION
6584 #if defined(__APPLE__)
6585 #if defined (TARGET_OSX)
6586 /* Apple defines this in crt_externs.h but doesn't provide that header for
6587 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6588 * in fact exist on all implementations (so far)
6590 gchar ***_NSGetEnviron(void);
6591 #define environ (*_NSGetEnviron())
6593 static char *mono_environ[1] = { NULL };
6594 #define environ mono_environ
6595 #endif /* defined (TARGET_OSX) */
6603 ICALL_EXPORT MonoArray *
6604 ves_icall_System_Environment_GetCoomandLineArgs (void)
6607 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6608 mono_error_set_pending_exception (&error);
6614 mono_icall_get_environment_variable_names (void)
6624 for (e = environ; *e != 0; ++ e)
6627 domain = mono_domain_get ();
6628 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6629 if (mono_error_set_pending_exception (&error))
6633 for (e = environ; *e != 0; ++ e) {
6634 parts = g_strsplit (*e, "=", 2);
6636 str = mono_string_new (domain, *parts);
6637 mono_array_setref (names, n, str);
6647 #endif /* !HOST_WIN32 */
6649 ICALL_EXPORT MonoArray *
6650 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6652 return mono_icall_get_environment_variable_names ();
6657 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6659 gchar *utf8_name, *utf8_value;
6662 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6663 if (mono_error_set_pending_exception (&error))
6666 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6667 g_unsetenv (utf8_name);
6672 utf8_value = mono_string_to_utf8_checked (value, &error);
6673 if (!mono_error_ok (&error)) {
6675 mono_error_set_pending_exception (&error);
6678 g_setenv (utf8_name, utf8_value, TRUE);
6681 g_free (utf8_value);
6683 #endif /* !HOST_WIN32 */
6686 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6688 mono_icall_set_environment_variable (name, value);
6692 ves_icall_System_Environment_Exit (int result)
6694 mono_environment_exitcode_set (result);
6696 /* FIXME: There are some cleanup hangs that should be worked out, but
6697 * if the program is going to exit, everything will be cleaned up when
6698 * NaCl exits anyway.
6700 #ifndef __native_client__
6701 if (!mono_runtime_try_shutdown ())
6702 mono_thread_exit ();
6704 /* Suspend all managed threads since the runtime is going away */
6705 mono_thread_suspend_all_other_threads ();
6707 mono_runtime_quit ();
6710 /* we may need to do some cleanup here... */
6714 ICALL_EXPORT MonoStringHandle
6715 ves_icall_System_Environment_GetGacPath (MonoError *error)
6717 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6721 static inline MonoString *
6722 mono_icall_get_windows_folder_path (int folder)
6724 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6725 return mono_string_new (mono_domain_get (), "");
6727 #endif /* !HOST_WIN32 */
6729 ICALL_EXPORT MonoString*
6730 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6732 return mono_icall_get_windows_folder_path (folder);
6735 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6737 mono_icall_get_logical_drives (void)
6740 gunichar2 buf [256], *ptr, *dname;
6742 guint initial_size = 127, size = 128;
6745 MonoString *drivestr;
6746 MonoDomain *domain = mono_domain_get ();
6752 while (size > initial_size) {
6753 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6754 if (size > initial_size) {
6757 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6758 initial_size = size;
6772 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6773 if (mono_error_set_pending_exception (&error))
6780 while (*u16) { u16++; len ++; }
6781 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6782 if (mono_error_set_pending_exception (&error))
6785 mono_array_setref (result, ndrives++, drivestr);
6795 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6797 ICALL_EXPORT MonoArray *
6798 ves_icall_System_Environment_GetLogicalDrives (void)
6800 return mono_icall_get_logical_drives ();
6803 ICALL_EXPORT MonoString *
6804 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6807 gunichar2 volume_name [MAX_PATH + 1];
6809 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6811 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6812 mono_error_set_pending_exception (&error);
6816 ICALL_EXPORT MonoStringHandle
6817 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6819 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6822 static const char *encodings [] = {
6824 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6825 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6826 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6828 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6829 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6830 "x_unicode_2_0_utf_7",
6832 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6833 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6835 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6838 "unicodefffe", "utf_16be",
6845 * Returns the internal codepage, if the value of "int_code_page" is
6846 * 1 at entry, and we can not compute a suitable code page number,
6847 * returns the code page as a string
6849 ICALL_EXPORT MonoString*
6850 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6855 char *codepage = NULL;
6857 int want_name = *int_code_page;
6860 *int_code_page = -1;
6862 g_get_charset (&cset);
6863 c = codepage = g_strdup (cset);
6864 for (c = codepage; *c; c++){
6865 if (isascii (*c) && isalpha (*c))
6870 /* g_print ("charset: %s\n", cset); */
6872 /* handle some common aliases */
6875 for (i = 0; p != 0; ){
6878 p = encodings [++i];
6881 if (strcmp (p, codepage) == 0){
6882 *int_code_page = code;
6885 p = encodings [++i];
6888 if (strstr (codepage, "utf_8") != NULL)
6889 *int_code_page |= 0x10000000;
6892 if (want_name && *int_code_page == -1)
6893 return mono_string_new (mono_domain_get (), cset);
6898 ICALL_EXPORT MonoBoolean
6899 ves_icall_System_Environment_get_HasShutdownStarted (void)
6901 if (mono_runtime_is_shutting_down ())
6904 if (mono_domain_is_unloading (mono_domain_get ()))
6912 mono_icall_broadcast_setting_change (void)
6916 #endif /* !HOST_WIN32 */
6919 ves_icall_System_Environment_BroadcastSettingChange (void)
6921 mono_icall_broadcast_setting_change ();
6926 ves_icall_System_Environment_get_TickCount (void)
6928 /* this will overflow after ~24 days */
6929 return (gint32) (mono_msec_boottime () & 0xffffffff);
6933 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6938 #ifndef DISABLE_REMOTING
6939 ICALL_EXPORT MonoBoolean
6940 ves_icall_IsTransparentProxy (MonoObject *proxy)
6945 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6951 ICALL_EXPORT MonoReflectionMethod *
6952 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6953 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6955 MonoReflectionMethod *ret = NULL;
6960 MonoMethod **vtable;
6961 MonoMethod *res = NULL;
6963 MONO_CHECK_ARG_NULL (rtype, NULL);
6964 MONO_CHECK_ARG_NULL (rmethod, NULL);
6966 method = rmethod->method;
6967 klass = mono_class_from_mono_type (rtype->type);
6968 mono_class_init_checked (klass, &error);
6969 if (mono_error_set_pending_exception (&error))
6972 if (MONO_CLASS_IS_INTERFACE (klass))
6975 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6978 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6979 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6985 mono_class_setup_vtable (klass);
6986 vtable = klass->vtable;
6988 if (mono_class_is_interface (method->klass)) {
6989 gboolean variance_used = FALSE;
6990 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6991 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6993 res = vtable [offs + method->slot];
6995 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6998 if (method->slot != -1)
6999 res = vtable [method->slot];
7005 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7006 mono_error_set_pending_exception (&error);
7011 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7017 klass = mono_class_from_mono_type (type->type);
7018 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7019 if (!is_ok (&error)) {
7020 mono_error_set_pending_exception (&error);
7024 mono_vtable_set_is_remote (vtable, enable);
7027 #else /* DISABLE_REMOTING */
7030 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7032 g_assert_not_reached ();
7037 ICALL_EXPORT MonoObject *
7038 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7045 domain = mono_object_domain (type);
7046 klass = mono_class_from_mono_type (type->type);
7047 mono_class_init_checked (klass, &error);
7048 if (mono_error_set_pending_exception (&error))
7051 if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
7052 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7056 if (klass->rank >= 1) {
7057 g_assert (klass->rank == 1);
7058 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7059 mono_error_set_pending_exception (&error);
7062 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7063 if (!is_ok (&error)) {
7064 mono_error_set_pending_exception (&error);
7067 /* Bypass remoting object creation check */
7068 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7069 mono_error_set_pending_exception (&error);
7075 ICALL_EXPORT MonoStringHandle
7076 ves_icall_System_IO_get_temp_path (MonoError *error)
7078 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7081 #ifndef PLATFORM_NO_DRIVEINFO
7082 ICALL_EXPORT MonoBoolean
7083 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7084 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7088 ULARGE_INTEGER wapi_free_bytes_avail;
7089 ULARGE_INTEGER wapi_total_number_of_bytes;
7090 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7092 *error = ERROR_SUCCESS;
7093 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7094 &wapi_total_number_of_free_bytes);
7097 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7098 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7099 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7101 *free_bytes_avail = 0;
7102 *total_number_of_bytes = 0;
7103 *total_number_of_free_bytes = 0;
7104 *error = GetLastError ();
7110 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7111 static inline guint32
7112 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7114 return GetDriveType (mono_string_chars (root_path_name));
7116 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7118 ICALL_EXPORT guint32
7119 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7121 return mono_icall_drive_info_get_drive_type (root_path_name);
7124 #endif /* PLATFORM_NO_DRIVEINFO */
7126 ICALL_EXPORT gpointer
7127 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7130 gpointer result = mono_compile_method_checked (method, &error);
7131 mono_error_set_pending_exception (&error);
7135 ICALL_EXPORT MonoString *
7136 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7141 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7143 mono_icall_make_platform_path (path);
7145 mcpath = mono_string_new (mono_domain_get (), path);
7151 /* this is an icall */
7153 get_bundled_app_config (void)
7156 const gchar *app_config;
7159 gchar *config_file_name, *config_file_path;
7160 gsize len, config_file_path_length, config_ext_length;
7163 domain = mono_domain_get ();
7164 file = domain->setup->configuration_file;
7165 if (!file || file->length == 0)
7168 // Retrieve config file and remove the extension
7169 config_file_name = mono_string_to_utf8_checked (file, &error);
7170 if (mono_error_set_pending_exception (&error))
7172 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7173 if (!config_file_path)
7174 config_file_path = config_file_name;
7176 config_file_path_length = strlen (config_file_path);
7177 config_ext_length = strlen (".config");
7178 if (config_file_path_length <= config_ext_length)
7181 len = config_file_path_length - config_ext_length;
7182 module = (gchar *)g_malloc0 (len + 1);
7183 memcpy (module, config_file_path, len);
7184 // Get the config file from the module name
7185 app_config = mono_config_string_for_assembly_file (module);
7188 if (config_file_name != config_file_path)
7189 g_free (config_file_name);
7190 g_free (config_file_path);
7195 return mono_string_new (mono_domain_get (), app_config);
7198 static MonoStringHandle
7199 get_bundled_machine_config (MonoError *error)
7201 const gchar *machine_config;
7203 machine_config = mono_get_machine_config ();
7205 if (!machine_config)
7206 return NULL_HANDLE_STRING;
7208 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7211 ICALL_EXPORT MonoStringHandle
7212 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7214 return get_bundled_machine_config (error);
7218 ICALL_EXPORT MonoStringHandle
7219 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7221 return get_bundled_machine_config (error);
7224 ICALL_EXPORT MonoStringHandle
7225 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7227 return get_bundled_machine_config (error);
7231 ICALL_EXPORT MonoString *
7232 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7237 path = g_path_get_dirname (mono_get_config_dir ());
7239 mono_icall_make_platform_path (path);
7241 ipath = mono_string_new (mono_domain_get (), path);
7247 ICALL_EXPORT gboolean
7248 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7250 MonoPEResourceDataEntry *entry;
7253 if (!assembly || !result || !size)
7258 image = assembly->assembly->image;
7259 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7263 *result = mono_image_rva_map (image, entry->rde_data_offset);
7268 *size = entry->rde_size;
7273 ICALL_EXPORT MonoBoolean
7274 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7276 return mono_is_debugger_attached ();
7279 ICALL_EXPORT MonoBoolean
7280 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7282 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7283 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7289 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7291 if (mono_get_runtime_callbacks ()->debug_log)
7292 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7297 mono_icall_write_windows_debug_string (MonoString *message)
7299 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7301 #endif /* !HOST_WIN32 */
7304 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7306 mono_icall_write_windows_debug_string (message);
7309 /* Only used for value types */
7310 ICALL_EXPORT MonoObject *
7311 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7318 domain = mono_object_domain (type);
7319 klass = mono_class_from_mono_type (type->type);
7320 mono_class_init_checked (klass, &error);
7321 if (mono_error_set_pending_exception (&error))
7324 if (mono_class_is_nullable (klass))
7325 /* No arguments -> null */
7328 result = mono_object_new_checked (domain, klass, &error);
7329 mono_error_set_pending_exception (&error);
7333 ICALL_EXPORT MonoReflectionMethod *
7334 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7336 MonoReflectionMethod *ret = NULL;
7339 MonoClass *klass, *parent;
7340 MonoGenericContext *generic_inst = NULL;
7341 MonoMethod *method = m->method;
7342 MonoMethod *result = NULL;
7345 if (method->klass == NULL)
7348 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7349 MONO_CLASS_IS_INTERFACE (method->klass) ||
7350 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7353 slot = mono_method_get_vtable_slot (method);
7357 klass = method->klass;
7358 if (mono_class_is_ginst (klass)) {
7359 generic_inst = mono_class_get_context (klass);
7360 klass = mono_class_get_generic_class (klass)->container_class;
7365 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7366 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7367 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7368 or klass is the generic container class and generic_inst is the instantiation.
7370 when we go to the parent, if the parent is an open constructed type, we need to
7371 replace the type parameters by the definitions from the generic_inst, and then take it
7372 apart again into the klass and the generic_inst.
7374 For cases like this:
7375 class C<T> : B<T, int> {
7376 public override void Foo () { ... }
7378 class B<U,V> : A<HashMap<U,V>> {
7379 public override void Foo () { ... }
7382 public virtual void Foo () { ... }
7385 if at each iteration the parent isn't open, we can skip inflating it. if at some
7386 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7389 MonoGenericContext *parent_inst = NULL;
7390 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7391 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7392 if (!mono_error_ok (&error)) {
7393 mono_error_set_pending_exception (&error);
7397 if (mono_class_is_ginst (parent)) {
7398 parent_inst = mono_class_get_context (parent);
7399 parent = mono_class_get_generic_class (parent)->container_class;
7402 mono_class_setup_vtable (parent);
7403 if (parent->vtable_size <= slot)
7406 generic_inst = parent_inst;
7409 klass = klass->parent;
7412 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7413 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7414 if (!mono_error_ok (&error)) {
7415 mono_error_set_pending_exception (&error);
7419 generic_inst = NULL;
7421 if (mono_class_is_ginst (klass)) {
7422 generic_inst = mono_class_get_context (klass);
7423 klass = mono_class_get_generic_class (klass)->container_class;
7429 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7430 if (!mono_error_ok (&error)) {
7431 mono_error_set_pending_exception (&error);
7436 if (klass == method->klass)
7439 /*This is possible if definition == FALSE.
7440 * Do it here to be really sure we don't read invalid memory.
7442 if (slot >= klass->vtable_size)
7445 mono_class_setup_vtable (klass);
7447 result = klass->vtable [slot];
7448 if (result == NULL) {
7449 /* It is an abstract method */
7450 gboolean found = FALSE;
7451 gpointer iter = NULL;
7452 while ((result = mono_class_get_methods (klass, &iter))) {
7453 if (result->slot == slot) {
7458 /* found might be FALSE if we looked in an abstract class
7459 * that doesn't override an abstract method of its
7461 * abstract class Base {
7462 * public abstract void Foo ();
7464 * abstract class Derived : Base { }
7465 * class Child : Derived {
7466 * public override void Foo () { }
7469 * if m was Child.Foo and we ask for the base method,
7470 * then we get here with klass == Derived and found == FALSE
7472 /* but it shouldn't be the case that if we're looking
7473 * for the definition and didn't find a result; the
7474 * loop above should've taken us as far as we could
7476 g_assert (!(definition && !found));
7481 g_assert (result != NULL);
7483 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7484 mono_error_set_pending_exception (&error);
7488 ICALL_EXPORT MonoString*
7489 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7491 MonoMethod *method = m->method;
7493 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7498 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7500 iter->sig = *(MonoMethodSignature**)argsp;
7502 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7503 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7506 /* FIXME: it's not documented what start is exactly... */
7510 iter->args = argsp + sizeof (gpointer);
7512 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7514 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7517 ICALL_EXPORT MonoTypedRef
7518 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7520 guint32 i, arg_size;
7524 i = iter->sig->sentinelpos + iter->next_arg;
7526 g_assert (i < iter->sig->param_count);
7528 res.type = iter->sig->params [i];
7529 res.klass = mono_class_from_mono_type (res.type);
7530 arg_size = mono_type_stack_size (res.type, &align);
7531 #if defined(__arm__) || defined(__mips__)
7532 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7534 res.value = iter->args;
7535 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7536 /* Values are stored as 8 byte register sized objects, but 'value'
7537 * is dereferenced as a pointer in other routines.
7539 res.value = (char*)res.value + 4;
7541 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7542 if (arg_size <= sizeof (gpointer)) {
7544 int padding = arg_size - mono_type_size (res.type, &dummy);
7545 res.value = (guint8*)res.value + padding;
7548 iter->args = (char*)iter->args + arg_size;
7551 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7556 ICALL_EXPORT MonoTypedRef
7557 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7559 guint32 i, arg_size;
7563 i = iter->sig->sentinelpos + iter->next_arg;
7565 g_assert (i < iter->sig->param_count);
7567 while (i < iter->sig->param_count) {
7568 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7570 res.type = iter->sig->params [i];
7571 res.klass = mono_class_from_mono_type (res.type);
7572 /* FIXME: endianess issue... */
7573 arg_size = mono_type_stack_size (res.type, &align);
7574 #if defined(__arm__) || defined(__mips__)
7575 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7577 res.value = iter->args;
7578 iter->args = (char*)iter->args + arg_size;
7580 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7583 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7591 ICALL_EXPORT MonoType*
7592 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7596 i = iter->sig->sentinelpos + iter->next_arg;
7598 g_assert (i < iter->sig->param_count);
7600 return iter->sig->params [i];
7603 ICALL_EXPORT MonoObject*
7604 mono_TypedReference_ToObject (MonoTypedRef* tref)
7607 MonoObject *result = NULL;
7608 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7609 MonoObject** objp = (MonoObject **)tref->value;
7613 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7614 mono_error_set_pending_exception (&error);
7618 ICALL_EXPORT MonoTypedRef
7619 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7622 MonoReflectionField *f;
7624 MonoType *ftype = NULL;
7628 memset (&res, 0, sizeof (res));
7631 g_assert (mono_array_length (fields) > 0);
7633 klass = target->vtable->klass;
7635 for (i = 0; i < mono_array_length (fields); ++i) {
7636 f = mono_array_get (fields, MonoReflectionField*, i);
7638 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7641 if (f->field->parent != klass) {
7642 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7646 p = (guint8*)target + f->field->offset;
7648 p += f->field->offset - sizeof (MonoObject);
7649 klass = mono_class_from_mono_type (f->field->type);
7650 ftype = f->field->type;
7654 res.klass = mono_class_from_mono_type (ftype);
7661 prelink_method (MonoMethod *method, MonoError *error)
7663 const char *exc_class, *exc_arg;
7665 mono_error_init (error);
7666 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7668 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7670 mono_error_set_exception_instance (error,
7671 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7674 /* create the wrapper, too? */
7678 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7682 prelink_method (method->method, &error);
7683 mono_error_set_pending_exception (&error);
7687 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7690 MonoClass *klass = mono_class_from_mono_type (type->type);
7692 gpointer iter = NULL;
7694 mono_class_init_checked (klass, &error);
7695 if (mono_error_set_pending_exception (&error))
7698 while ((m = mono_class_get_methods (klass, &iter))) {
7699 prelink_method (m, &error);
7700 if (mono_error_set_pending_exception (&error))
7705 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7707 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7708 gint32 const **exponents,
7709 gunichar2 const **digitLowerTable,
7710 gunichar2 const **digitUpperTable,
7711 gint64 const **tenPowersList,
7712 gint32 const **decHexDigits)
7714 *mantissas = Formatter_MantissaBitsTable;
7715 *exponents = Formatter_TensExponentTable;
7716 *digitLowerTable = Formatter_DigitLowerTable;
7717 *digitUpperTable = Formatter_DigitUpperTable;
7718 *tenPowersList = Formatter_TenPowersList;
7719 *decHexDigits = Formatter_DecHexDigits;
7723 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7724 * and avoid useless allocations.
7727 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7729 MonoReflectionType *rt;
7733 mono_error_init (error);
7734 for (i = 0; i < type->num_mods; ++i) {
7735 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7740 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7741 return_val_if_nok (error, NULL);
7743 for (i = 0; i < type->num_mods; ++i) {
7744 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7745 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7746 return_val_if_nok (error, NULL);
7748 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7749 return_val_if_nok (error, NULL);
7751 mono_array_setref (res, count, rt);
7758 ICALL_EXPORT MonoArray*
7759 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7762 MonoType *type = param->ClassImpl->type;
7763 MonoClass *member_class = mono_object_class (param->MemberImpl);
7764 MonoMethod *method = NULL;
7767 MonoMethodSignature *sig;
7770 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7771 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7772 method = rmethod->method;
7773 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7774 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7775 if (!(method = prop->property->get))
7776 method = prop->property->set;
7779 char *type_name = mono_type_get_full_name (member_class);
7780 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7781 MonoException *ex = mono_get_exception_not_supported (msg);
7784 mono_set_pending_exception (ex);
7788 image = method->klass->image;
7789 pos = param->PositionImpl;
7790 sig = mono_method_signature (method);
7794 type = sig->params [pos];
7796 res = type_array_from_modifiers (image, type, optional, &error);
7797 mono_error_set_pending_exception (&error);
7802 get_property_type (MonoProperty *prop)
7804 MonoMethodSignature *sig;
7806 sig = mono_method_signature (prop->get);
7808 } else if (prop->set) {
7809 sig = mono_method_signature (prop->set);
7810 return sig->params [sig->param_count - 1];
7815 ICALL_EXPORT MonoArray*
7816 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7819 MonoType *type = get_property_type (property->property);
7820 MonoImage *image = property->klass->image;
7825 res = type_array_from_modifiers (image, type, optional, &error);
7826 mono_error_set_pending_exception (&error);
7831 *Construct a MonoType suited to be used to decode a constant blob object.
7833 * @type is the target type which will be constructed
7834 * @blob_type is the blob type, for example, that comes from the constant table
7835 * @real_type is the expected constructed type.
7838 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7840 type->type = blob_type;
7841 type->data.klass = NULL;
7842 if (blob_type == MONO_TYPE_CLASS)
7843 type->data.klass = mono_defaults.object_class;
7844 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7845 /* For enums, we need to use the base type */
7846 type->type = MONO_TYPE_VALUETYPE;
7847 type->data.klass = mono_class_from_mono_type (real_type);
7849 type->data.klass = mono_class_from_mono_type (real_type);
7852 ICALL_EXPORT MonoObject*
7853 property_info_get_default_value (MonoReflectionProperty *property)
7857 MonoProperty *prop = property->property;
7858 MonoType *type = get_property_type (prop);
7859 MonoDomain *domain = mono_object_domain (property);
7860 MonoTypeEnum def_type;
7861 const char *def_value;
7864 mono_class_init (prop->parent);
7866 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7867 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7871 def_value = mono_class_get_property_default_value (prop, &def_type);
7873 mono_type_from_blob_type (&blob_type, def_type, type);
7874 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7876 mono_error_set_pending_exception (&error);
7880 ICALL_EXPORT MonoBoolean
7881 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7884 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7885 MonoCustomAttrInfo *cinfo;
7888 mono_class_init_checked (attr_class, &error);
7889 if (mono_error_set_pending_exception (&error))
7892 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7893 if (!is_ok (&error)) {
7894 mono_error_set_pending_exception (&error);
7899 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7901 mono_custom_attrs_free (cinfo);
7905 ICALL_EXPORT MonoArray*
7906 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7908 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7913 mono_class_init_checked (attr_class, &error);
7914 if (mono_error_set_pending_exception (&error))
7918 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7919 if (!mono_error_ok (&error)) {
7920 mono_error_set_pending_exception (&error);
7927 ICALL_EXPORT MonoArray*
7928 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7932 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7933 mono_error_set_pending_exception (&error);
7938 ICALL_EXPORT MonoString*
7939 ves_icall_Mono_Runtime_GetDisplayName (void)
7942 MonoString *display_name;
7944 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7945 display_name = mono_string_new (mono_domain_get (), info);
7947 return display_name;
7950 ICALL_EXPORT MonoString*
7951 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7954 MonoString *message;
7958 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7959 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7962 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7964 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7965 if (mono_error_set_pending_exception (&error))
7973 static inline gint32
7974 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
7976 return WAIT_TIMEOUT;
7978 #endif /* !HOST_WIN32 */
7981 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7983 return mono_icall_wait_for_input_idle (handle, milliseconds);
7987 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7989 return mono_process_current_pid ();
7992 ICALL_EXPORT MonoBoolean
7993 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
8005 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
8007 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
8011 ICALL_EXPORT MonoObject*
8012 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
8014 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
8019 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
8021 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
8025 ICALL_EXPORT MonoObject*
8026 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
8028 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
8032 ICALL_EXPORT MonoBoolean
8033 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
8035 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
8040 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
8042 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
8046 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
8048 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
8053 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
8055 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
8059 ICALL_EXPORT mono_unichar2*
8060 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
8062 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
8069 #ifndef DISABLE_ICALL_TABLES
8071 #define ICALL_TYPE(id,name,first)
8072 #define ICALL(id,name,func) Icall_ ## id,
8073 #define HANDLES(inner) inner
8076 #include "metadata/icall-def.h"
8082 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8083 #define ICALL(id,name,func)
8085 #define HANDLES(inner) inner
8087 #include "metadata/icall-def.h"
8093 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8094 #define ICALL(id,name,func)
8096 #define HANDLES(inner) inner
8098 guint16 first_icall;
8101 static const IcallTypeDesc
8102 icall_type_descs [] = {
8103 #include "metadata/icall-def.h"
8107 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8110 #define HANDLES(inner) inner
8112 #define ICALL_TYPE(id,name,first)
8115 #ifdef HAVE_ARRAY_ELEM_INIT
8116 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8117 #define MSGSTRFIELD1(line) str##line
8119 static const struct msgstrtn_t {
8120 #define ICALL(id,name,func)
8122 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8123 #include "metadata/icall-def.h"
8125 } icall_type_names_str = {
8126 #define ICALL_TYPE(id,name,first) (name),
8127 #include "metadata/icall-def.h"
8130 static const guint16 icall_type_names_idx [] = {
8131 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8132 #include "metadata/icall-def.h"
8135 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8137 static const struct msgstr_t {
8139 #define ICALL_TYPE(id,name,first)
8140 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8141 #include "metadata/icall-def.h"
8143 } icall_names_str = {
8144 #define ICALL(id,name,func) (name),
8145 #include "metadata/icall-def.h"
8148 static const guint16 icall_names_idx [] = {
8149 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8150 #include "metadata/icall-def.h"
8153 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8159 #define ICALL_TYPE(id,name,first) name,
8160 #define ICALL(id,name,func)
8161 static const char* const
8162 icall_type_names [] = {
8163 #include "metadata/icall-def.h"
8167 #define icall_type_name_get(id) (icall_type_names [(id)])
8171 #define ICALL_TYPE(id,name,first)
8172 #define ICALL(id,name,func) name,
8173 static const char* const
8175 #include "metadata/icall-def.h"
8178 #define icall_name_get(id) icall_names [(id)]
8180 #endif /* !HAVE_ARRAY_ELEM_INIT */
8183 #define HANDLES(inner) inner
8186 #define ICALL_TYPE(id,name,first)
8187 #define ICALL(id,name,func) func,
8188 static const gconstpointer
8189 icall_functions [] = {
8190 #include "metadata/icall-def.h"
8194 #ifdef ENABLE_ICALL_SYMBOL_MAP
8196 #define HANDLES(inner) inner
8199 #define ICALL_TYPE(id,name,first)
8200 #define ICALL(id,name,func) #func,
8201 static const gconstpointer
8202 icall_symbols [] = {
8203 #include "metadata/icall-def.h"
8210 #define ICALL_TYPE(id,name,first)
8211 #define ICALL(id,name,func) 0,
8213 #define HANDLES(inner) 1,
8215 icall_uses_handles [] = {
8216 #include "metadata/icall-def.h"
8221 #endif /* DISABLE_ICALL_TABLES */
8223 static mono_mutex_t icall_mutex;
8224 static GHashTable *icall_hash = NULL;
8225 static GHashTable *jit_icall_hash_name = NULL;
8226 static GHashTable *jit_icall_hash_addr = NULL;
8229 mono_icall_init (void)
8231 #ifndef DISABLE_ICALL_TABLES
8234 /* check that tables are sorted: disable in release */
8237 const char *prev_class = NULL;
8238 const char *prev_method;
8240 for (i = 0; i < Icall_type_num; ++i) {
8241 const IcallTypeDesc *desc;
8244 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8245 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8246 prev_class = icall_type_name_get (i);
8247 desc = &icall_type_descs [i];
8248 num_icalls = icall_desc_num_icalls (desc);
8249 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8250 for (j = 0; j < num_icalls; ++j) {
8251 const char *methodn = icall_name_get (desc->first_icall + j);
8252 if (prev_method && strcmp (prev_method, methodn) >= 0)
8253 g_print ("method %s should come before method %s\n", methodn, prev_method);
8254 prev_method = methodn;
8260 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8261 mono_os_mutex_init (&icall_mutex);
8265 mono_icall_lock (void)
8267 mono_locks_os_acquire (&icall_mutex, IcallLock);
8271 mono_icall_unlock (void)
8273 mono_locks_os_release (&icall_mutex, IcallLock);
8277 mono_icall_cleanup (void)
8279 g_hash_table_destroy (icall_hash);
8280 g_hash_table_destroy (jit_icall_hash_name);
8281 g_hash_table_destroy (jit_icall_hash_addr);
8282 mono_os_mutex_destroy (&icall_mutex);
8286 * mono_add_internal_call:
8287 * @name: method specification to surface to the managed world
8288 * @method: pointer to a C method to invoke when the method is called
8290 * This method surfaces the C function pointed by @method as a method
8291 * that has been surfaced in managed code with the method specified in
8292 * @name as an internal call.
8294 * Internal calls are surfaced to all app domains loaded and they are
8295 * accessibly by a type with the specified name.
8297 * You must provide a fully qualified type name, that is namespaces
8298 * and type name, followed by a colon and the method name, with an
8299 * optional signature to bind.
8301 * For example, the following are all valid declarations:
8303 * "MyApp.Services.ScriptService:Accelerate"
8304 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8306 * You use method parameters in cases where there might be more than
8307 * one surface method to managed code. That way you can register different
8308 * internal calls for different method overloads.
8310 * The internal calls are invoked with no marshalling. This means that .NET
8311 * types like System.String are exposed as `MonoString *` parameters. This is
8312 * different than the way that strings are surfaced in P/Invoke.
8314 * For more information on how the parameters are marshalled, see the
8315 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8318 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8319 * reference for more information on the format of method descriptions.
8322 mono_add_internal_call (const char *name, gconstpointer method)
8326 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8328 mono_icall_unlock ();
8331 #ifndef DISABLE_ICALL_TABLES
8333 #ifdef HAVE_ARRAY_ELEM_INIT
8335 compare_method_imap (const void *key, const void *elem)
8337 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8338 return strcmp (key, method_name);
8342 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8344 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);
8347 return (nameslot - &icall_names_idx [0]);
8351 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8353 gsize slotnum = find_slot_icall (imap, name);
8356 return (gboolean)icall_uses_handles [slotnum];
8360 find_method_icall (const IcallTypeDesc *imap, const char *name)
8362 gsize slotnum = find_slot_icall (imap, name);
8365 return (gpointer)icall_functions [slotnum];
8369 compare_class_imap (const void *key, const void *elem)
8371 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8372 return strcmp (key, class_name);
8375 static const IcallTypeDesc*
8376 find_class_icalls (const char *name)
8378 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);
8381 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8384 #else /* HAVE_ARRAY_ELEM_INIT */
8387 compare_method_imap (const void *key, const void *elem)
8389 const char** method_name = (const char**)elem;
8390 return strcmp (key, *method_name);
8394 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8396 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8399 return nameslot - icall_names;
8403 find_method_icall (const IcallTypeDesc *imap, const char *name)
8405 gsize slotnum = find_slot_icall (imap, name);
8408 return (gpointer)icall_functions [slotnum];
8412 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8414 gsize slotnum = find_slot_icall (imap, name);
8417 return (gboolean)icall_uses_handles [slotnum];
8421 compare_class_imap (const void *key, const void *elem)
8423 const char** class_name = (const char**)elem;
8424 return strcmp (key, *class_name);
8427 static const IcallTypeDesc*
8428 find_class_icalls (const char *name)
8430 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8433 return &icall_type_descs [nameslot - icall_type_names];
8436 #endif /* HAVE_ARRAY_ELEM_INIT */
8438 #endif /* DISABLE_ICALL_TABLES */
8441 * we should probably export this as an helper (handle nested types).
8442 * Returns the number of chars written in buf.
8445 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8447 int nspacelen, cnamelen;
8448 nspacelen = strlen (klass->name_space);
8449 cnamelen = strlen (klass->name);
8450 if (nspacelen + cnamelen + 2 > bufsize)
8453 memcpy (buf, klass->name_space, nspacelen);
8454 buf [nspacelen ++] = '.';
8456 memcpy (buf + nspacelen, klass->name, cnamelen);
8457 buf [nspacelen + cnamelen] = 0;
8458 return nspacelen + cnamelen;
8461 #ifdef DISABLE_ICALL_TABLES
8463 no_icall_table (void)
8465 g_assert_not_reached ();
8470 * mono_lookup_internal_call_full:
8471 * @method: the method to look up
8472 * @uses_handles: out argument if method needs handles around managed objects.
8474 * Returns a pointer to the icall code for the given method. If
8475 * uses_handles is not NULL, it will be set to TRUE if the method
8476 * needs managed objects wrapped using the infrastructure in handle.h
8478 * If the method is not found, warns and returns NULL.
8481 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8486 int typelen = 0, mlen, siglen;
8488 #ifndef DISABLE_ICALL_TABLES
8489 const IcallTypeDesc *imap = NULL;
8492 g_assert (method != NULL);
8494 if (method->is_inflated)
8495 method = ((MonoMethodInflated *) method)->declaring;
8497 if (method->klass->nested_in) {
8498 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8502 mname [pos++] = '/';
8505 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8511 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8516 #ifndef DISABLE_ICALL_TABLES
8517 imap = find_class_icalls (mname);
8520 mname [typelen] = ':';
8521 mname [typelen + 1] = ':';
8523 mlen = strlen (method->name);
8524 memcpy (mname + typelen + 2, method->name, mlen);
8525 sigstart = mname + typelen + 2 + mlen;
8528 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8529 siglen = strlen (tmpsig);
8530 if (typelen + mlen + siglen + 6 > sizeof (mname))
8533 memcpy (sigstart + 1, tmpsig, siglen);
8534 sigstart [siglen + 1] = ')';
8535 sigstart [siglen + 2] = 0;
8540 res = g_hash_table_lookup (icall_hash, mname);
8543 *uses_handles = FALSE;
8544 mono_icall_unlock ();;
8547 /* try without signature */
8549 res = g_hash_table_lookup (icall_hash, mname);
8552 *uses_handles = FALSE;
8553 mono_icall_unlock ();
8557 #ifdef DISABLE_ICALL_TABLES
8558 mono_icall_unlock ();
8559 /* Fail only when the result is actually used */
8560 /* mono_marshal_get_native_wrapper () depends on this */
8561 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8562 return ves_icall_System_String_ctor_RedirectToCreateString;
8564 return no_icall_table;
8566 /* it wasn't found in the static call tables */
8569 *uses_handles = FALSE;
8570 mono_icall_unlock ();
8573 res = find_method_icall (imap, sigstart - mlen);
8576 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8577 mono_icall_unlock ();
8580 /* try _with_ signature */
8582 res = find_method_icall (imap, sigstart - mlen);
8585 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8586 mono_icall_unlock ();
8590 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8591 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8592 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8593 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8594 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");
8595 g_print ("If you see other errors or faults after this message they are probably related\n");
8596 g_print ("and you need to fix your mono install first.\n");
8598 mono_icall_unlock ();
8605 mono_lookup_internal_call (MonoMethod *method)
8607 return mono_lookup_internal_call_full (method, NULL);
8610 #ifdef ENABLE_ICALL_SYMBOL_MAP
8612 func_cmp (gconstpointer key, gconstpointer p)
8614 return (gsize)key - (gsize)*(gsize*)p;
8619 * mono_lookup_icall_symbol:
8621 * Given the icall METHOD, returns its C symbol.
8624 mono_lookup_icall_symbol (MonoMethod *m)
8626 #ifdef DISABLE_ICALL_TABLES
8627 g_assert_not_reached ();
8630 #ifdef ENABLE_ICALL_SYMBOL_MAP
8634 static gconstpointer *functions_sorted;
8635 static const char**symbols_sorted;
8636 static gboolean inited;
8641 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8642 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8643 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8644 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8645 /* Bubble sort the two arrays */
8649 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8650 if (functions_sorted [i] > functions_sorted [i + 1]) {
8653 tmp = functions_sorted [i];
8654 functions_sorted [i] = functions_sorted [i + 1];
8655 functions_sorted [i + 1] = tmp;
8656 tmp = symbols_sorted [i];
8657 symbols_sorted [i] = symbols_sorted [i + 1];
8658 symbols_sorted [i + 1] = tmp;
8665 func = mono_lookup_internal_call (m);
8668 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8672 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8674 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8675 g_assert_not_reached ();
8682 type_from_typename (char *type_name)
8684 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8686 if (!strcmp (type_name, "int"))
8687 klass = mono_defaults.int_class;
8688 else if (!strcmp (type_name, "ptr"))
8689 klass = mono_defaults.int_class;
8690 else if (!strcmp (type_name, "void"))
8691 klass = mono_defaults.void_class;
8692 else if (!strcmp (type_name, "int32"))
8693 klass = mono_defaults.int32_class;
8694 else if (!strcmp (type_name, "uint32"))
8695 klass = mono_defaults.uint32_class;
8696 else if (!strcmp (type_name, "int8"))
8697 klass = mono_defaults.sbyte_class;
8698 else if (!strcmp (type_name, "uint8"))
8699 klass = mono_defaults.byte_class;
8700 else if (!strcmp (type_name, "int16"))
8701 klass = mono_defaults.int16_class;
8702 else if (!strcmp (type_name, "uint16"))
8703 klass = mono_defaults.uint16_class;
8704 else if (!strcmp (type_name, "long"))
8705 klass = mono_defaults.int64_class;
8706 else if (!strcmp (type_name, "ulong"))
8707 klass = mono_defaults.uint64_class;
8708 else if (!strcmp (type_name, "float"))
8709 klass = mono_defaults.single_class;
8710 else if (!strcmp (type_name, "double"))
8711 klass = mono_defaults.double_class;
8712 else if (!strcmp (type_name, "object"))
8713 klass = mono_defaults.object_class;
8714 else if (!strcmp (type_name, "obj"))
8715 klass = mono_defaults.object_class;
8716 else if (!strcmp (type_name, "string"))
8717 klass = mono_defaults.string_class;
8718 else if (!strcmp (type_name, "bool"))
8719 klass = mono_defaults.boolean_class;
8720 else if (!strcmp (type_name, "boolean"))
8721 klass = mono_defaults.boolean_class;
8723 g_error ("%s", type_name);
8724 g_assert_not_reached ();
8726 return &klass->byval_arg;
8730 * LOCKING: Take the corlib image lock.
8732 MonoMethodSignature*
8733 mono_create_icall_signature (const char *sigstr)
8738 MonoMethodSignature *res, *res2;
8739 MonoImage *corlib = mono_defaults.corlib;
8741 mono_image_lock (corlib);
8742 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8743 mono_image_unlock (corlib);
8748 parts = g_strsplit (sigstr, " ", 256);
8757 res = mono_metadata_signature_alloc (corlib, len - 1);
8762 * Under windows, the default pinvoke calling convention is STDCALL but
8765 res->call_convention = MONO_CALL_C;
8768 res->ret = type_from_typename (parts [0]);
8769 for (i = 1; i < len; ++i) {
8770 res->params [i - 1] = type_from_typename (parts [i]);
8775 mono_image_lock (corlib);
8776 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8778 res = res2; /*Value is allocated in the image pool*/
8780 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8781 mono_image_unlock (corlib);
8787 mono_find_jit_icall_by_name (const char *name)
8789 MonoJitICallInfo *info;
8790 g_assert (jit_icall_hash_name);
8793 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8794 mono_icall_unlock ();
8799 mono_find_jit_icall_by_addr (gconstpointer addr)
8801 MonoJitICallInfo *info;
8802 g_assert (jit_icall_hash_addr);
8805 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8806 mono_icall_unlock ();
8812 * mono_get_jit_icall_info:
8814 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8815 * caller should access it while holding the icall lock.
8818 mono_get_jit_icall_info (void)
8820 return jit_icall_hash_name;
8824 * mono_lookup_jit_icall_symbol:
8826 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8829 mono_lookup_jit_icall_symbol (const char *name)
8831 MonoJitICallInfo *info;
8832 const char *res = NULL;
8835 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8837 res = info->c_symbol;
8838 mono_icall_unlock ();
8843 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8846 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8847 mono_icall_unlock ();
8851 * 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
8852 * icalls without wrappers in some cases.
8855 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8857 MonoJitICallInfo *info;
8864 if (!jit_icall_hash_name) {
8865 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8866 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8869 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8870 g_warning ("jit icall already defined \"%s\"\n", name);
8871 g_assert_not_reached ();
8874 info = g_new0 (MonoJitICallInfo, 1);
8879 info->c_symbol = c_symbol;
8880 info->no_raise = no_raise;
8883 info->wrapper = func;
8885 info->wrapper = NULL;
8888 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8889 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8891 mono_icall_unlock ();
8896 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8898 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);