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 < mono_class_get_field_count (klass));
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 int mcount = mono_class_get_method_count (method->klass);
5111 for (i = 0; i < mcount; ++i) {
5112 if (method->klass->methods [i] == method) {
5117 mono_class_setup_methods (klass);
5118 if (mono_class_has_failure (klass))
5120 g_assert (offset >= 0 && offset < mono_class_get_method_count (klass));
5121 return klass->methods [offset];
5124 ICALL_EXPORT MonoReflectionMethod*
5125 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5127 MonoReflectionMethod *res = NULL;
5130 if (type && generic_check) {
5131 klass = mono_class_from_mono_type (type);
5132 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5135 if (method->klass != klass) {
5136 method = mono_method_get_equivalent_method (method, klass);
5141 klass = mono_class_from_mono_type (type);
5143 klass = method->klass;
5144 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5145 mono_error_set_pending_exception (&error);
5149 ICALL_EXPORT MonoReflectionMethodBody*
5150 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5153 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5154 mono_error_set_pending_exception (&error);
5158 ICALL_EXPORT MonoReflectionAssembly*
5159 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5162 MonoReflectionAssembly *result;
5163 MonoMethod *dest = NULL;
5165 mono_stack_walk_no_il (get_executing, &dest);
5167 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5169 mono_error_set_pending_exception (&error);
5174 ICALL_EXPORT MonoReflectionAssembly*
5175 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5178 MonoReflectionAssembly *result;
5179 MonoDomain* domain = mono_domain_get ();
5181 if (!domain->entry_assembly)
5184 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5186 mono_error_set_pending_exception (&error);
5190 ICALL_EXPORT MonoReflectionAssembly*
5191 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5196 MonoReflectionAssembly *result;
5199 mono_stack_walk_no_il (get_executing, &dest);
5201 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5205 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5208 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5210 mono_error_set_pending_exception (&error);
5214 ICALL_EXPORT MonoStringHandle
5215 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5216 gboolean assembly_qualified, MonoError *error)
5218 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5219 MonoType *type = MONO_HANDLE_RAW (object)->type;
5220 MonoTypeNameFormat format;
5221 MonoStringHandle res;
5225 format = assembly_qualified ?
5226 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5227 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5229 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5231 name = mono_type_get_name_full (type, format);
5233 return NULL_HANDLE_STRING;
5235 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5237 return NULL_HANDLE_STRING;
5240 res = mono_string_new_handle (domain, name, error);
5247 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5250 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5252 mono_class_init_checked (klass, &error);
5253 mono_error_set_pending_exception (&error);
5254 return mono_security_core_clr_class_level (klass);
5258 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5260 MonoClassField *field = rfield->field;
5261 return mono_security_core_clr_field_level (field, TRUE);
5265 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5267 MonoMethod *method = rfield->method;
5268 return mono_security_core_clr_method_level (method, TRUE);
5272 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)
5274 static MonoMethod *create_culture = NULL;
5278 const char *pkey_ptr;
5280 MonoBoolean assembly_ref = 0;
5282 mono_error_init (error);
5284 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5285 aname->major = name->major;
5286 aname->minor = name->minor;
5287 aname->build = name->build;
5288 aname->flags = name->flags;
5289 aname->revision = name->revision;
5290 aname->hashalg = name->hash_alg;
5291 aname->versioncompat = 1; /* SameMachine (default) */
5292 aname->processor_architecture = name->arch;
5294 if (by_default_version) {
5295 MonoObject *version;
5297 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5298 return_if_nok (error);
5300 MONO_OBJECT_SETREF (aname, version, version);
5304 if (absolute != NULL && *absolute != '\0') {
5307 codebase = g_strdup (absolute);
5309 mono_icall_make_platform_path (codebase);
5311 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5313 result = g_strconcat (prepend, codebase, NULL);
5319 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5323 if (!create_culture) {
5324 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5325 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5326 g_assert (create_culture);
5327 mono_method_desc_free (desc);
5330 if (name->culture) {
5331 args [0] = mono_string_new (domain, name->culture);
5332 args [1] = &assembly_ref;
5334 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5335 return_if_nok (error);
5337 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5340 if (name->public_key) {
5341 pkey_ptr = (char*)name->public_key;
5342 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5344 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5345 return_if_nok (error);
5346 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5347 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5348 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5349 } else if (default_publickey) {
5350 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5351 return_if_nok (error);
5352 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5353 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5356 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5357 if (name->public_key_token [0]) {
5361 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5362 return_if_nok (error);
5364 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5365 p = mono_array_addr (keyToken, char, 0);
5367 for (i = 0, j = 0; i < 8; i++) {
5368 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5369 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5372 } else if (default_token) {
5373 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5374 return_if_nok (error);
5375 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5379 ICALL_EXPORT MonoString *
5380 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5382 MonoDomain *domain = mono_object_domain (assembly);
5383 MonoAssembly *mass = assembly->assembly;
5387 name = mono_stringify_assembly_name (&mass->aname);
5388 res = mono_string_new (domain, name);
5394 ICALL_EXPORT MonoAssemblyName *
5395 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5397 return &mass->aname;
5401 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5405 MonoImageOpenStatus status = MONO_IMAGE_OK;
5408 MonoAssemblyName name;
5411 filename = mono_string_to_utf8_checked (fname, &error);
5412 if (mono_error_set_pending_exception (&error))
5415 dirname = g_path_get_dirname (filename);
5416 replace_shadow_path (mono_domain_get (), dirname, &filename);
5419 image = mono_image_open (filename, &status);
5425 if (status == MONO_IMAGE_IMAGE_INVALID)
5426 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5428 exc = mono_get_exception_file_not_found2 (NULL, fname);
5429 mono_set_pending_exception (exc);
5433 res = mono_assembly_fill_assembly_name (image, &name);
5435 mono_image_close (image);
5437 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5441 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5442 mono_error_set_pending_exception (&error);
5444 mono_image_close (image);
5448 ICALL_EXPORT MonoBoolean
5449 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5450 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5452 MonoBoolean result = FALSE;
5453 MonoDeclSecurityEntry entry;
5455 /* SecurityAction.RequestMinimum */
5456 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5457 *minimum = entry.blob;
5458 *minLength = entry.size;
5461 /* SecurityAction.RequestOptional */
5462 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5463 *optional = entry.blob;
5464 *optLength = entry.size;
5467 /* SecurityAction.RequestRefuse */
5468 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5469 *refused = entry.blob;
5470 *refLength = entry.size;
5478 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5480 guint32 attrs, visibility;
5482 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5483 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5484 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5487 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5493 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5495 MonoReflectionType *rt;
5498 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5501 mono_error_init (error);
5503 /* we start the count from 1 because we skip the special type <Module> */
5506 for (i = 1; i < tdef->rows; ++i) {
5507 if (mono_module_type_is_visible (tdef, image, i + 1))
5511 count = tdef->rows - 1;
5513 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5514 return_val_if_nok (error, NULL);
5515 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5516 return_val_if_nok (error, NULL);
5518 for (i = 1; i < tdef->rows; ++i) {
5519 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5520 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5523 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5524 return_val_if_nok (error, NULL);
5526 mono_array_setref (res, count, rt);
5528 MonoException *ex = mono_error_convert_to_exception (error);
5529 mono_array_setref (*exceptions, count, ex);
5538 ICALL_EXPORT MonoArray*
5539 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5542 MonoArray *res = NULL;
5543 MonoArray *exceptions = NULL;
5544 MonoImage *image = NULL;
5545 MonoTableInfo *table = NULL;
5548 int i, len, ex_count;
5550 domain = mono_object_domain (assembly);
5552 g_assert (!assembly_is_dynamic (assembly->assembly));
5553 image = assembly->assembly->image;
5554 table = &image->tables [MONO_TABLE_FILE];
5555 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5556 if (mono_error_set_pending_exception (&error))
5559 /* Append data from all modules in the assembly */
5560 for (i = 0; i < table->rows; ++i) {
5561 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5562 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5563 if (mono_error_set_pending_exception (&error))
5569 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5570 if (mono_error_set_pending_exception (&error))
5574 /* Append the new types to the end of the array */
5575 if (mono_array_length (res2) > 0) {
5577 MonoArray *res3, *ex3;
5579 len1 = mono_array_length (res);
5580 len2 = mono_array_length (res2);
5582 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5583 if (mono_error_set_pending_exception (&error))
5585 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5586 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5589 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5590 if (mono_error_set_pending_exception (&error))
5592 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5593 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5600 /* the ReflectionTypeLoadException must have all the types (Types property),
5601 * NULL replacing types which throws an exception. The LoaderException must
5602 * contain all exceptions for NULL items.
5605 len = mono_array_length (res);
5608 for (i = 0; i < len; i++) {
5609 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5613 klass = mono_type_get_class (t->type);
5614 if ((klass != NULL) && mono_class_has_failure (klass)) {
5615 /* keep the class in the list */
5616 list = g_list_append (list, klass);
5617 /* and replace Type with NULL */
5618 mono_array_setref (res, i, NULL);
5625 if (list || ex_count) {
5627 MonoException *exc = NULL;
5628 MonoArray *exl = NULL;
5629 int j, length = g_list_length (list) + ex_count;
5631 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5632 if (mono_error_set_pending_exception (&error)) {
5636 /* Types for which mono_class_get_checked () succeeded */
5637 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5638 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5639 mono_array_setref (exl, i, exc);
5641 /* Types for which it don't */
5642 for (j = 0; j < mono_array_length (exceptions); ++j) {
5643 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5645 g_assert (i < length);
5646 mono_array_setref (exl, i, exc);
5653 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5654 if (!is_ok (&error)) {
5655 mono_error_set_pending_exception (&error);
5658 mono_set_pending_exception (exc);
5666 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5668 mono_assembly_name_free (aname);
5671 ICALL_EXPORT gboolean
5672 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5674 *is_version_definited = *is_token_defined = FALSE;
5676 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5679 ICALL_EXPORT MonoReflectionType*
5680 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5683 MonoReflectionType *ret;
5684 MonoDomain *domain = mono_object_domain (module);
5687 g_assert (module->image);
5689 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5690 /* These images do not have a global type */
5693 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5694 if (!mono_error_ok (&error)) {
5695 mono_error_set_pending_exception (&error);
5699 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5700 if (!mono_error_ok (&error)) {
5701 mono_error_set_pending_exception (&error);
5709 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5711 /*if (module->image)
5712 mono_image_close (module->image);*/
5715 ICALL_EXPORT MonoStringHandle
5716 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5718 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5719 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5722 return mono_string_new_handle (domain, image->guid, error);
5726 static inline gpointer
5727 mono_icall_module_get_hinstance (MonoReflectionModule *module)
5729 return (gpointer) (-1);
5731 #endif /* HOST_WIN32 */
5733 ICALL_EXPORT gpointer
5734 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5736 return mono_icall_module_get_hinstance (module);
5740 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5742 if (image_is_dynamic (image)) {
5743 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5744 *pe_kind = dyn->pe_kind;
5745 *machine = dyn->machine;
5748 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5749 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5754 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5756 return (image->md_version_major << 16) | (image->md_version_minor);
5759 ICALL_EXPORT MonoArray*
5760 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5763 MonoArray *exceptions;
5766 if (!module->image) {
5767 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5768 mono_error_set_pending_exception (&error);
5773 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5774 if (mono_error_set_pending_exception (&error))
5777 for (i = 0; i < mono_array_length (exceptions); ++i) {
5778 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5780 mono_set_pending_exception (ex);
5789 mono_memberref_is_method (MonoImage *image, guint32 token)
5791 if (!image_is_dynamic (image)) {
5792 guint32 cols [MONO_MEMBERREF_SIZE];
5794 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5795 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5796 mono_metadata_decode_blob_size (sig, &sig);
5797 return (*sig != 0x6);
5800 MonoClass *handle_class;
5802 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5803 mono_error_cleanup (&error); /* just probing, ignore error */
5807 return mono_defaults.methodhandle_class == handle_class;
5812 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5815 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5816 mono_array_addr (type_args, MonoType*, 0));
5818 context->class_inst = NULL;
5820 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5821 mono_array_addr (method_args, MonoType*, 0));
5823 context->method_inst = NULL;
5826 ICALL_EXPORT MonoType*
5827 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5830 int table = mono_metadata_token_table (token);
5831 int index = mono_metadata_token_index (token);
5832 MonoGenericContext context;
5835 *resolve_error = ResolveTokenError_Other;
5837 /* Validate token */
5838 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5839 (table != MONO_TABLE_TYPESPEC)) {
5840 *resolve_error = ResolveTokenError_BadTable;
5844 if (image_is_dynamic (image)) {
5845 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5846 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5847 mono_error_cleanup (&error);
5848 return klass ? &klass->byval_arg : NULL;
5851 init_generic_context_from_args (&context, type_args, method_args);
5852 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5853 mono_error_cleanup (&error);
5854 return klass ? &klass->byval_arg : NULL;
5857 if ((index <= 0) || (index > image->tables [table].rows)) {
5858 *resolve_error = ResolveTokenError_OutOfRange;
5862 init_generic_context_from_args (&context, type_args, method_args);
5863 klass = mono_class_get_checked (image, token, &error);
5865 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5866 if (!mono_error_ok (&error)) {
5867 mono_error_set_pending_exception (&error);
5872 return &klass->byval_arg;
5877 ICALL_EXPORT MonoMethod*
5878 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5881 int table = mono_metadata_token_table (token);
5882 int index = mono_metadata_token_index (token);
5883 MonoGenericContext context;
5886 *resolve_error = ResolveTokenError_Other;
5888 /* Validate token */
5889 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5890 (table != MONO_TABLE_MEMBERREF)) {
5891 *resolve_error = ResolveTokenError_BadTable;
5895 if (image_is_dynamic (image)) {
5896 if (table == MONO_TABLE_METHOD) {
5897 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5898 mono_error_cleanup (&error);
5902 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5903 *resolve_error = ResolveTokenError_BadTable;
5907 init_generic_context_from_args (&context, type_args, method_args);
5908 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5909 mono_error_cleanup (&error);
5913 if ((index <= 0) || (index > image->tables [table].rows)) {
5914 *resolve_error = ResolveTokenError_OutOfRange;
5917 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5918 *resolve_error = ResolveTokenError_BadTable;
5922 init_generic_context_from_args (&context, type_args, method_args);
5923 method = mono_get_method_checked (image, token, NULL, &context, &error);
5924 mono_error_set_pending_exception (&error);
5929 ICALL_EXPORT MonoString*
5930 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5933 int index = mono_metadata_token_index (token);
5935 *resolve_error = ResolveTokenError_Other;
5937 /* Validate token */
5938 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5939 *resolve_error = ResolveTokenError_BadTable;
5943 if (image_is_dynamic (image)) {
5944 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5945 mono_error_cleanup (&error);
5949 if ((index <= 0) || (index >= image->heap_us.size)) {
5950 *resolve_error = ResolveTokenError_OutOfRange;
5954 /* FIXME: What to do if the index points into the middle of a string ? */
5956 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5957 mono_error_set_pending_exception (&error);
5961 ICALL_EXPORT MonoClassField*
5962 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5966 int table = mono_metadata_token_table (token);
5967 int index = mono_metadata_token_index (token);
5968 MonoGenericContext context;
5969 MonoClassField *field;
5971 *resolve_error = ResolveTokenError_Other;
5973 /* Validate token */
5974 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5975 *resolve_error = ResolveTokenError_BadTable;
5979 if (image_is_dynamic (image)) {
5980 if (table == MONO_TABLE_FIELD) {
5981 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5982 mono_error_cleanup (&error);
5986 if (mono_memberref_is_method (image, token)) {
5987 *resolve_error = ResolveTokenError_BadTable;
5991 init_generic_context_from_args (&context, type_args, method_args);
5992 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5993 mono_error_cleanup (&error);
5997 if ((index <= 0) || (index > image->tables [table].rows)) {
5998 *resolve_error = ResolveTokenError_OutOfRange;
6001 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6002 *resolve_error = ResolveTokenError_BadTable;
6006 init_generic_context_from_args (&context, type_args, method_args);
6007 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6008 mono_error_set_pending_exception (&error);
6014 ICALL_EXPORT MonoObject*
6015 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6019 int table = mono_metadata_token_table (token);
6021 *error = ResolveTokenError_Other;
6024 case MONO_TABLE_TYPEDEF:
6025 case MONO_TABLE_TYPEREF:
6026 case MONO_TABLE_TYPESPEC: {
6027 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6029 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6030 mono_error_set_pending_exception (&merror);
6037 case MONO_TABLE_METHOD:
6038 case MONO_TABLE_METHODSPEC: {
6039 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6041 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6042 mono_error_set_pending_exception (&merror);
6048 case MONO_TABLE_FIELD: {
6049 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6051 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6052 mono_error_set_pending_exception (&merror);
6058 case MONO_TABLE_MEMBERREF:
6059 if (mono_memberref_is_method (image, token)) {
6060 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6062 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6063 mono_error_set_pending_exception (&merror);
6070 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6072 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6073 mono_error_set_pending_exception (&merror);
6082 *error = ResolveTokenError_BadTable;
6088 ICALL_EXPORT MonoArray*
6089 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6092 int table = mono_metadata_token_table (token);
6093 int idx = mono_metadata_token_index (token);
6094 MonoTableInfo *tables = image->tables;
6099 *resolve_error = ResolveTokenError_OutOfRange;
6101 /* FIXME: Support other tables ? */
6102 if (table != MONO_TABLE_STANDALONESIG)
6105 if (image_is_dynamic (image))
6108 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6111 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6113 ptr = mono_metadata_blob_heap (image, sig);
6114 len = mono_metadata_decode_blob_size (ptr, &ptr);
6116 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6117 if (mono_error_set_pending_exception (&error))
6119 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6123 ICALL_EXPORT MonoBoolean
6124 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6130 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6136 check_for_invalid_type (MonoClass *klass, MonoError *error)
6140 mono_error_init (error);
6142 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6145 name = mono_type_get_full_name (klass);
6146 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6148 ICALL_EXPORT MonoReflectionType *
6149 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6152 MonoReflectionType *ret;
6153 MonoClass *klass, *aklass;
6155 klass = mono_class_from_mono_type (type->type);
6156 check_for_invalid_type (klass, &error);
6157 if (mono_error_set_pending_exception (&error))
6160 if (rank == 0) //single dimentional array
6161 aklass = mono_array_class_get (klass, 1);
6163 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6165 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6166 mono_error_set_pending_exception (&error);
6171 ICALL_EXPORT MonoReflectionType *
6172 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6175 MonoReflectionType *ret;
6178 klass = mono_class_from_mono_type (type->type);
6179 mono_class_init_checked (klass, &error);
6180 if (mono_error_set_pending_exception (&error))
6183 check_for_invalid_type (klass, &error);
6184 if (mono_error_set_pending_exception (&error))
6187 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6188 mono_error_set_pending_exception (&error);
6193 ICALL_EXPORT MonoReflectionType *
6194 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6197 MonoReflectionType *ret;
6198 MonoClass *klass, *pklass;
6200 klass = mono_class_from_mono_type (type->type);
6201 mono_class_init_checked (klass, &error);
6202 if (mono_error_set_pending_exception (&error))
6204 check_for_invalid_type (klass, &error);
6205 if (mono_error_set_pending_exception (&error))
6208 pklass = mono_ptr_class_get (type->type);
6210 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6211 mono_error_set_pending_exception (&error);
6216 ICALL_EXPORT MonoObject *
6217 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6218 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6221 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6222 MonoObject *delegate;
6224 MonoMethod *method = info->method;
6225 MonoMethodSignature *sig = mono_method_signature(method);
6227 mono_class_init_checked (delegate_class, &error);
6228 if (mono_error_set_pending_exception (&error))
6231 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6232 /* FIXME improve this exception message */
6233 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6235 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6236 mono_error_set_pending_exception (&error);
6240 if (mono_security_core_clr_enabled ()) {
6241 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6242 if (throwOnBindFailure)
6243 mono_error_set_pending_exception (&error);
6245 mono_error_cleanup (&error);
6250 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6251 if (!method->is_inflated) {
6252 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"));
6257 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6258 if (mono_error_set_pending_exception (&error))
6261 if (method_is_dynamic (method)) {
6262 /* Creating a trampoline would leak memory */
6263 func = mono_compile_method_checked (method, &error);
6264 if (mono_error_set_pending_exception (&error))
6267 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6268 method = mono_object_get_virtual_method (target, method);
6269 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6270 if (mono_error_set_pending_exception (&error))
6272 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6275 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6276 if (mono_error_set_pending_exception (&error))
6281 ICALL_EXPORT MonoMulticastDelegate *
6282 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6285 MonoMulticastDelegate *ret;
6287 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6289 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6290 if (mono_error_set_pending_exception (&error))
6293 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6298 ICALL_EXPORT MonoReflectionMethod*
6299 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6301 MonoReflectionMethod *ret = NULL;
6303 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6304 mono_error_set_pending_exception (&error);
6310 static inline gint32
6311 mono_array_get_byte_length (MonoArray *array)
6317 klass = array->obj.vtable->klass;
6319 if (array->bounds == NULL)
6320 length = array->max_length;
6323 for (i = 0; i < klass->rank; ++ i)
6324 length *= array->bounds [i].length;
6327 switch (klass->element_class->byval_arg.type) {
6330 case MONO_TYPE_BOOLEAN:
6334 case MONO_TYPE_CHAR:
6342 return length * sizeof (gpointer);
6353 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6355 return mono_array_get_byte_length (array);
6359 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6361 return mono_array_get (array, gint8, idx);
6365 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6367 mono_array_set (array, gint8, idx, value);
6370 ICALL_EXPORT MonoBoolean
6371 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6373 guint8 *src_buf, *dest_buf;
6376 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6380 g_assert (count >= 0);
6382 /* This is called directly from the class libraries without going through the managed wrapper */
6383 MONO_CHECK_ARG_NULL (src, FALSE);
6384 MONO_CHECK_ARG_NULL (dest, FALSE);
6386 /* watch out for integer overflow */
6387 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6390 src_buf = (guint8 *)src->vector + src_offset;
6391 dest_buf = (guint8 *)dest->vector + dest_offset;
6394 memcpy (dest_buf, src_buf, count);
6396 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6401 #ifndef DISABLE_REMOTING
6402 ICALL_EXPORT MonoObject *
6403 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6406 MonoDomain *domain = mono_object_domain (this_obj);
6408 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6409 MonoTransparentProxy *tp;
6413 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6414 if (mono_error_set_pending_exception (&error))
6417 tp = (MonoTransparentProxy*) res;
6419 MONO_OBJECT_SETREF (tp, rp, rp);
6420 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6421 klass = mono_class_from_mono_type (type);
6423 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6424 mono_class_setup_vtable (klass);
6425 if (mono_class_has_failure (klass)) {
6426 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6430 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6431 if (mono_error_set_pending_exception (&error))
6433 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6434 if (mono_error_set_pending_exception (&error))
6437 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6438 if (mono_error_set_pending_exception (&error))
6443 ICALL_EXPORT MonoReflectionType *
6444 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6447 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6448 mono_error_set_pending_exception (&error);
6454 /* System.Environment */
6457 ves_icall_System_Environment_get_UserName (void)
6459 /* using glib is more portable */
6460 return mono_string_new (mono_domain_get (), g_get_user_name ());
6465 mono_icall_get_machine_name (void)
6467 #if !defined(DISABLE_SOCKETS)
6471 #if defined _SC_HOST_NAME_MAX
6472 n = sysconf (_SC_HOST_NAME_MAX);
6476 buf = g_malloc (n+1);
6478 if (gethostname (buf, n) == 0){
6480 result = mono_string_new (mono_domain_get (), buf);
6487 return mono_string_new (mono_domain_get (), "mono");
6490 #endif /* !HOST_WIN32 */
6492 ICALL_EXPORT MonoString *
6493 ves_icall_System_Environment_get_MachineName (void)
6495 return mono_icall_get_machine_name ();
6500 mono_icall_get_platform (void)
6502 #if defined(__MACH__)
6505 // Notice that the value is hidden from user code, and only exposed
6506 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6507 // define and making assumptions based on Unix/128/4 values before there
6508 // was a MacOS define. Lots of code would assume that not-Unix meant
6509 // Windows, but in this case, it would be OSX.
6517 #endif /* !HOST_WIN32 */
6520 ves_icall_System_Environment_get_Platform (void)
6522 return mono_icall_get_platform ();
6526 static inline MonoString *
6527 mono_icall_get_new_line (void)
6529 return mono_string_new (mono_domain_get (), "\n");
6531 #endif /* !HOST_WIN32 */
6533 ICALL_EXPORT MonoString *
6534 ves_icall_System_Environment_get_NewLine (void)
6536 return mono_icall_get_new_line ();
6540 static inline MonoBoolean
6541 mono_icall_is_64bit_os (void)
6543 #if SIZEOF_VOID_P == 8
6546 #if defined(HAVE_SYS_UTSNAME_H)
6547 struct utsname name;
6549 if (uname (&name) >= 0) {
6550 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6556 #endif /* !HOST_WIN32 */
6558 ICALL_EXPORT MonoBoolean
6559 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6561 return mono_icall_is_64bit_os ();
6564 ICALL_EXPORT MonoStringHandle
6565 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6569 if (utf8_name == NULL)
6570 return NULL_HANDLE_STRING;
6572 value = g_getenv (utf8_name);
6575 return NULL_HANDLE_STRING;
6577 return mono_string_new_handle (mono_domain_get (), value, error);
6581 * There is no standard way to get at environ.
6584 #ifndef __MINGW32_VERSION
6585 #if defined(__APPLE__)
6586 #if defined (TARGET_OSX)
6587 /* Apple defines this in crt_externs.h but doesn't provide that header for
6588 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6589 * in fact exist on all implementations (so far)
6591 gchar ***_NSGetEnviron(void);
6592 #define environ (*_NSGetEnviron())
6594 static char *mono_environ[1] = { NULL };
6595 #define environ mono_environ
6596 #endif /* defined (TARGET_OSX) */
6604 ICALL_EXPORT MonoArray *
6605 ves_icall_System_Environment_GetCoomandLineArgs (void)
6608 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6609 mono_error_set_pending_exception (&error);
6615 mono_icall_get_environment_variable_names (void)
6625 for (e = environ; *e != 0; ++ e)
6628 domain = mono_domain_get ();
6629 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6630 if (mono_error_set_pending_exception (&error))
6634 for (e = environ; *e != 0; ++ e) {
6635 parts = g_strsplit (*e, "=", 2);
6637 str = mono_string_new (domain, *parts);
6638 mono_array_setref (names, n, str);
6648 #endif /* !HOST_WIN32 */
6650 ICALL_EXPORT MonoArray *
6651 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6653 return mono_icall_get_environment_variable_names ();
6658 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6660 gchar *utf8_name, *utf8_value;
6663 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6664 if (mono_error_set_pending_exception (&error))
6667 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6668 g_unsetenv (utf8_name);
6673 utf8_value = mono_string_to_utf8_checked (value, &error);
6674 if (!mono_error_ok (&error)) {
6676 mono_error_set_pending_exception (&error);
6679 g_setenv (utf8_name, utf8_value, TRUE);
6682 g_free (utf8_value);
6684 #endif /* !HOST_WIN32 */
6687 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6689 mono_icall_set_environment_variable (name, value);
6693 ves_icall_System_Environment_Exit (int result)
6695 mono_environment_exitcode_set (result);
6697 /* FIXME: There are some cleanup hangs that should be worked out, but
6698 * if the program is going to exit, everything will be cleaned up when
6699 * NaCl exits anyway.
6701 #ifndef __native_client__
6702 if (!mono_runtime_try_shutdown ())
6703 mono_thread_exit ();
6705 /* Suspend all managed threads since the runtime is going away */
6706 mono_thread_suspend_all_other_threads ();
6708 mono_runtime_quit ();
6711 /* we may need to do some cleanup here... */
6715 ICALL_EXPORT MonoStringHandle
6716 ves_icall_System_Environment_GetGacPath (MonoError *error)
6718 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6722 static inline MonoString *
6723 mono_icall_get_windows_folder_path (int folder)
6725 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6726 return mono_string_new (mono_domain_get (), "");
6728 #endif /* !HOST_WIN32 */
6730 ICALL_EXPORT MonoString*
6731 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6733 return mono_icall_get_windows_folder_path (folder);
6736 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6738 mono_icall_get_logical_drives (void)
6741 gunichar2 buf [256], *ptr, *dname;
6743 guint initial_size = 127, size = 128;
6746 MonoString *drivestr;
6747 MonoDomain *domain = mono_domain_get ();
6753 while (size > initial_size) {
6754 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6755 if (size > initial_size) {
6758 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6759 initial_size = size;
6773 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6774 if (mono_error_set_pending_exception (&error))
6781 while (*u16) { u16++; len ++; }
6782 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6783 if (mono_error_set_pending_exception (&error))
6786 mono_array_setref (result, ndrives++, drivestr);
6796 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6798 ICALL_EXPORT MonoArray *
6799 ves_icall_System_Environment_GetLogicalDrives (void)
6801 return mono_icall_get_logical_drives ();
6804 ICALL_EXPORT MonoString *
6805 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6808 gunichar2 volume_name [MAX_PATH + 1];
6810 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6812 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6813 mono_error_set_pending_exception (&error);
6817 ICALL_EXPORT MonoStringHandle
6818 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6820 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6823 static const char *encodings [] = {
6825 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6826 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6827 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6829 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6830 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6831 "x_unicode_2_0_utf_7",
6833 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6834 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6836 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6839 "unicodefffe", "utf_16be",
6846 * Returns the internal codepage, if the value of "int_code_page" is
6847 * 1 at entry, and we can not compute a suitable code page number,
6848 * returns the code page as a string
6850 ICALL_EXPORT MonoString*
6851 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6856 char *codepage = NULL;
6858 int want_name = *int_code_page;
6861 *int_code_page = -1;
6863 g_get_charset (&cset);
6864 c = codepage = g_strdup (cset);
6865 for (c = codepage; *c; c++){
6866 if (isascii (*c) && isalpha (*c))
6871 /* g_print ("charset: %s\n", cset); */
6873 /* handle some common aliases */
6876 for (i = 0; p != 0; ){
6879 p = encodings [++i];
6882 if (strcmp (p, codepage) == 0){
6883 *int_code_page = code;
6886 p = encodings [++i];
6889 if (strstr (codepage, "utf_8") != NULL)
6890 *int_code_page |= 0x10000000;
6893 if (want_name && *int_code_page == -1)
6894 return mono_string_new (mono_domain_get (), cset);
6899 ICALL_EXPORT MonoBoolean
6900 ves_icall_System_Environment_get_HasShutdownStarted (void)
6902 if (mono_runtime_is_shutting_down ())
6905 if (mono_domain_is_unloading (mono_domain_get ()))
6913 mono_icall_broadcast_setting_change (void)
6917 #endif /* !HOST_WIN32 */
6920 ves_icall_System_Environment_BroadcastSettingChange (void)
6922 mono_icall_broadcast_setting_change ();
6927 ves_icall_System_Environment_get_TickCount (void)
6929 /* this will overflow after ~24 days */
6930 return (gint32) (mono_msec_boottime () & 0xffffffff);
6934 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6939 #ifndef DISABLE_REMOTING
6940 ICALL_EXPORT MonoBoolean
6941 ves_icall_IsTransparentProxy (MonoObject *proxy)
6946 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6952 ICALL_EXPORT MonoReflectionMethod *
6953 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6954 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6956 MonoReflectionMethod *ret = NULL;
6961 MonoMethod **vtable;
6962 MonoMethod *res = NULL;
6964 MONO_CHECK_ARG_NULL (rtype, NULL);
6965 MONO_CHECK_ARG_NULL (rmethod, NULL);
6967 method = rmethod->method;
6968 klass = mono_class_from_mono_type (rtype->type);
6969 mono_class_init_checked (klass, &error);
6970 if (mono_error_set_pending_exception (&error))
6973 if (MONO_CLASS_IS_INTERFACE (klass))
6976 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6979 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6980 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6986 mono_class_setup_vtable (klass);
6987 vtable = klass->vtable;
6989 if (mono_class_is_interface (method->klass)) {
6990 gboolean variance_used = FALSE;
6991 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6992 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6994 res = vtable [offs + method->slot];
6996 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6999 if (method->slot != -1)
7000 res = vtable [method->slot];
7006 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7007 mono_error_set_pending_exception (&error);
7012 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7018 klass = mono_class_from_mono_type (type->type);
7019 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7020 if (!is_ok (&error)) {
7021 mono_error_set_pending_exception (&error);
7025 mono_vtable_set_is_remote (vtable, enable);
7028 #else /* DISABLE_REMOTING */
7031 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7033 g_assert_not_reached ();
7038 ICALL_EXPORT MonoObject *
7039 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7046 domain = mono_object_domain (type);
7047 klass = mono_class_from_mono_type (type->type);
7048 mono_class_init_checked (klass, &error);
7049 if (mono_error_set_pending_exception (&error))
7052 if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
7053 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7057 if (klass->rank >= 1) {
7058 g_assert (klass->rank == 1);
7059 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7060 mono_error_set_pending_exception (&error);
7063 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7064 if (!is_ok (&error)) {
7065 mono_error_set_pending_exception (&error);
7068 /* Bypass remoting object creation check */
7069 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7070 mono_error_set_pending_exception (&error);
7076 ICALL_EXPORT MonoStringHandle
7077 ves_icall_System_IO_get_temp_path (MonoError *error)
7079 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7082 #ifndef PLATFORM_NO_DRIVEINFO
7083 ICALL_EXPORT MonoBoolean
7084 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7085 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7089 ULARGE_INTEGER wapi_free_bytes_avail;
7090 ULARGE_INTEGER wapi_total_number_of_bytes;
7091 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7093 *error = ERROR_SUCCESS;
7094 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7095 &wapi_total_number_of_free_bytes);
7098 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7099 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7100 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7102 *free_bytes_avail = 0;
7103 *total_number_of_bytes = 0;
7104 *total_number_of_free_bytes = 0;
7105 *error = GetLastError ();
7111 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7112 static inline guint32
7113 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7115 return GetDriveType (mono_string_chars (root_path_name));
7117 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7119 ICALL_EXPORT guint32
7120 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7122 return mono_icall_drive_info_get_drive_type (root_path_name);
7125 #endif /* PLATFORM_NO_DRIVEINFO */
7127 ICALL_EXPORT gpointer
7128 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7131 gpointer result = mono_compile_method_checked (method, &error);
7132 mono_error_set_pending_exception (&error);
7136 ICALL_EXPORT MonoString *
7137 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7142 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7144 mono_icall_make_platform_path (path);
7146 mcpath = mono_string_new (mono_domain_get (), path);
7152 /* this is an icall */
7154 get_bundled_app_config (void)
7157 const gchar *app_config;
7160 gchar *config_file_name, *config_file_path;
7161 gsize len, config_file_path_length, config_ext_length;
7164 domain = mono_domain_get ();
7165 file = domain->setup->configuration_file;
7166 if (!file || file->length == 0)
7169 // Retrieve config file and remove the extension
7170 config_file_name = mono_string_to_utf8_checked (file, &error);
7171 if (mono_error_set_pending_exception (&error))
7173 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7174 if (!config_file_path)
7175 config_file_path = config_file_name;
7177 config_file_path_length = strlen (config_file_path);
7178 config_ext_length = strlen (".config");
7179 if (config_file_path_length <= config_ext_length)
7182 len = config_file_path_length - config_ext_length;
7183 module = (gchar *)g_malloc0 (len + 1);
7184 memcpy (module, config_file_path, len);
7185 // Get the config file from the module name
7186 app_config = mono_config_string_for_assembly_file (module);
7189 if (config_file_name != config_file_path)
7190 g_free (config_file_name);
7191 g_free (config_file_path);
7196 return mono_string_new (mono_domain_get (), app_config);
7199 static MonoStringHandle
7200 get_bundled_machine_config (MonoError *error)
7202 const gchar *machine_config;
7204 machine_config = mono_get_machine_config ();
7206 if (!machine_config)
7207 return NULL_HANDLE_STRING;
7209 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7212 ICALL_EXPORT MonoStringHandle
7213 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7215 return get_bundled_machine_config (error);
7219 ICALL_EXPORT MonoStringHandle
7220 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7222 return get_bundled_machine_config (error);
7225 ICALL_EXPORT MonoStringHandle
7226 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7228 return get_bundled_machine_config (error);
7232 ICALL_EXPORT MonoString *
7233 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7238 path = g_path_get_dirname (mono_get_config_dir ());
7240 mono_icall_make_platform_path (path);
7242 ipath = mono_string_new (mono_domain_get (), path);
7248 ICALL_EXPORT gboolean
7249 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7251 MonoPEResourceDataEntry *entry;
7254 if (!assembly || !result || !size)
7259 image = assembly->assembly->image;
7260 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7264 *result = mono_image_rva_map (image, entry->rde_data_offset);
7269 *size = entry->rde_size;
7274 ICALL_EXPORT MonoBoolean
7275 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7277 return mono_is_debugger_attached ();
7280 ICALL_EXPORT MonoBoolean
7281 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7283 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7284 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7290 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7292 if (mono_get_runtime_callbacks ()->debug_log)
7293 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7298 mono_icall_write_windows_debug_string (MonoString *message)
7300 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7302 #endif /* !HOST_WIN32 */
7305 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7307 mono_icall_write_windows_debug_string (message);
7310 /* Only used for value types */
7311 ICALL_EXPORT MonoObject *
7312 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7319 domain = mono_object_domain (type);
7320 klass = mono_class_from_mono_type (type->type);
7321 mono_class_init_checked (klass, &error);
7322 if (mono_error_set_pending_exception (&error))
7325 if (mono_class_is_nullable (klass))
7326 /* No arguments -> null */
7329 result = mono_object_new_checked (domain, klass, &error);
7330 mono_error_set_pending_exception (&error);
7334 ICALL_EXPORT MonoReflectionMethod *
7335 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7337 MonoReflectionMethod *ret = NULL;
7340 MonoClass *klass, *parent;
7341 MonoGenericContext *generic_inst = NULL;
7342 MonoMethod *method = m->method;
7343 MonoMethod *result = NULL;
7346 if (method->klass == NULL)
7349 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7350 MONO_CLASS_IS_INTERFACE (method->klass) ||
7351 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7354 slot = mono_method_get_vtable_slot (method);
7358 klass = method->klass;
7359 if (mono_class_is_ginst (klass)) {
7360 generic_inst = mono_class_get_context (klass);
7361 klass = mono_class_get_generic_class (klass)->container_class;
7366 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7367 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7368 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7369 or klass is the generic container class and generic_inst is the instantiation.
7371 when we go to the parent, if the parent is an open constructed type, we need to
7372 replace the type parameters by the definitions from the generic_inst, and then take it
7373 apart again into the klass and the generic_inst.
7375 For cases like this:
7376 class C<T> : B<T, int> {
7377 public override void Foo () { ... }
7379 class B<U,V> : A<HashMap<U,V>> {
7380 public override void Foo () { ... }
7383 public virtual void Foo () { ... }
7386 if at each iteration the parent isn't open, we can skip inflating it. if at some
7387 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7390 MonoGenericContext *parent_inst = NULL;
7391 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7392 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7393 if (!mono_error_ok (&error)) {
7394 mono_error_set_pending_exception (&error);
7398 if (mono_class_is_ginst (parent)) {
7399 parent_inst = mono_class_get_context (parent);
7400 parent = mono_class_get_generic_class (parent)->container_class;
7403 mono_class_setup_vtable (parent);
7404 if (parent->vtable_size <= slot)
7407 generic_inst = parent_inst;
7410 klass = klass->parent;
7413 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7414 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7415 if (!mono_error_ok (&error)) {
7416 mono_error_set_pending_exception (&error);
7420 generic_inst = NULL;
7422 if (mono_class_is_ginst (klass)) {
7423 generic_inst = mono_class_get_context (klass);
7424 klass = mono_class_get_generic_class (klass)->container_class;
7430 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7431 if (!mono_error_ok (&error)) {
7432 mono_error_set_pending_exception (&error);
7437 if (klass == method->klass)
7440 /*This is possible if definition == FALSE.
7441 * Do it here to be really sure we don't read invalid memory.
7443 if (slot >= klass->vtable_size)
7446 mono_class_setup_vtable (klass);
7448 result = klass->vtable [slot];
7449 if (result == NULL) {
7450 /* It is an abstract method */
7451 gboolean found = FALSE;
7452 gpointer iter = NULL;
7453 while ((result = mono_class_get_methods (klass, &iter))) {
7454 if (result->slot == slot) {
7459 /* found might be FALSE if we looked in an abstract class
7460 * that doesn't override an abstract method of its
7462 * abstract class Base {
7463 * public abstract void Foo ();
7465 * abstract class Derived : Base { }
7466 * class Child : Derived {
7467 * public override void Foo () { }
7470 * if m was Child.Foo and we ask for the base method,
7471 * then we get here with klass == Derived and found == FALSE
7473 /* but it shouldn't be the case that if we're looking
7474 * for the definition and didn't find a result; the
7475 * loop above should've taken us as far as we could
7477 g_assert (!(definition && !found));
7482 g_assert (result != NULL);
7484 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7485 mono_error_set_pending_exception (&error);
7489 ICALL_EXPORT MonoString*
7490 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7492 MonoMethod *method = m->method;
7494 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7499 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7501 iter->sig = *(MonoMethodSignature**)argsp;
7503 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7504 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7507 /* FIXME: it's not documented what start is exactly... */
7511 iter->args = argsp + sizeof (gpointer);
7513 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7515 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7518 ICALL_EXPORT MonoTypedRef
7519 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7521 guint32 i, arg_size;
7525 i = iter->sig->sentinelpos + iter->next_arg;
7527 g_assert (i < iter->sig->param_count);
7529 res.type = iter->sig->params [i];
7530 res.klass = mono_class_from_mono_type (res.type);
7531 arg_size = mono_type_stack_size (res.type, &align);
7532 #if defined(__arm__) || defined(__mips__)
7533 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7535 res.value = iter->args;
7536 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7537 /* Values are stored as 8 byte register sized objects, but 'value'
7538 * is dereferenced as a pointer in other routines.
7540 res.value = (char*)res.value + 4;
7542 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7543 if (arg_size <= sizeof (gpointer)) {
7545 int padding = arg_size - mono_type_size (res.type, &dummy);
7546 res.value = (guint8*)res.value + padding;
7549 iter->args = (char*)iter->args + arg_size;
7552 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7557 ICALL_EXPORT MonoTypedRef
7558 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7560 guint32 i, arg_size;
7564 i = iter->sig->sentinelpos + iter->next_arg;
7566 g_assert (i < iter->sig->param_count);
7568 while (i < iter->sig->param_count) {
7569 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7571 res.type = iter->sig->params [i];
7572 res.klass = mono_class_from_mono_type (res.type);
7573 /* FIXME: endianess issue... */
7574 arg_size = mono_type_stack_size (res.type, &align);
7575 #if defined(__arm__) || defined(__mips__)
7576 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7578 res.value = iter->args;
7579 iter->args = (char*)iter->args + arg_size;
7581 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7584 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7592 ICALL_EXPORT MonoType*
7593 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7597 i = iter->sig->sentinelpos + iter->next_arg;
7599 g_assert (i < iter->sig->param_count);
7601 return iter->sig->params [i];
7604 ICALL_EXPORT MonoObject*
7605 mono_TypedReference_ToObject (MonoTypedRef* tref)
7608 MonoObject *result = NULL;
7609 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7610 MonoObject** objp = (MonoObject **)tref->value;
7614 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7615 mono_error_set_pending_exception (&error);
7619 ICALL_EXPORT MonoTypedRef
7620 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7623 MonoReflectionField *f;
7625 MonoType *ftype = NULL;
7629 memset (&res, 0, sizeof (res));
7632 g_assert (mono_array_length (fields) > 0);
7634 klass = target->vtable->klass;
7636 for (i = 0; i < mono_array_length (fields); ++i) {
7637 f = mono_array_get (fields, MonoReflectionField*, i);
7639 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7642 if (f->field->parent != klass) {
7643 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7647 p = (guint8*)target + f->field->offset;
7649 p += f->field->offset - sizeof (MonoObject);
7650 klass = mono_class_from_mono_type (f->field->type);
7651 ftype = f->field->type;
7655 res.klass = mono_class_from_mono_type (ftype);
7662 prelink_method (MonoMethod *method, MonoError *error)
7664 const char *exc_class, *exc_arg;
7666 mono_error_init (error);
7667 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7669 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7671 mono_error_set_exception_instance (error,
7672 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7675 /* create the wrapper, too? */
7679 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7683 prelink_method (method->method, &error);
7684 mono_error_set_pending_exception (&error);
7688 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7691 MonoClass *klass = mono_class_from_mono_type (type->type);
7693 gpointer iter = NULL;
7695 mono_class_init_checked (klass, &error);
7696 if (mono_error_set_pending_exception (&error))
7699 while ((m = mono_class_get_methods (klass, &iter))) {
7700 prelink_method (m, &error);
7701 if (mono_error_set_pending_exception (&error))
7706 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7708 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7709 gint32 const **exponents,
7710 gunichar2 const **digitLowerTable,
7711 gunichar2 const **digitUpperTable,
7712 gint64 const **tenPowersList,
7713 gint32 const **decHexDigits)
7715 *mantissas = Formatter_MantissaBitsTable;
7716 *exponents = Formatter_TensExponentTable;
7717 *digitLowerTable = Formatter_DigitLowerTable;
7718 *digitUpperTable = Formatter_DigitUpperTable;
7719 *tenPowersList = Formatter_TenPowersList;
7720 *decHexDigits = Formatter_DecHexDigits;
7724 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7725 * and avoid useless allocations.
7728 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7730 MonoReflectionType *rt;
7734 mono_error_init (error);
7735 for (i = 0; i < type->num_mods; ++i) {
7736 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7741 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7742 return_val_if_nok (error, NULL);
7744 for (i = 0; i < type->num_mods; ++i) {
7745 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7746 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7747 return_val_if_nok (error, NULL);
7749 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7750 return_val_if_nok (error, NULL);
7752 mono_array_setref (res, count, rt);
7759 ICALL_EXPORT MonoArray*
7760 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7763 MonoType *type = param->ClassImpl->type;
7764 MonoClass *member_class = mono_object_class (param->MemberImpl);
7765 MonoMethod *method = NULL;
7768 MonoMethodSignature *sig;
7771 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7772 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7773 method = rmethod->method;
7774 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7775 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7776 if (!(method = prop->property->get))
7777 method = prop->property->set;
7780 char *type_name = mono_type_get_full_name (member_class);
7781 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7782 MonoException *ex = mono_get_exception_not_supported (msg);
7785 mono_set_pending_exception (ex);
7789 image = method->klass->image;
7790 pos = param->PositionImpl;
7791 sig = mono_method_signature (method);
7795 type = sig->params [pos];
7797 res = type_array_from_modifiers (image, type, optional, &error);
7798 mono_error_set_pending_exception (&error);
7803 get_property_type (MonoProperty *prop)
7805 MonoMethodSignature *sig;
7807 sig = mono_method_signature (prop->get);
7809 } else if (prop->set) {
7810 sig = mono_method_signature (prop->set);
7811 return sig->params [sig->param_count - 1];
7816 ICALL_EXPORT MonoArray*
7817 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7820 MonoType *type = get_property_type (property->property);
7821 MonoImage *image = property->klass->image;
7826 res = type_array_from_modifiers (image, type, optional, &error);
7827 mono_error_set_pending_exception (&error);
7832 *Construct a MonoType suited to be used to decode a constant blob object.
7834 * @type is the target type which will be constructed
7835 * @blob_type is the blob type, for example, that comes from the constant table
7836 * @real_type is the expected constructed type.
7839 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7841 type->type = blob_type;
7842 type->data.klass = NULL;
7843 if (blob_type == MONO_TYPE_CLASS)
7844 type->data.klass = mono_defaults.object_class;
7845 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7846 /* For enums, we need to use the base type */
7847 type->type = MONO_TYPE_VALUETYPE;
7848 type->data.klass = mono_class_from_mono_type (real_type);
7850 type->data.klass = mono_class_from_mono_type (real_type);
7853 ICALL_EXPORT MonoObject*
7854 property_info_get_default_value (MonoReflectionProperty *property)
7858 MonoProperty *prop = property->property;
7859 MonoType *type = get_property_type (prop);
7860 MonoDomain *domain = mono_object_domain (property);
7861 MonoTypeEnum def_type;
7862 const char *def_value;
7865 mono_class_init (prop->parent);
7867 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7868 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7872 def_value = mono_class_get_property_default_value (prop, &def_type);
7874 mono_type_from_blob_type (&blob_type, def_type, type);
7875 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7877 mono_error_set_pending_exception (&error);
7881 ICALL_EXPORT MonoBoolean
7882 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7885 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7886 MonoCustomAttrInfo *cinfo;
7889 mono_class_init_checked (attr_class, &error);
7890 if (mono_error_set_pending_exception (&error))
7893 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7894 if (!is_ok (&error)) {
7895 mono_error_set_pending_exception (&error);
7900 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7902 mono_custom_attrs_free (cinfo);
7906 ICALL_EXPORT MonoArray*
7907 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7909 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7914 mono_class_init_checked (attr_class, &error);
7915 if (mono_error_set_pending_exception (&error))
7919 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7920 if (!mono_error_ok (&error)) {
7921 mono_error_set_pending_exception (&error);
7928 ICALL_EXPORT MonoArray*
7929 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7933 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7934 mono_error_set_pending_exception (&error);
7939 ICALL_EXPORT MonoString*
7940 ves_icall_Mono_Runtime_GetDisplayName (void)
7943 MonoString *display_name;
7945 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7946 display_name = mono_string_new (mono_domain_get (), info);
7948 return display_name;
7951 ICALL_EXPORT MonoString*
7952 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7955 MonoString *message;
7959 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7960 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7963 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7965 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7966 if (mono_error_set_pending_exception (&error))
7974 static inline gint32
7975 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
7977 return WAIT_TIMEOUT;
7979 #endif /* !HOST_WIN32 */
7982 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7984 return mono_icall_wait_for_input_idle (handle, milliseconds);
7988 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7990 return mono_process_current_pid ();
7993 ICALL_EXPORT MonoBoolean
7994 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
8006 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
8008 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
8012 ICALL_EXPORT MonoObject*
8013 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
8015 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
8020 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
8022 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
8026 ICALL_EXPORT MonoObject*
8027 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
8029 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
8033 ICALL_EXPORT MonoBoolean
8034 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
8036 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
8041 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
8043 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
8047 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
8049 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
8054 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
8056 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
8060 ICALL_EXPORT mono_unichar2*
8061 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
8063 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
8070 #ifndef DISABLE_ICALL_TABLES
8072 #define ICALL_TYPE(id,name,first)
8073 #define ICALL(id,name,func) Icall_ ## id,
8074 #define HANDLES(inner) inner
8077 #include "metadata/icall-def.h"
8083 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8084 #define ICALL(id,name,func)
8086 #define HANDLES(inner) inner
8088 #include "metadata/icall-def.h"
8094 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8095 #define ICALL(id,name,func)
8097 #define HANDLES(inner) inner
8099 guint16 first_icall;
8102 static const IcallTypeDesc
8103 icall_type_descs [] = {
8104 #include "metadata/icall-def.h"
8108 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8111 #define HANDLES(inner) inner
8113 #define ICALL_TYPE(id,name,first)
8116 #ifdef HAVE_ARRAY_ELEM_INIT
8117 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8118 #define MSGSTRFIELD1(line) str##line
8120 static const struct msgstrtn_t {
8121 #define ICALL(id,name,func)
8123 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8124 #include "metadata/icall-def.h"
8126 } icall_type_names_str = {
8127 #define ICALL_TYPE(id,name,first) (name),
8128 #include "metadata/icall-def.h"
8131 static const guint16 icall_type_names_idx [] = {
8132 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8133 #include "metadata/icall-def.h"
8136 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8138 static const struct msgstr_t {
8140 #define ICALL_TYPE(id,name,first)
8141 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8142 #include "metadata/icall-def.h"
8144 } icall_names_str = {
8145 #define ICALL(id,name,func) (name),
8146 #include "metadata/icall-def.h"
8149 static const guint16 icall_names_idx [] = {
8150 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8151 #include "metadata/icall-def.h"
8154 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8160 #define ICALL_TYPE(id,name,first) name,
8161 #define ICALL(id,name,func)
8162 static const char* const
8163 icall_type_names [] = {
8164 #include "metadata/icall-def.h"
8168 #define icall_type_name_get(id) (icall_type_names [(id)])
8172 #define ICALL_TYPE(id,name,first)
8173 #define ICALL(id,name,func) name,
8174 static const char* const
8176 #include "metadata/icall-def.h"
8179 #define icall_name_get(id) icall_names [(id)]
8181 #endif /* !HAVE_ARRAY_ELEM_INIT */
8184 #define HANDLES(inner) inner
8187 #define ICALL_TYPE(id,name,first)
8188 #define ICALL(id,name,func) func,
8189 static const gconstpointer
8190 icall_functions [] = {
8191 #include "metadata/icall-def.h"
8195 #ifdef ENABLE_ICALL_SYMBOL_MAP
8197 #define HANDLES(inner) inner
8200 #define ICALL_TYPE(id,name,first)
8201 #define ICALL(id,name,func) #func,
8202 static const gconstpointer
8203 icall_symbols [] = {
8204 #include "metadata/icall-def.h"
8211 #define ICALL_TYPE(id,name,first)
8212 #define ICALL(id,name,func) 0,
8214 #define HANDLES(inner) 1,
8216 icall_uses_handles [] = {
8217 #include "metadata/icall-def.h"
8222 #endif /* DISABLE_ICALL_TABLES */
8224 static mono_mutex_t icall_mutex;
8225 static GHashTable *icall_hash = NULL;
8226 static GHashTable *jit_icall_hash_name = NULL;
8227 static GHashTable *jit_icall_hash_addr = NULL;
8230 mono_icall_init (void)
8232 #ifndef DISABLE_ICALL_TABLES
8235 /* check that tables are sorted: disable in release */
8238 const char *prev_class = NULL;
8239 const char *prev_method;
8241 for (i = 0; i < Icall_type_num; ++i) {
8242 const IcallTypeDesc *desc;
8245 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8246 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8247 prev_class = icall_type_name_get (i);
8248 desc = &icall_type_descs [i];
8249 num_icalls = icall_desc_num_icalls (desc);
8250 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8251 for (j = 0; j < num_icalls; ++j) {
8252 const char *methodn = icall_name_get (desc->first_icall + j);
8253 if (prev_method && strcmp (prev_method, methodn) >= 0)
8254 g_print ("method %s should come before method %s\n", methodn, prev_method);
8255 prev_method = methodn;
8261 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8262 mono_os_mutex_init (&icall_mutex);
8266 mono_icall_lock (void)
8268 mono_locks_os_acquire (&icall_mutex, IcallLock);
8272 mono_icall_unlock (void)
8274 mono_locks_os_release (&icall_mutex, IcallLock);
8278 mono_icall_cleanup (void)
8280 g_hash_table_destroy (icall_hash);
8281 g_hash_table_destroy (jit_icall_hash_name);
8282 g_hash_table_destroy (jit_icall_hash_addr);
8283 mono_os_mutex_destroy (&icall_mutex);
8287 * mono_add_internal_call:
8288 * @name: method specification to surface to the managed world
8289 * @method: pointer to a C method to invoke when the method is called
8291 * This method surfaces the C function pointed by @method as a method
8292 * that has been surfaced in managed code with the method specified in
8293 * @name as an internal call.
8295 * Internal calls are surfaced to all app domains loaded and they are
8296 * accessibly by a type with the specified name.
8298 * You must provide a fully qualified type name, that is namespaces
8299 * and type name, followed by a colon and the method name, with an
8300 * optional signature to bind.
8302 * For example, the following are all valid declarations:
8304 * "MyApp.Services.ScriptService:Accelerate"
8305 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8307 * You use method parameters in cases where there might be more than
8308 * one surface method to managed code. That way you can register different
8309 * internal calls for different method overloads.
8311 * The internal calls are invoked with no marshalling. This means that .NET
8312 * types like System.String are exposed as `MonoString *` parameters. This is
8313 * different than the way that strings are surfaced in P/Invoke.
8315 * For more information on how the parameters are marshalled, see the
8316 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8319 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8320 * reference for more information on the format of method descriptions.
8323 mono_add_internal_call (const char *name, gconstpointer method)
8327 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8329 mono_icall_unlock ();
8332 #ifndef DISABLE_ICALL_TABLES
8334 #ifdef HAVE_ARRAY_ELEM_INIT
8336 compare_method_imap (const void *key, const void *elem)
8338 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8339 return strcmp (key, method_name);
8343 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8345 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);
8348 return (nameslot - &icall_names_idx [0]);
8352 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8354 gsize slotnum = find_slot_icall (imap, name);
8357 return (gboolean)icall_uses_handles [slotnum];
8361 find_method_icall (const IcallTypeDesc *imap, const char *name)
8363 gsize slotnum = find_slot_icall (imap, name);
8366 return (gpointer)icall_functions [slotnum];
8370 compare_class_imap (const void *key, const void *elem)
8372 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8373 return strcmp (key, class_name);
8376 static const IcallTypeDesc*
8377 find_class_icalls (const char *name)
8379 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);
8382 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8385 #else /* HAVE_ARRAY_ELEM_INIT */
8388 compare_method_imap (const void *key, const void *elem)
8390 const char** method_name = (const char**)elem;
8391 return strcmp (key, *method_name);
8395 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8397 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8400 return nameslot - icall_names;
8404 find_method_icall (const IcallTypeDesc *imap, const char *name)
8406 gsize slotnum = find_slot_icall (imap, name);
8409 return (gpointer)icall_functions [slotnum];
8413 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8415 gsize slotnum = find_slot_icall (imap, name);
8418 return (gboolean)icall_uses_handles [slotnum];
8422 compare_class_imap (const void *key, const void *elem)
8424 const char** class_name = (const char**)elem;
8425 return strcmp (key, *class_name);
8428 static const IcallTypeDesc*
8429 find_class_icalls (const char *name)
8431 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8434 return &icall_type_descs [nameslot - icall_type_names];
8437 #endif /* HAVE_ARRAY_ELEM_INIT */
8439 #endif /* DISABLE_ICALL_TABLES */
8442 * we should probably export this as an helper (handle nested types).
8443 * Returns the number of chars written in buf.
8446 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8448 int nspacelen, cnamelen;
8449 nspacelen = strlen (klass->name_space);
8450 cnamelen = strlen (klass->name);
8451 if (nspacelen + cnamelen + 2 > bufsize)
8454 memcpy (buf, klass->name_space, nspacelen);
8455 buf [nspacelen ++] = '.';
8457 memcpy (buf + nspacelen, klass->name, cnamelen);
8458 buf [nspacelen + cnamelen] = 0;
8459 return nspacelen + cnamelen;
8462 #ifdef DISABLE_ICALL_TABLES
8464 no_icall_table (void)
8466 g_assert_not_reached ();
8471 * mono_lookup_internal_call_full:
8472 * @method: the method to look up
8473 * @uses_handles: out argument if method needs handles around managed objects.
8475 * Returns a pointer to the icall code for the given method. If
8476 * uses_handles is not NULL, it will be set to TRUE if the method
8477 * needs managed objects wrapped using the infrastructure in handle.h
8479 * If the method is not found, warns and returns NULL.
8482 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8487 int typelen = 0, mlen, siglen;
8489 #ifndef DISABLE_ICALL_TABLES
8490 const IcallTypeDesc *imap = NULL;
8493 g_assert (method != NULL);
8495 if (method->is_inflated)
8496 method = ((MonoMethodInflated *) method)->declaring;
8498 if (method->klass->nested_in) {
8499 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8503 mname [pos++] = '/';
8506 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8512 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8517 #ifndef DISABLE_ICALL_TABLES
8518 imap = find_class_icalls (mname);
8521 mname [typelen] = ':';
8522 mname [typelen + 1] = ':';
8524 mlen = strlen (method->name);
8525 memcpy (mname + typelen + 2, method->name, mlen);
8526 sigstart = mname + typelen + 2 + mlen;
8529 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8530 siglen = strlen (tmpsig);
8531 if (typelen + mlen + siglen + 6 > sizeof (mname))
8534 memcpy (sigstart + 1, tmpsig, siglen);
8535 sigstart [siglen + 1] = ')';
8536 sigstart [siglen + 2] = 0;
8541 res = g_hash_table_lookup (icall_hash, mname);
8544 *uses_handles = FALSE;
8545 mono_icall_unlock ();;
8548 /* try without signature */
8550 res = g_hash_table_lookup (icall_hash, mname);
8553 *uses_handles = FALSE;
8554 mono_icall_unlock ();
8558 #ifdef DISABLE_ICALL_TABLES
8559 mono_icall_unlock ();
8560 /* Fail only when the result is actually used */
8561 /* mono_marshal_get_native_wrapper () depends on this */
8562 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8563 return ves_icall_System_String_ctor_RedirectToCreateString;
8565 return no_icall_table;
8567 /* it wasn't found in the static call tables */
8570 *uses_handles = FALSE;
8571 mono_icall_unlock ();
8574 res = find_method_icall (imap, sigstart - mlen);
8577 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8578 mono_icall_unlock ();
8581 /* try _with_ signature */
8583 res = find_method_icall (imap, sigstart - mlen);
8586 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8587 mono_icall_unlock ();
8591 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8592 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8593 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8594 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8595 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");
8596 g_print ("If you see other errors or faults after this message they are probably related\n");
8597 g_print ("and you need to fix your mono install first.\n");
8599 mono_icall_unlock ();
8606 mono_lookup_internal_call (MonoMethod *method)
8608 return mono_lookup_internal_call_full (method, NULL);
8611 #ifdef ENABLE_ICALL_SYMBOL_MAP
8613 func_cmp (gconstpointer key, gconstpointer p)
8615 return (gsize)key - (gsize)*(gsize*)p;
8620 * mono_lookup_icall_symbol:
8622 * Given the icall METHOD, returns its C symbol.
8625 mono_lookup_icall_symbol (MonoMethod *m)
8627 #ifdef DISABLE_ICALL_TABLES
8628 g_assert_not_reached ();
8631 #ifdef ENABLE_ICALL_SYMBOL_MAP
8635 static gconstpointer *functions_sorted;
8636 static const char**symbols_sorted;
8637 static gboolean inited;
8642 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8643 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8644 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8645 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8646 /* Bubble sort the two arrays */
8650 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8651 if (functions_sorted [i] > functions_sorted [i + 1]) {
8654 tmp = functions_sorted [i];
8655 functions_sorted [i] = functions_sorted [i + 1];
8656 functions_sorted [i + 1] = tmp;
8657 tmp = symbols_sorted [i];
8658 symbols_sorted [i] = symbols_sorted [i + 1];
8659 symbols_sorted [i + 1] = tmp;
8666 func = mono_lookup_internal_call (m);
8669 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8673 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8675 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8676 g_assert_not_reached ();
8683 type_from_typename (char *type_name)
8685 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8687 if (!strcmp (type_name, "int"))
8688 klass = mono_defaults.int_class;
8689 else if (!strcmp (type_name, "ptr"))
8690 klass = mono_defaults.int_class;
8691 else if (!strcmp (type_name, "void"))
8692 klass = mono_defaults.void_class;
8693 else if (!strcmp (type_name, "int32"))
8694 klass = mono_defaults.int32_class;
8695 else if (!strcmp (type_name, "uint32"))
8696 klass = mono_defaults.uint32_class;
8697 else if (!strcmp (type_name, "int8"))
8698 klass = mono_defaults.sbyte_class;
8699 else if (!strcmp (type_name, "uint8"))
8700 klass = mono_defaults.byte_class;
8701 else if (!strcmp (type_name, "int16"))
8702 klass = mono_defaults.int16_class;
8703 else if (!strcmp (type_name, "uint16"))
8704 klass = mono_defaults.uint16_class;
8705 else if (!strcmp (type_name, "long"))
8706 klass = mono_defaults.int64_class;
8707 else if (!strcmp (type_name, "ulong"))
8708 klass = mono_defaults.uint64_class;
8709 else if (!strcmp (type_name, "float"))
8710 klass = mono_defaults.single_class;
8711 else if (!strcmp (type_name, "double"))
8712 klass = mono_defaults.double_class;
8713 else if (!strcmp (type_name, "object"))
8714 klass = mono_defaults.object_class;
8715 else if (!strcmp (type_name, "obj"))
8716 klass = mono_defaults.object_class;
8717 else if (!strcmp (type_name, "string"))
8718 klass = mono_defaults.string_class;
8719 else if (!strcmp (type_name, "bool"))
8720 klass = mono_defaults.boolean_class;
8721 else if (!strcmp (type_name, "boolean"))
8722 klass = mono_defaults.boolean_class;
8724 g_error ("%s", type_name);
8725 g_assert_not_reached ();
8727 return &klass->byval_arg;
8731 * LOCKING: Take the corlib image lock.
8733 MonoMethodSignature*
8734 mono_create_icall_signature (const char *sigstr)
8739 MonoMethodSignature *res, *res2;
8740 MonoImage *corlib = mono_defaults.corlib;
8742 mono_image_lock (corlib);
8743 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8744 mono_image_unlock (corlib);
8749 parts = g_strsplit (sigstr, " ", 256);
8758 res = mono_metadata_signature_alloc (corlib, len - 1);
8763 * Under windows, the default pinvoke calling convention is STDCALL but
8766 res->call_convention = MONO_CALL_C;
8769 res->ret = type_from_typename (parts [0]);
8770 for (i = 1; i < len; ++i) {
8771 res->params [i - 1] = type_from_typename (parts [i]);
8776 mono_image_lock (corlib);
8777 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8779 res = res2; /*Value is allocated in the image pool*/
8781 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8782 mono_image_unlock (corlib);
8788 mono_find_jit_icall_by_name (const char *name)
8790 MonoJitICallInfo *info;
8791 g_assert (jit_icall_hash_name);
8794 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8795 mono_icall_unlock ();
8800 mono_find_jit_icall_by_addr (gconstpointer addr)
8802 MonoJitICallInfo *info;
8803 g_assert (jit_icall_hash_addr);
8806 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8807 mono_icall_unlock ();
8813 * mono_get_jit_icall_info:
8815 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8816 * caller should access it while holding the icall lock.
8819 mono_get_jit_icall_info (void)
8821 return jit_icall_hash_name;
8825 * mono_lookup_jit_icall_symbol:
8827 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8830 mono_lookup_jit_icall_symbol (const char *name)
8832 MonoJitICallInfo *info;
8833 const char *res = NULL;
8836 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8838 res = info->c_symbol;
8839 mono_icall_unlock ();
8844 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8847 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8848 mono_icall_unlock ();
8852 * 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
8853 * icalls without wrappers in some cases.
8856 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8858 MonoJitICallInfo *info;
8865 if (!jit_icall_hash_name) {
8866 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8867 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8870 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8871 g_warning ("jit icall already defined \"%s\"\n", name);
8872 g_assert_not_reached ();
8875 info = g_new0 (MonoJitICallInfo, 1);
8880 info->c_symbol = c_symbol;
8881 info->no_raise = no_raise;
8884 info->wrapper = func;
8886 info->wrapper = NULL;
8889 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8890 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8892 mono_icall_unlock ();
8897 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8899 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);