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/metadata-internals.h>
56 #include <mono/metadata/class-internals.h>
57 #include <mono/metadata/reflection-internals.h>
58 #include <mono/metadata/marshal.h>
59 #include <mono/metadata/gc-internals.h>
60 #include <mono/metadata/mono-gc.h>
61 #include <mono/metadata/rand.h>
62 #include <mono/metadata/sysmath.h>
63 #include <mono/metadata/appdomain-icalls.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 MonoReflectionAssemblyHandle ves_icall_System_Reflection_Assembly_GetCallingAssembly (MonoError *error);
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 (MonoArrayHandle array, MonoClassField *field_handle, MonoError *error)
846 mono_error_init (error);
848 MonoClass *klass = mono_handle_class (array);
849 guint32 size = mono_array_element_size (klass);
850 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
852 const char *field_data;
854 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
855 mono_error_set_argument (error, "array", "Cannot initialize array of non-primitive type");
859 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
860 mono_error_set_argument (error, "field_handle", "Field '%s' doesn't have an RVA", mono_field_get_name (field_handle));
864 size *= MONO_HANDLE_GETVAL(array, max_length);
865 field_data = mono_field_get_data (field_handle);
867 if (size > mono_type_size (field_handle->type, &align)) {
868 mono_error_set_argument (error, "field_handle", "Field not large enough to fill array");
872 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
874 guint ## n *data = (guint ## n *) mono_array_addr (MONO_HANDLE_RAW(array), char, 0); \
875 guint ## n *src = (guint ## n *) field_data; \
877 nEnt = (size / sizeof(guint ## n)); \
879 for (i = 0; i < nEnt; i++) { \
880 data[i] = read ## n (&src[i]); \
884 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
886 switch (type->type) {
903 memcpy (mono_array_addr (MONO_HANDLE_RAW(array), char, 0), field_data, size);
907 memcpy (mono_array_addr (MONO_HANDLE_RAW(array), char, 0), field_data, size);
912 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
914 return offsetof (MonoString, chars);
917 ICALL_EXPORT MonoObject *
918 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
920 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
924 MonoObject *ret = mono_object_clone_checked (obj, &error);
925 mono_error_set_pending_exception (&error);
932 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
938 MONO_CHECK_ARG_NULL (handle,);
940 klass = mono_class_from_mono_type (handle);
941 MONO_CHECK_ARG (handle, klass,);
943 if (mono_class_is_gtd (klass))
946 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
947 if (!is_ok (&error)) {
948 mono_error_set_pending_exception (&error);
952 /* This will call the type constructor */
953 if (!mono_runtime_class_init_full (vtable, &error))
954 mono_error_set_pending_exception (&error);
958 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
962 mono_image_check_for_module_cctor (image);
963 if (image->has_module_cctor) {
964 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
965 if (!mono_error_ok (&error)) {
966 mono_error_set_pending_exception (&error);
969 /*It's fine to raise the exception here*/
970 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
971 if (!is_ok (&error)) {
972 mono_error_set_pending_exception (&error);
975 if (!mono_runtime_class_init_full (vtable, &error))
976 mono_error_set_pending_exception (&error);
980 ICALL_EXPORT MonoBoolean
981 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
983 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
984 // It does not work on win32
990 MonoInternalThread *thread;
992 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
993 /* if we have no info we are optimistic and assume there is enough room */
997 thread = mono_thread_internal_current ();
998 // .net seems to check that at least 50% of stack is available
999 min_size = thread->stack_size / 2;
1001 // TODO: It's not always set
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_get_underlying_type_ignore_byref (MonoType *type)
1601 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1602 return mono_class_enum_basetype (type->data.klass);
1603 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1604 return mono_class_enum_basetype (type->data.generic_class->container_class);
1608 ICALL_EXPORT guint32
1609 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1614 g_assert (type != NULL);
1616 klass = mono_class_from_mono_type (type->type);
1617 klassc = mono_class_from_mono_type (c->type);
1619 if (type->type->byref ^ c->type->byref)
1622 if (type->type->byref) {
1623 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1624 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1626 klass = mono_class_from_mono_type (t);
1627 klassc = mono_class_from_mono_type (ot);
1629 if (mono_type_is_primitive (t)) {
1630 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1631 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1632 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1633 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1634 return t->type == ot->type;
1636 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1639 if (klass->valuetype)
1640 return klass == klassc;
1641 return klass->valuetype == klassc->valuetype;
1644 return mono_class_is_assignable_from (klass, klassc);
1647 ICALL_EXPORT guint32
1648 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1651 MonoClass *klass = mono_class_from_mono_type (type->type);
1652 mono_class_init_checked (klass, &error);
1653 if (!is_ok (&error)) {
1654 mono_error_set_pending_exception (&error);
1657 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1658 mono_error_set_pending_exception (&error);
1662 ICALL_EXPORT guint32
1663 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1665 MonoClass *klass = mono_class_from_mono_type (type->type);
1666 return mono_class_get_flags (klass);
1669 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1670 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1673 MonoClass *klass = field->field->parent;
1674 MonoMarshalType *info;
1678 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1679 if (mono_class_is_gtd (klass) ||
1680 (gklass && gklass->context.class_inst->is_open))
1683 ftype = mono_field_get_type (field->field);
1684 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1687 info = mono_marshal_load_type_info (klass);
1689 for (i = 0; i < info->num_fields; ++i) {
1690 if (info->fields [i].field == field->field) {
1691 if (!info->fields [i].mspec)
1694 MonoReflectionMarshalAsAttribute* obj;
1695 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1696 if (!mono_error_ok (&error))
1697 mono_error_set_pending_exception (&error);
1706 ICALL_EXPORT MonoReflectionField*
1707 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1710 gboolean found = FALSE;
1716 klass = handle->parent;
1718 klass = mono_class_from_mono_type (type);
1720 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1723 /* The managed code will throw the exception */
1727 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1728 mono_error_set_pending_exception (&error);
1732 ICALL_EXPORT MonoReflectionEvent*
1733 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1741 klass = handle->parent;
1743 klass = mono_class_from_mono_type (type);
1745 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1747 /* Managed code will throw an exception */
1751 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1752 mono_error_set_pending_exception (&error);
1757 ICALL_EXPORT MonoReflectionProperty*
1758 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1766 klass = handle->parent;
1768 klass = mono_class_from_mono_type (type);
1770 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1772 /* Managed code will throw an exception */
1776 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1777 mono_error_set_pending_exception (&error);
1781 ICALL_EXPORT MonoArray*
1782 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1785 MonoType *type = mono_field_get_type_checked (field->field, &error);
1788 if (!mono_error_ok (&error)) {
1789 mono_error_set_pending_exception (&error);
1793 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1794 mono_error_set_pending_exception (&error);
1799 vell_icall_get_method_attributes (MonoMethod *method)
1801 return method->flags;
1805 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1808 MonoReflectionType *rt;
1809 MonoDomain *domain = mono_domain_get ();
1810 MonoMethodSignature* sig;
1812 sig = mono_method_signature_checked (method, &error);
1813 if (!mono_error_ok (&error)) {
1814 mono_error_set_pending_exception (&error);
1818 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1819 if (!mono_error_ok (&error)) {
1820 mono_error_set_pending_exception (&error);
1824 MONO_STRUCT_SETREF (info, parent, rt);
1826 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1827 if (!mono_error_ok (&error)) {
1828 mono_error_set_pending_exception (&error);
1832 MONO_STRUCT_SETREF (info, ret, rt);
1834 info->attrs = method->flags;
1835 info->implattrs = method->iflags;
1836 if (sig->call_convention == MONO_CALL_DEFAULT)
1837 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1839 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1844 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1847 ICALL_EXPORT MonoArray*
1848 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1851 MonoDomain *domain = mono_domain_get ();
1853 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1854 mono_error_set_pending_exception (&error);
1858 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1859 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1862 MonoDomain *domain = mono_domain_get ();
1863 MonoReflectionMarshalAsAttribute* res = NULL;
1864 MonoMarshalSpec **mspecs;
1867 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1868 mono_method_get_marshal_info (method, mspecs);
1871 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1872 if (!mono_error_ok (&error)) {
1873 mono_error_set_pending_exception (&error);
1878 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1880 mono_metadata_free_marshal_spec (mspecs [i]);
1887 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1889 MonoClass *parent = field->field->parent;
1890 mono_class_setup_fields (parent);
1892 return field->field->offset - sizeof (MonoObject);
1895 ICALL_EXPORT MonoReflectionType*
1896 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1899 MonoReflectionType *ret;
1902 parent = declaring? field->field->parent: field->klass;
1904 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1905 mono_error_set_pending_exception (&error);
1911 ICALL_EXPORT MonoObject *
1912 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1915 MonoClass *fklass = field->klass;
1916 MonoClassField *cf = field->field;
1917 MonoDomain *domain = mono_object_domain (field);
1919 if (fklass->image->assembly->ref_only) {
1920 mono_set_pending_exception (mono_get_exception_invalid_operation (
1921 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1925 if (mono_security_core_clr_enabled () &&
1926 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1927 mono_error_set_pending_exception (&error);
1931 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1932 mono_error_set_pending_exception (&error);
1937 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1940 MonoClassField *cf = field->field;
1944 if (field->klass->image->assembly->ref_only) {
1945 mono_set_pending_exception (mono_get_exception_invalid_operation (
1946 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1950 if (mono_security_core_clr_enabled () &&
1951 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1952 mono_error_set_pending_exception (&error);
1956 type = mono_field_get_type_checked (cf, &error);
1957 if (!mono_error_ok (&error)) {
1958 mono_error_set_pending_exception (&error);
1962 v = (gchar *) value;
1964 switch (type->type) {
1967 case MONO_TYPE_BOOLEAN:
1970 case MONO_TYPE_CHAR:
1979 case MONO_TYPE_VALUETYPE:
1982 v += sizeof (MonoObject);
1984 case MONO_TYPE_STRING:
1985 case MONO_TYPE_OBJECT:
1986 case MONO_TYPE_CLASS:
1987 case MONO_TYPE_ARRAY:
1988 case MONO_TYPE_SZARRAY:
1991 case MONO_TYPE_GENERICINST: {
1992 MonoGenericClass *gclass = type->data.generic_class;
1993 g_assert (!gclass->context.class_inst->is_open);
1995 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1996 MonoClass *nklass = mono_class_from_mono_type (type);
1997 MonoObject *nullable;
2000 * Convert the boxed vtype into a Nullable structure.
2001 * This is complicated by the fact that Nullables have
2002 * a variable structure.
2004 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2005 if (!mono_error_ok (&error)) {
2006 mono_error_set_pending_exception (&error);
2010 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2012 v = (gchar *)mono_object_unbox (nullable);
2015 if (gclass->container_class->valuetype && (v != NULL))
2016 v += sizeof (MonoObject);
2020 g_error ("type 0x%x not handled in "
2021 "ves_icall_FieldInfo_SetValueInternal", type->type);
2026 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2027 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2028 if (!is_ok (&error)) {
2029 mono_error_set_pending_exception (&error);
2032 if (!vtable->initialized) {
2033 if (!mono_runtime_class_init_full (vtable, &error)) {
2034 mono_error_set_pending_exception (&error);
2038 mono_field_static_set_value (vtable, cf, v);
2040 mono_field_set_value (obj, cf, v);
2045 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2054 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2055 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2059 if (MONO_TYPE_IS_REFERENCE (f->type))
2060 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2062 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2065 ICALL_EXPORT MonoObject *
2066 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2068 MonoObject *o = NULL;
2069 MonoClassField *field = rfield->field;
2071 MonoDomain *domain = mono_object_domain (rfield);
2073 MonoTypeEnum def_type;
2074 const char *def_value;
2078 mono_class_init (field->parent);
2080 t = mono_field_get_type_checked (field, &error);
2081 if (!mono_error_ok (&error)) {
2082 mono_error_set_pending_exception (&error);
2086 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2087 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2091 if (image_is_dynamic (field->parent->image)) {
2092 MonoClass *klass = field->parent;
2093 int fidx = field - klass->fields;
2094 MonoFieldDefaultValue *def_values = mono_class_get_field_def_values (klass);
2096 g_assert (def_values);
2097 def_type = def_values [fidx].def_type;
2098 def_value = def_values [fidx].data;
2100 if (def_type == MONO_TYPE_END) {
2101 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2105 def_value = mono_class_get_field_default_value (field, &def_type);
2106 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2108 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2113 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2117 case MONO_TYPE_BOOLEAN:
2120 case MONO_TYPE_CHAR:
2128 case MONO_TYPE_R8: {
2131 /* boxed value type */
2132 t = g_new0 (MonoType, 1);
2134 klass = mono_class_from_mono_type (t);
2136 o = mono_object_new_checked (domain, klass, &error);
2137 if (!mono_error_ok (&error)) {
2138 mono_error_set_pending_exception (&error);
2141 v = ((gchar *) o) + sizeof (MonoObject);
2142 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2143 if (mono_error_set_pending_exception (&error))
2147 case MONO_TYPE_STRING:
2148 case MONO_TYPE_CLASS:
2149 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2150 if (mono_error_set_pending_exception (&error))
2154 g_assert_not_reached ();
2160 ICALL_EXPORT MonoReflectionType*
2161 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2164 MonoReflectionType *ret;
2167 type = mono_field_get_type_checked (ref_field->field, &error);
2168 if (!mono_error_ok (&error)) {
2169 mono_error_set_pending_exception (&error);
2173 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2174 if (!mono_error_ok (&error)) {
2175 mono_error_set_pending_exception (&error);
2182 /* From MonoProperty.cs */
2184 PInfo_Attributes = 1,
2185 PInfo_GetMethod = 1 << 1,
2186 PInfo_SetMethod = 1 << 2,
2187 PInfo_ReflectedType = 1 << 3,
2188 PInfo_DeclaringType = 1 << 4,
2193 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2196 MonoReflectionType *rt;
2197 MonoReflectionMethod *rm;
2198 MonoDomain *domain = mono_object_domain (property);
2199 const MonoProperty *pproperty = property->property;
2201 if ((req_info & PInfo_ReflectedType) != 0) {
2202 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2203 if (mono_error_set_pending_exception (&error))
2206 MONO_STRUCT_SETREF (info, parent, rt);
2208 if ((req_info & PInfo_DeclaringType) != 0) {
2209 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2210 if (mono_error_set_pending_exception (&error))
2213 MONO_STRUCT_SETREF (info, declaring_type, rt);
2216 if ((req_info & PInfo_Name) != 0)
2217 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2219 if ((req_info & PInfo_Attributes) != 0)
2220 info->attrs = pproperty->attrs;
2222 if ((req_info & PInfo_GetMethod) != 0) {
2223 if (pproperty->get &&
2224 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2225 pproperty->get->klass == property->klass)) {
2226 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2227 if (mono_error_set_pending_exception (&error))
2233 MONO_STRUCT_SETREF (info, get, rm);
2235 if ((req_info & PInfo_SetMethod) != 0) {
2236 if (pproperty->set &&
2237 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2238 pproperty->set->klass == property->klass)) {
2239 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2240 if (mono_error_set_pending_exception (&error))
2246 MONO_STRUCT_SETREF (info, set, rm);
2249 * There may be other methods defined for properties, though, it seems they are not exposed
2250 * in the reflection API
2255 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2258 MonoReflectionType *rt;
2259 MonoReflectionMethod *rm;
2260 MonoDomain *domain = mono_object_domain (event);
2262 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2263 if (mono_error_set_pending_exception (&error))
2266 MONO_STRUCT_SETREF (info, reflected_type, rt);
2268 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2269 if (mono_error_set_pending_exception (&error))
2272 MONO_STRUCT_SETREF (info, declaring_type, rt);
2274 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2275 info->attrs = event->event->attrs;
2277 if (event->event->add) {
2278 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2279 if (mono_error_set_pending_exception (&error))
2285 MONO_STRUCT_SETREF (info, add_method, rm);
2287 if (event->event->remove) {
2288 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2289 if (mono_error_set_pending_exception (&error))
2295 MONO_STRUCT_SETREF (info, remove_method, rm);
2297 if (event->event->raise) {
2298 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2299 if (mono_error_set_pending_exception (&error))
2305 MONO_STRUCT_SETREF (info, raise_method, rm);
2307 #ifndef MONO_SMALL_CONFIG
2308 if (event->event->other) {
2310 while (event->event->other [n])
2312 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2313 if (mono_error_set_pending_exception (&error))
2315 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2317 for (i = 0; i < n; i++) {
2318 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2319 if (mono_error_set_pending_exception (&error))
2321 mono_array_setref (info->other_methods, i, rm);
2328 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2333 mono_class_setup_interfaces (klass, error);
2334 if (!mono_error_ok (error))
2337 for (i = 0; i < klass->interface_count; i++) {
2338 ic = klass->interfaces [i];
2339 g_hash_table_insert (ifaces, ic, ic);
2341 collect_interfaces (ic, ifaces, error);
2342 if (!mono_error_ok (error))
2348 MonoArray *iface_array;
2349 MonoGenericContext *context;
2353 } FillIfaceArrayData;
2356 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2358 MonoReflectionType *rt;
2359 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2360 MonoClass *ic = (MonoClass *)key;
2361 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2363 if (!mono_error_ok (data->error))
2366 if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
2367 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2368 if (!mono_error_ok (data->error))
2372 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2373 if (!mono_error_ok (data->error))
2376 mono_array_setref (data->iface_array, data->next_idx++, rt);
2379 mono_metadata_free_type (inflated);
2383 get_interfaces_hash (gconstpointer v1)
2385 MonoClass *k = (MonoClass*)v1;
2387 return k->type_token;
2390 ICALL_EXPORT MonoArray*
2391 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2394 MonoClass *klass = mono_class_from_mono_type (type->type);
2396 FillIfaceArrayData data = { 0 };
2399 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2401 if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
2402 data.context = mono_class_get_context (klass);
2403 klass = mono_class_get_generic_class (klass)->container_class;
2406 for (parent = klass; parent; parent = parent->parent) {
2407 mono_class_setup_interfaces (parent, &error);
2408 if (!mono_error_ok (&error))
2410 collect_interfaces (parent, iface_hash, &error);
2411 if (!mono_error_ok (&error))
2415 data.error = &error;
2416 data.domain = mono_object_domain (type);
2418 len = g_hash_table_size (iface_hash);
2420 g_hash_table_destroy (iface_hash);
2421 if (!data.domain->empty_types) {
2422 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2423 if (!is_ok (&error))
2426 return data.domain->empty_types;
2429 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2430 if (!is_ok (&error))
2432 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2433 if (!mono_error_ok (&error))
2436 g_hash_table_destroy (iface_hash);
2437 return data.iface_array;
2440 g_hash_table_destroy (iface_hash);
2441 mono_error_set_pending_exception (&error);
2446 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2448 gboolean variance_used;
2449 MonoClass *klass = mono_class_from_mono_type (type->type);
2450 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2451 MonoReflectionMethod *member;
2454 int i = 0, len, ioffset;
2458 mono_class_init_checked (klass, &error);
2459 if (mono_error_set_pending_exception (&error))
2461 mono_class_init_checked (iclass, &error);
2462 if (mono_error_set_pending_exception (&error))
2465 mono_class_setup_vtable (klass);
2467 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2471 len = mono_class_num_methods (iclass);
2472 domain = mono_object_domain (type);
2473 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2474 if (mono_error_set_pending_exception (&error))
2476 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2477 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2478 if (mono_error_set_pending_exception (&error))
2480 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2482 while ((method = mono_class_get_methods (iclass, &iter))) {
2483 member = mono_method_get_object_checked (domain, method, iclass, &error);
2484 if (mono_error_set_pending_exception (&error))
2486 mono_array_setref (*methods, i, member);
2487 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2488 if (mono_error_set_pending_exception (&error))
2490 mono_array_setref (*targets, i, member);
2497 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2500 MonoClass *klass = mono_class_from_mono_type (type->type);
2502 mono_class_init_checked (klass, &error);
2503 if (mono_error_set_pending_exception (&error))
2506 if (image_is_dynamic (klass->image)) {
2507 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2508 *packing = tb->packing_size;
2509 *size = tb->class_size;
2511 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2515 ICALL_EXPORT MonoReflectionType*
2516 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2519 MonoReflectionType *ret;
2522 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2523 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2524 mono_error_set_pending_exception (&error);
2528 klass = mono_class_from_mono_type (type->type);
2529 mono_class_init_checked (klass, &error);
2530 if (mono_error_set_pending_exception (&error))
2534 // GetElementType should only return a type for:
2535 // Array Pointer PassedByRef
2536 if (type->type->byref)
2537 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2538 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2539 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2540 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2541 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2545 mono_error_set_pending_exception (&error);
2550 ICALL_EXPORT MonoReflectionType*
2551 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2554 MonoReflectionType *ret;
2556 if (type->type->byref)
2559 MonoClass *klass = mono_class_from_mono_type (type->type);
2563 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2564 mono_error_set_pending_exception (&error);
2569 ICALL_EXPORT MonoBoolean
2570 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2572 return type->type->type == MONO_TYPE_PTR;
2575 ICALL_EXPORT MonoBoolean
2576 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2578 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)));
2581 ICALL_EXPORT MonoBoolean
2582 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2584 return type->type->byref;
2587 ICALL_EXPORT MonoBoolean
2588 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2591 MonoClass *klass = mono_class_from_mono_type (type->type);
2592 mono_class_init_checked (klass, &error);
2593 if (mono_error_set_pending_exception (&error))
2596 return mono_class_is_com_object (klass);
2599 ICALL_EXPORT guint32
2600 ves_icall_reflection_get_token (MonoObject* obj)
2603 guint32 result = mono_reflection_get_token_checked (obj, &error);
2604 mono_error_set_pending_exception (&error);
2608 ICALL_EXPORT MonoReflectionModuleHandle
2609 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionTypeHandle type, MonoError *error)
2611 mono_error_init (error);
2612 MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
2613 MonoType *t = MONO_HANDLE_GETVAL (type, type);
2614 MonoClass *klass = mono_class_from_mono_type (t);
2615 return mono_module_get_object_handle (domain, klass->image, error);
2618 ICALL_EXPORT MonoReflectionAssemblyHandle
2619 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionTypeHandle type, MonoError *error)
2621 mono_error_init (error);
2622 MonoDomain *domain = mono_domain_get ();
2623 MonoType *t = MONO_HANDLE_GETVAL (type, type);
2624 MonoClass *klass = mono_class_from_mono_type (t);
2625 return mono_assembly_get_object_handle (domain, klass->image->assembly, error);
2628 ICALL_EXPORT MonoReflectionType*
2629 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2632 MonoReflectionType *ret;
2633 MonoDomain *domain = mono_domain_get ();
2636 if (type->type->byref)
2638 if (type->type->type == MONO_TYPE_VAR) {
2639 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2640 klass = param ? param->owner.klass : NULL;
2641 } else if (type->type->type == MONO_TYPE_MVAR) {
2642 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2643 klass = param ? param->owner.method->klass : NULL;
2645 klass = mono_class_from_mono_type (type->type)->nested_in;
2651 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2652 mono_error_set_pending_exception (&error);
2657 ICALL_EXPORT MonoStringHandle
2658 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2660 MonoDomain *domain = mono_domain_get ();
2661 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2662 MonoClass *klass = mono_class_from_mono_type (type);
2665 char *n = g_strdup_printf ("%s&", klass->name);
2666 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2672 return mono_string_new_handle (domain, klass->name, error);
2676 ICALL_EXPORT MonoStringHandle
2677 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2679 MonoDomain *domain = mono_domain_get ();
2680 MonoClass *klass = mono_class_from_mono_type_handle (type);
2682 while (klass->nested_in)
2683 klass = klass->nested_in;
2685 if (klass->name_space [0] == '\0')
2686 return NULL_HANDLE_STRING;
2688 return mono_string_new_handle (domain, klass->name_space, error);
2692 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2696 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2697 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2701 klass = mono_class_from_mono_type (type->type);
2707 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2709 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2712 ICALL_EXPORT MonoArray*
2713 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2716 MonoReflectionType *rt;
2718 MonoClass *klass, *pklass;
2719 MonoDomain *domain = mono_object_domain (type);
2722 klass = mono_class_from_mono_type (type->type);
2724 if (mono_class_is_gtd (klass)) {
2725 MonoGenericContainer *container = mono_class_get_generic_container (klass);
2726 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2727 if (mono_error_set_pending_exception (&error))
2729 for (i = 0; i < container->type_argc; ++i) {
2730 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2732 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2733 if (mono_error_set_pending_exception (&error))
2736 mono_array_setref (res, i, rt);
2738 } else if (mono_class_is_ginst (klass)) {
2739 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
2740 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2741 if (mono_error_set_pending_exception (&error))
2743 for (i = 0; i < inst->type_argc; ++i) {
2744 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2745 if (mono_error_set_pending_exception (&error))
2748 mono_array_setref (res, i, rt);
2756 ICALL_EXPORT gboolean
2757 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2761 if (!IS_MONOTYPE (type))
2764 if (type->type->byref)
2767 klass = mono_class_from_mono_type (type->type);
2768 return mono_class_is_gtd (klass);
2771 ICALL_EXPORT MonoReflectionType*
2772 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2775 MonoReflectionType *ret;
2778 if (type->type->byref)
2781 klass = mono_class_from_mono_type (type->type);
2783 if (mono_class_is_gtd (klass)) {
2784 return type; /* check this one */
2786 if (mono_class_is_ginst (klass)) {
2787 MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
2790 tb = mono_class_get_ref_info (generic_class);
2792 if (generic_class->wastypebuilder && tb)
2793 return (MonoReflectionType *)tb;
2795 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2796 mono_error_set_pending_exception (&error);
2804 ICALL_EXPORT MonoReflectionType*
2805 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2808 MonoReflectionType *ret;
2810 MonoType *geninst, **types;
2813 g_assert (IS_MONOTYPE (type));
2814 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2815 if (mono_error_set_pending_exception (&error))
2818 count = mono_array_length (type_array);
2819 types = g_new0 (MonoType *, count);
2821 for (i = 0; i < count; i++) {
2822 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2823 types [i] = t->type;
2826 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2829 mono_error_set_pending_exception (&error);
2833 klass = mono_class_from_mono_type (geninst);
2835 /*we might inflate to the GTD*/
2836 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2837 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2841 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2842 mono_error_set_pending_exception (&error);
2847 ICALL_EXPORT gboolean
2848 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2852 if (!IS_MONOTYPE (type))
2855 if (type->type->byref)
2858 klass = mono_class_from_mono_type (type->type);
2859 return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
2863 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2865 if (!IS_MONOTYPE (type))
2868 if (is_generic_parameter (type->type))
2869 return mono_type_get_generic_param_num (type->type);
2873 ICALL_EXPORT MonoGenericParamInfo *
2874 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2876 return mono_generic_param_info (type->type->data.generic_param);
2879 ICALL_EXPORT MonoBoolean
2880 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2882 return is_generic_parameter (type->type);
2885 ICALL_EXPORT MonoReflectionMethod*
2886 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2887 MonoReflectionMethod* generic)
2894 MonoReflectionMethod *ret = NULL;
2896 domain = ((MonoObject *)type)->vtable->domain;
2898 klass = mono_class_from_mono_type (type->type);
2899 mono_class_init_checked (klass, &error);
2900 if (mono_error_set_pending_exception (&error))
2904 while ((method = mono_class_get_methods (klass, &iter))) {
2905 if (method->token == generic->method->token) {
2906 ret = mono_method_get_object_checked (domain, method, klass, &error);
2907 if (mono_error_set_pending_exception (&error))
2915 ICALL_EXPORT MonoReflectionMethod *
2916 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2919 MonoType *type = ref_type->type;
2921 MonoReflectionMethod *ret = NULL;
2923 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2924 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2927 if (type->type == MONO_TYPE_VAR)
2930 method = mono_type_get_generic_param_owner (type)->owner.method;
2933 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2934 if (!mono_error_ok (&error))
2935 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2939 ICALL_EXPORT MonoBoolean
2940 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2942 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2946 ICALL_EXPORT MonoBoolean
2947 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2949 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2954 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2956 MonoDomain *domain = mono_domain_get ();
2957 MonoImage *image = method->method->klass->image;
2958 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2959 MonoTableInfo *tables = image->tables;
2960 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2961 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2962 guint32 im_cols [MONO_IMPLMAP_SIZE];
2963 guint32 scope_token;
2964 const char *import = NULL;
2965 const char *scope = NULL;
2967 if (image_is_dynamic (image)) {
2968 MonoReflectionMethodAux *method_aux =
2969 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2971 import = method_aux->dllentry;
2972 scope = method_aux->dll;
2975 if (!import || !scope) {
2976 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2981 if (piinfo->implmap_idx) {
2982 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2984 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2985 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2986 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2987 scope = mono_metadata_string_heap (image, scope_token);
2991 *flags = piinfo->piflags;
2992 *entry_point = mono_string_new (domain, import);
2993 *dll_name = mono_string_new (domain, scope);
2996 ICALL_EXPORT MonoReflectionMethod *
2997 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2999 MonoMethodInflated *imethod;
3001 MonoReflectionMethod *ret = NULL;
3004 if (method->method->is_generic)
3007 if (!method->method->is_inflated)
3010 imethod = (MonoMethodInflated *) method->method;
3012 result = imethod->declaring;
3013 /* Not a generic method. */
3014 if (!result->is_generic)
3017 if (image_is_dynamic (method->method->klass->image)) {
3018 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3019 MonoReflectionMethod *res;
3022 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3023 * the dynamic case as well ?
3025 mono_image_lock ((MonoImage*)image);
3026 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3027 mono_image_unlock ((MonoImage*)image);
3033 if (imethod->context.class_inst) {
3034 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3035 /*Generic methods gets the context of the GTD.*/
3036 if (mono_class_get_context (klass)) {
3037 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3038 if (!mono_error_ok (&error))
3043 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3045 if (!mono_error_ok (&error))
3046 mono_error_set_pending_exception (&error);
3050 ICALL_EXPORT gboolean
3051 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3053 return mono_method_signature (method->method)->generic_param_count != 0;
3056 ICALL_EXPORT gboolean
3057 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3059 return method->method->is_generic;
3062 ICALL_EXPORT MonoArray*
3063 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3066 MonoReflectionType *rt;
3071 domain = mono_object_domain (method);
3073 if (method->method->is_inflated) {
3074 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3077 count = inst->type_argc;
3078 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3079 if (mono_error_set_pending_exception (&error))
3082 for (i = 0; i < count; i++) {
3083 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3084 if (mono_error_set_pending_exception (&error))
3087 mono_array_setref (res, i, rt);
3094 count = mono_method_signature (method->method)->generic_param_count;
3095 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3096 if (mono_error_set_pending_exception (&error))
3099 for (i = 0; i < count; i++) {
3100 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3101 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3102 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3104 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3105 if (mono_error_set_pending_exception (&error))
3108 mono_array_setref (res, i, rt);
3114 ICALL_EXPORT MonoObject *
3115 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3119 * Invoke from reflection is supposed to always be a virtual call (the API
3120 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3121 * greater flexibility.
3123 MonoMethod *m = method->method;
3124 MonoMethodSignature *sig = mono_method_signature (m);
3127 void *obj = this_arg;
3131 if (mono_security_core_clr_enabled () &&
3132 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3133 mono_error_set_pending_exception (&error);
3137 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3138 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3139 mono_error_cleanup (&error); /* FIXME does this make sense? */
3140 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3145 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3146 if (!is_ok (&error)) {
3147 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3150 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3151 char *target_name = mono_type_get_full_name (m->klass);
3152 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3153 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3155 g_free (target_name);
3159 m = mono_object_get_virtual_method (this_arg, m);
3160 /* must pass the pointer to the value for valuetype methods */
3161 if (m->klass->valuetype)
3162 obj = mono_object_unbox (this_arg);
3163 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3164 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3169 if (sig->ret->byref) {
3170 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"));
3174 pcount = params? mono_array_length (params): 0;
3175 if (pcount != sig->param_count) {
3176 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3180 if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
3181 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."));
3185 image = m->klass->image;
3186 if (image->assembly->ref_only) {
3187 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."));
3191 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3192 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3196 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3200 intptr_t *lower_bounds;
3201 pcount = mono_array_length (params);
3202 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3203 /* Note: the synthetized array .ctors have int32 as argument type */
3204 for (i = 0; i < pcount; ++i)
3205 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3207 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3208 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3209 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3210 if (!mono_error_ok (&error)) {
3211 mono_error_set_pending_exception (&error);
3215 for (i = 0; i < mono_array_length (arr); ++i) {
3216 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3217 if (!mono_error_ok (&error)) {
3218 mono_error_set_pending_exception (&error);
3221 mono_array_setref_fast (arr, i, subarray);
3223 return (MonoObject*)arr;
3226 if (m->klass->rank == pcount) {
3227 /* Only lengths provided. */
3228 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3229 if (!mono_error_ok (&error)) {
3230 mono_error_set_pending_exception (&error);
3234 return (MonoObject*)arr;
3236 g_assert (pcount == (m->klass->rank * 2));
3237 /* The arguments are lower-bound-length pairs */
3238 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3240 for (i = 0; i < pcount / 2; ++i) {
3241 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3242 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3245 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3246 if (!mono_error_ok (&error)) {
3247 mono_error_set_pending_exception (&error);
3251 return (MonoObject*)arr;
3254 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3255 mono_error_set_pending_exception (&error);
3259 #ifndef DISABLE_REMOTING
3260 ICALL_EXPORT MonoObject *
3261 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3264 MonoDomain *domain = mono_object_domain (method);
3265 MonoMethod *m = method->method;
3266 MonoMethodSignature *sig = mono_method_signature (m);
3267 MonoArray *out_args;
3269 int i, j, outarg_count = 0;
3271 if (m->klass == mono_defaults.object_class) {
3272 if (!strcmp (m->name, "FieldGetter")) {
3273 MonoClass *k = this_arg->vtable->klass;
3277 /* If this is a proxy, then it must be a CBO */
3278 if (k == mono_defaults.transparent_proxy_class) {
3279 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3280 this_arg = tp->rp->unwrapped_server;
3281 g_assert (this_arg);
3282 k = this_arg->vtable->klass;
3285 name = mono_array_get (params, MonoString *, 1);
3286 str = mono_string_to_utf8_checked (name, &error);
3287 if (mono_error_set_pending_exception (&error))
3291 MonoClassField* field = mono_class_get_field_from_name (k, str);
3294 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3295 if (field_klass->valuetype) {
3296 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3297 if (mono_error_set_pending_exception (&error))
3300 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3302 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3303 if (mono_error_set_pending_exception (&error))
3305 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3306 mono_array_setref (out_args, 0, result);
3313 g_assert_not_reached ();
3315 } else if (!strcmp (m->name, "FieldSetter")) {
3316 MonoClass *k = this_arg->vtable->klass;
3322 /* If this is a proxy, then it must be a CBO */
3323 if (k == mono_defaults.transparent_proxy_class) {
3324 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3325 this_arg = tp->rp->unwrapped_server;
3326 g_assert (this_arg);
3327 k = this_arg->vtable->klass;
3330 name = mono_array_get (params, MonoString *, 1);
3331 str = mono_string_to_utf8_checked (name, &error);
3332 if (mono_error_set_pending_exception (&error))
3336 MonoClassField* field = mono_class_get_field_from_name (k, str);
3339 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3340 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3342 if (field_klass->valuetype) {
3343 size = mono_type_size (field->type, &align);
3344 g_assert (size == mono_class_value_size (field_klass, NULL));
3345 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3347 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3350 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3351 if (mono_error_set_pending_exception (&error))
3353 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3362 g_assert_not_reached ();
3367 for (i = 0; i < mono_array_length (params); i++) {
3368 if (sig->params [i]->byref)
3372 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3373 if (mono_error_set_pending_exception (&error))
3376 /* handle constructors only for objects already allocated */
3377 if (!strcmp (method->method->name, ".ctor"))
3378 g_assert (this_arg);
3380 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3381 g_assert (!method->method->klass->valuetype);
3382 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3383 if (mono_error_set_pending_exception (&error))
3386 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3387 if (sig->params [i]->byref) {
3389 arg = mono_array_get (params, gpointer, i);
3390 mono_array_setref (out_args, j, arg);
3395 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3402 read_enum_value (const char *mem, int type)
3405 case MONO_TYPE_BOOLEAN:
3407 return *(guint8*)mem;
3409 return *(gint8*)mem;
3410 case MONO_TYPE_CHAR:
3412 return read16 (mem);
3414 return (gint16) read16 (mem);
3416 return read32 (mem);
3418 return (gint32) read32 (mem);
3421 return read64 (mem);
3423 g_assert_not_reached ();
3429 write_enum_value (char *mem, int type, guint64 value)
3433 case MONO_TYPE_I1: {
3434 guint8 *p = (guint8*)mem;
3440 case MONO_TYPE_CHAR: {
3441 guint16 *p = (guint16 *)mem;
3446 case MONO_TYPE_I4: {
3447 guint32 *p = (guint32 *)mem;
3452 case MONO_TYPE_I8: {
3453 guint64 *p = (guint64 *)mem;
3458 g_assert_not_reached ();
3463 ICALL_EXPORT MonoObject *
3464 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3472 domain = mono_object_domain (enumType);
3473 enumc = mono_class_from_mono_type (enumType->type);
3475 mono_class_init_checked (enumc, &error);
3476 if (mono_error_set_pending_exception (&error))
3479 etype = mono_class_enum_basetype (enumc);
3481 res = mono_object_new_checked (domain, enumc, &error);
3482 if (mono_error_set_pending_exception (&error))
3484 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3489 ICALL_EXPORT MonoBoolean
3490 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3492 int size = mono_class_value_size (a->vtable->klass, NULL);
3493 guint64 a_val = 0, b_val = 0;
3495 memcpy (&a_val, mono_object_unbox (a), size);
3496 memcpy (&b_val, mono_object_unbox (b), size);
3498 return (a_val & b_val) == b_val;
3501 ICALL_EXPORT MonoObject *
3502 ves_icall_System_Enum_get_value (MonoObject *eobj)
3514 g_assert (eobj->vtable->klass->enumtype);
3516 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3517 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3518 if (mono_error_set_pending_exception (&error))
3520 dst = (char *)res + sizeof (MonoObject);
3521 src = (char *)eobj + sizeof (MonoObject);
3522 size = mono_class_value_size (enumc, NULL);
3524 memcpy (dst, src, size);
3529 ICALL_EXPORT MonoReflectionType *
3530 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3533 MonoReflectionType *ret;
3537 klass = mono_class_from_mono_type (type->type);
3538 mono_class_init_checked (klass, &error);
3539 if (mono_error_set_pending_exception (&error))
3542 etype = mono_class_enum_basetype (klass);
3544 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3548 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3549 mono_error_set_pending_exception (&error);
3555 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3557 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3558 gpointer odata = (char *)other + sizeof (MonoObject);
3559 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3560 g_assert (basetype);
3565 if (eobj->vtable->klass != other->vtable->klass)
3568 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3569 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3570 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3573 return me > other ? 1 : -1; \
3576 switch (basetype->type) {
3578 COMPARE_ENUM_VALUES (guint8);
3580 COMPARE_ENUM_VALUES (gint8);
3581 case MONO_TYPE_CHAR:
3583 COMPARE_ENUM_VALUES (guint16);
3585 COMPARE_ENUM_VALUES (gint16);
3587 COMPARE_ENUM_VALUES (guint32);
3589 COMPARE_ENUM_VALUES (gint32);
3591 COMPARE_ENUM_VALUES (guint64);
3593 COMPARE_ENUM_VALUES (gint64);
3597 #undef COMPARE_ENUM_VALUES
3598 /* indicates that the enum was of an unsupported unerlying type */
3603 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3605 gpointer data = (char *)eobj + sizeof (MonoObject);
3606 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3607 g_assert (basetype);
3609 switch (basetype->type) {
3610 case MONO_TYPE_I1: {
3611 gint8 value = *((gint8*)data);
3612 return ((int)value ^ (int)value << 8);
3615 return *((guint8*)data);
3616 case MONO_TYPE_CHAR:
3618 return *((guint16*)data);
3620 case MONO_TYPE_I2: {
3621 gint16 value = *((gint16*)data);
3622 return ((int)(guint16)value | (((int)value) << 16));
3625 return *((guint32*)data);
3627 return *((gint32*)data);
3629 case MONO_TYPE_I8: {
3630 gint64 value = *((gint64*)data);
3631 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3634 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3640 get_enum_field (MonoDomain *domain, MonoArrayHandle names, MonoArrayHandle values, int base_type, MonoClassField *field, guint* j, guint64 *previous_value, gboolean *sorted, MonoError *error)
3642 mono_error_init (error);
3643 HANDLE_FUNCTION_ENTER();
3644 guint64 field_value;
3646 MonoTypeEnum def_type;
3648 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3650 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3652 if (mono_field_is_deleted (field))
3654 MonoStringHandle name = mono_string_new_handle (domain, mono_field_get_name (field), error);
3657 MONO_HANDLE_ARRAY_SETREF (names, *j, name);
3659 p = mono_class_get_field_default_value (field, &def_type);
3660 /* len = */ mono_metadata_decode_blob_size (p, &p);
3662 field_value = read_enum_value (p, base_type);
3663 MONO_HANDLE_ARRAY_SETVAL (values, guint64, *j, field_value);
3665 if (*previous_value > field_value)
3668 *previous_value = field_value;
3671 HANDLE_FUNCTION_RETURN();
3674 ICALL_EXPORT MonoBoolean
3675 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionTypeHandle type, MonoArrayHandleOut values, MonoArrayHandleOut names, MonoError *error)
3677 MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
3678 MonoClass *enumc = mono_class_from_mono_type (MONO_HANDLE_RAW(type)->type);
3679 guint j = 0, nvalues;
3681 MonoClassField *field;
3683 guint64 previous_value = 0;
3684 gboolean sorted = TRUE;
3686 mono_error_init (error);
3687 mono_class_init_checked (enumc, error);
3688 return_val_if_nok (error, FALSE);
3690 if (!enumc->enumtype) {
3691 mono_error_set_argument (error, "enumType", "Type provided must be an Enum.");
3695 base_type = mono_class_enum_basetype (enumc)->type;
3697 nvalues = mono_class_num_fields (enumc) > 0 ? mono_class_num_fields (enumc) - 1 : 0;
3698 MONO_HANDLE_ASSIGN(names, mono_array_new_handle (domain, mono_defaults.string_class, nvalues, error));
3699 return_val_if_nok (error, FALSE);
3700 MONO_HANDLE_ASSIGN(values, mono_array_new_handle (domain, mono_defaults.uint64_class, nvalues, error));
3701 return_val_if_nok (error, FALSE);
3704 while ((field = mono_class_get_fields (enumc, &iter))) {
3705 get_enum_field(domain, names, values, base_type, field, &j, &previous_value, &sorted, error);
3709 return_val_if_nok (error, FALSE);
3715 BFLAGS_IgnoreCase = 1,
3716 BFLAGS_DeclaredOnly = 2,
3717 BFLAGS_Instance = 4,
3719 BFLAGS_Public = 0x10,
3720 BFLAGS_NonPublic = 0x20,
3721 BFLAGS_FlattenHierarchy = 0x40,
3722 BFLAGS_InvokeMethod = 0x100,
3723 BFLAGS_CreateInstance = 0x200,
3724 BFLAGS_GetField = 0x400,
3725 BFLAGS_SetField = 0x800,
3726 BFLAGS_GetProperty = 0x1000,
3727 BFLAGS_SetProperty = 0x2000,
3728 BFLAGS_ExactBinding = 0x10000,
3729 BFLAGS_SuppressChangeType = 0x20000,
3730 BFLAGS_OptionalParamBinding = 0x40000
3733 ICALL_EXPORT GPtrArray*
3734 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3737 MonoClass *startklass, *klass;
3740 int (*compare_func) (const char *s1, const char *s2) = NULL;
3741 MonoClassField *field;
3743 if (type->type->byref) {
3744 return g_ptr_array_new ();
3747 mono_error_init (&error);
3749 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3751 klass = startklass = mono_class_from_mono_type (type->type);
3753 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3756 if (mono_class_has_failure (klass)) {
3757 mono_error_set_for_class_failure (&error, klass);
3762 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3763 guint32 flags = mono_field_get_flags (field);
3765 if (mono_field_is_deleted_with_flags (field, flags))
3767 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3768 if (bflags & BFLAGS_Public)
3770 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3771 if (bflags & BFLAGS_NonPublic) {
3778 if (flags & FIELD_ATTRIBUTE_STATIC) {
3779 if (bflags & BFLAGS_Static)
3780 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3783 if (bflags & BFLAGS_Instance)
3790 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3793 g_ptr_array_add (ptr_array, field);
3795 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3801 g_ptr_array_free (ptr_array, TRUE);
3802 mono_error_set_pending_exception (&error);
3807 method_nonpublic (MonoMethod* method, gboolean start_klass)
3809 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3810 case METHOD_ATTRIBUTE_ASSEM:
3811 return (start_klass || mono_defaults.generic_ilist_class);
3812 case METHOD_ATTRIBUTE_PRIVATE:
3814 case METHOD_ATTRIBUTE_PUBLIC:
3822 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3825 MonoClass *startklass;
3829 /*FIXME, use MonoBitSet*/
3830 guint32 method_slots_default [8];
3831 guint32 *method_slots = NULL;
3832 int (*compare_func) (const char *s1, const char *s2) = NULL;
3834 array = g_ptr_array_new ();
3836 mono_error_init (error);
3839 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3841 /* An optimization for calls made from Delegate:CreateDelegate () */
3842 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3843 method = mono_get_delegate_invoke (klass);
3846 g_ptr_array_add (array, method);
3850 mono_class_setup_methods (klass);
3851 mono_class_setup_vtable (klass);
3852 if (mono_class_has_failure (klass))
3855 if (is_generic_parameter (&klass->byval_arg))
3856 nslots = mono_class_get_vtable_size (klass->parent);
3858 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3859 if (nslots >= sizeof (method_slots_default) * 8) {
3860 method_slots = g_new0 (guint32, nslots / 32 + 1);
3862 method_slots = method_slots_default;
3863 memset (method_slots, 0, sizeof (method_slots_default));
3866 mono_class_setup_methods (klass);
3867 mono_class_setup_vtable (klass);
3868 if (mono_class_has_failure (klass))
3872 while ((method = mono_class_get_methods (klass, &iter))) {
3874 if (method->slot != -1) {
3875 g_assert (method->slot < nslots);
3876 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3878 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3879 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3882 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3884 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3885 if (bflags & BFLAGS_Public)
3887 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3893 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3894 if (bflags & BFLAGS_Static)
3895 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3898 if (bflags & BFLAGS_Instance)
3906 if (compare_func (name, method->name))
3911 g_ptr_array_add (array, method);
3913 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3915 if (method_slots != method_slots_default)
3916 g_free (method_slots);
3921 if (method_slots != method_slots_default)
3922 g_free (method_slots);
3923 g_ptr_array_free (array, TRUE);
3925 g_assert (mono_class_has_failure (klass));
3926 mono_error_set_for_class_failure (error, klass);
3930 ICALL_EXPORT GPtrArray*
3931 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3934 GPtrArray *method_array;
3937 klass = mono_class_from_mono_type (type->type);
3938 if (type->type->byref) {
3939 return g_ptr_array_new ();
3942 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3943 mono_error_set_pending_exception (&error);
3944 return method_array;
3947 ICALL_EXPORT GPtrArray*
3948 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3950 MonoClass *startklass, *klass;
3953 gpointer iter = NULL;
3954 GPtrArray *res_array;
3957 if (type->type->byref) {
3958 return g_ptr_array_new ();
3961 klass = startklass = mono_class_from_mono_type (type->type);
3963 mono_class_setup_methods (klass);
3964 if (mono_class_has_failure (klass)) {
3965 mono_error_init (&error);
3966 mono_error_set_for_class_failure (&error, klass);
3967 mono_error_set_pending_exception (&error);
3971 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3974 while ((method = mono_class_get_methods (klass, &iter))) {
3976 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3978 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3979 if (bflags & BFLAGS_Public)
3982 if (bflags & BFLAGS_NonPublic)
3988 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3989 if (bflags & BFLAGS_Static)
3990 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3993 if (bflags & BFLAGS_Instance)
3999 g_ptr_array_add (res_array, method);
4006 property_hash (gconstpointer data)
4008 MonoProperty *prop = (MonoProperty*)data;
4010 return g_str_hash (prop->name);
4014 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4016 if (method1->slot != -1 && method1->slot == method2->slot)
4019 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4020 if (method1->is_inflated)
4021 method1 = ((MonoMethodInflated*) method1)->declaring;
4022 if (method2->is_inflated)
4023 method2 = ((MonoMethodInflated*) method2)->declaring;
4026 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4030 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4032 // Properties are hide-by-name-and-signature
4033 if (!g_str_equal (prop1->name, prop2->name))
4036 /* If we see a property in a generic method, we want to
4037 compare the generic signatures, not the inflated signatures
4038 because we might conflate two properties that were
4042 public T this[T t] { getter { return t; } } // method 1
4043 public U this[U u] { getter { return u; } } // method 2
4046 If we see int Foo<int,int>::Item[int] we need to know if
4047 the indexer came from method 1 or from method 2, and we
4048 shouldn't conflate them. (Bugzilla 36283)
4050 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4053 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4060 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4065 return method_nonpublic (accessor, start_klass);
4068 ICALL_EXPORT GPtrArray*
4069 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4072 MonoClass *startklass, *klass;
4077 int (*compare_func) (const char *s1, const char *s2) = NULL;
4079 GHashTable *properties = NULL;
4080 GPtrArray *res_array;
4082 if (type->type->byref) {
4083 return g_ptr_array_new ();
4086 mono_error_init (&error);
4088 klass = startklass = mono_class_from_mono_type (type->type);
4090 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4092 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4094 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4096 mono_class_setup_methods (klass);
4097 mono_class_setup_vtable (klass);
4098 if (mono_class_has_failure (klass)) {
4099 mono_error_set_for_class_failure (&error, klass);
4104 while ((prop = mono_class_get_properties (klass, &iter))) {
4110 flags = method->flags;
4113 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4114 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4115 if (bflags & BFLAGS_Public)
4117 } else if (bflags & BFLAGS_NonPublic) {
4118 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4119 property_accessor_nonpublic(prop->set, startklass == klass)) {
4126 if (flags & METHOD_ATTRIBUTE_STATIC) {
4127 if (bflags & BFLAGS_Static)
4128 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4131 if (bflags & BFLAGS_Instance)
4139 if (propname != NULL && compare_func (propname, prop->name))
4142 if (g_hash_table_lookup (properties, prop))
4145 g_ptr_array_add (res_array, prop);
4147 g_hash_table_insert (properties, prop, prop);
4149 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4152 g_hash_table_destroy (properties);
4159 g_hash_table_destroy (properties);
4160 g_ptr_array_free (res_array, TRUE);
4162 mono_error_set_pending_exception (&error);
4168 event_hash (gconstpointer data)
4170 MonoEvent *event = (MonoEvent*)data;
4172 return g_str_hash (event->name);
4176 event_equal (MonoEvent *event1, MonoEvent *event2)
4178 // Events are hide-by-name
4179 return g_str_equal (event1->name, event2->name);
4182 ICALL_EXPORT GPtrArray*
4183 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4186 MonoClass *startklass, *klass;
4191 int (*compare_func) (const char *s1, const char *s2) = NULL;
4192 GHashTable *events = NULL;
4193 GPtrArray *res_array;
4195 if (type->type->byref) {
4196 return g_ptr_array_new ();
4199 mono_error_init (&error);
4201 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4203 res_array = g_ptr_array_sized_new (4);
4205 klass = startklass = mono_class_from_mono_type (type->type);
4207 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4209 mono_class_setup_methods (klass);
4210 mono_class_setup_vtable (klass);
4211 if (mono_class_has_failure (klass)) {
4212 mono_error_set_for_class_failure (&error, klass);
4217 while ((event = mono_class_get_events (klass, &iter))) {
4219 method = event->add;
4221 method = event->remove;
4223 method = event->raise;
4225 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4226 if (bflags & BFLAGS_Public)
4228 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4229 if (bflags & BFLAGS_NonPublic)
4234 if (bflags & BFLAGS_NonPublic)
4240 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4241 if (bflags & BFLAGS_Static)
4242 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4245 if (bflags & BFLAGS_Instance)
4250 if (bflags & BFLAGS_Instance)
4255 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4258 if (g_hash_table_lookup (events, event))
4261 g_ptr_array_add (res_array, event);
4263 g_hash_table_insert (events, event, event);
4265 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4268 g_hash_table_destroy (events);
4274 g_hash_table_destroy (events);
4276 g_ptr_array_free (res_array, TRUE);
4278 mono_error_set_pending_exception (&error);
4282 ICALL_EXPORT GPtrArray *
4283 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4289 GPtrArray *res_array;
4291 if (type->type->byref) {
4292 return g_ptr_array_new ();
4295 klass = mono_class_from_mono_type (type->type);
4298 * If a nested type is generic, return its generic type definition.
4299 * Note that this means that the return value is essentially the set
4300 * of nested types of the generic type definition of @klass.
4302 * A note in MSDN claims that a generic type definition can have
4303 * nested types that aren't generic. In any case, the container of that
4304 * nested type would be the generic type definition.
4306 if (mono_class_is_ginst (klass))
4307 klass = mono_class_get_generic_class (klass)->container_class;
4309 res_array = g_ptr_array_new ();
4312 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4314 if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4315 if (bflags & BFLAGS_Public)
4318 if (bflags & BFLAGS_NonPublic)
4324 if (str != NULL && strcmp (nested->name, str))
4327 g_ptr_array_add (res_array, &nested->byval_arg);
4333 ICALL_EXPORT MonoReflectionType*
4334 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4337 MonoReflectionType *ret;
4339 MonoType *type = NULL;
4340 MonoTypeNameParse info;
4341 gboolean type_resolve;
4343 /* On MS.NET, this does not fire a TypeResolve event */
4344 type_resolve = TRUE;
4345 str = mono_string_to_utf8_checked (name, &error);
4346 if (mono_error_set_pending_exception (&error))
4348 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4349 if (!mono_reflection_parse_type (str, &info)) {
4351 mono_reflection_free_type_info (&info);
4353 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4356 /*g_print ("failed parse\n");*/
4360 if (info.assembly.name) {
4362 mono_reflection_free_type_info (&info);
4364 /* 1.0 and 2.0 throw different exceptions */
4365 if (mono_defaults.generic_ilist_class)
4366 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4368 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4374 if (module != NULL) {
4375 if (module->image) {
4376 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4377 if (!is_ok (&error)) {
4379 mono_reflection_free_type_info (&info);
4380 mono_error_set_pending_exception (&error);
4387 if (assembly_is_dynamic (assembly->assembly)) {
4388 /* Enumerate all modules */
4389 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4393 if (abuilder->modules) {
4394 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4395 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4396 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4397 if (!is_ok (&error)) {
4399 mono_reflection_free_type_info (&info);
4400 mono_error_set_pending_exception (&error);
4408 if (!type && abuilder->loaded_modules) {
4409 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4410 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4411 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4412 if (!is_ok (&error)) {
4414 mono_reflection_free_type_info (&info);
4415 mono_error_set_pending_exception (&error);
4424 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4425 if (!is_ok (&error)) {
4427 mono_reflection_free_type_info (&info);
4428 mono_error_set_pending_exception (&error);
4433 mono_reflection_free_type_info (&info);
4435 MonoException *e = NULL;
4438 e = mono_get_exception_type_load (name, NULL);
4441 mono_set_pending_exception (e);
4445 if (type->type == MONO_TYPE_CLASS) {
4446 MonoClass *klass = mono_type_get_class (type);
4448 /* need to report exceptions ? */
4449 if (throwOnError && mono_class_has_failure (klass)) {
4450 /* report SecurityException (or others) that occured when loading the assembly */
4451 mono_error_set_for_class_failure (&error, klass);
4452 mono_error_set_pending_exception (&error);
4457 /* g_print ("got it\n"); */
4458 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4459 mono_error_set_pending_exception (&error);
4465 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4468 gchar *shadow_ini_file;
4471 /* Check for shadow-copied assembly */
4472 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4473 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4475 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4476 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4482 g_free (shadow_ini_file);
4483 if (content != NULL) {
4486 *filename = content;
4493 ICALL_EXPORT MonoString *
4494 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4496 MonoDomain *domain = mono_object_domain (assembly);
4497 MonoAssembly *mass = assembly->assembly;
4498 MonoString *res = NULL;
4503 if (g_path_is_absolute (mass->image->name)) {
4504 absolute = g_strdup (mass->image->name);
4505 dirname = g_path_get_dirname (absolute);
4507 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4508 dirname = g_strdup (mass->basedir);
4511 replace_shadow_path (domain, dirname, &absolute);
4514 mono_icall_make_platform_path (absolute);
4517 uri = g_filename_to_uri (absolute, NULL, NULL);
4519 const gchar *prepend = mono_icall_get_file_path_prefix (absolute);
4520 uri = g_strconcat (prepend, absolute, NULL);
4524 res = mono_string_new (domain, uri);
4531 ICALL_EXPORT MonoBoolean
4532 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4534 MonoAssembly *mass = assembly->assembly;
4536 return mass->in_gac;
4539 ICALL_EXPORT MonoReflectionAssemblyHandle
4540 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoStringHandle mname, MonoObjectHandle evidence, MonoError *error)
4543 MonoImageOpenStatus status;
4544 MonoReflectionAssemblyHandle result = MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
4546 name = mono_string_handle_to_utf8 (mname, error);
4549 MonoAssembly *res = mono_assembly_load_with_partial_name (name, &status);
4555 result = mono_assembly_get_object_handle (mono_domain_get (), res, error);
4560 ICALL_EXPORT MonoStringHandle
4561 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4563 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4564 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4565 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4568 ICALL_EXPORT MonoBoolean
4569 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4571 return assembly->assembly->ref_only;
4574 ICALL_EXPORT MonoStringHandle
4575 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4577 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4578 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4580 return mono_string_new_handle (domain, assembly->image->version, error);
4583 ICALL_EXPORT MonoReflectionMethod*
4584 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4587 MonoReflectionMethod *res = NULL;
4590 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4594 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4595 if (!mono_error_ok (&error))
4598 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4601 if (!mono_error_ok (&error))
4602 mono_error_set_pending_exception (&error);
4606 ICALL_EXPORT MonoReflectionModuleHandle
4607 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssemblyHandle assembly, MonoError *error)
4609 mono_error_init (error);
4610 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
4611 MonoAssembly *a = MONO_HANDLE_GETVAL (assembly, assembly);
4612 return mono_module_get_object_handle (domain, a->image, error);
4615 ICALL_EXPORT MonoArray*
4616 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4619 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4620 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4621 if (mono_error_set_pending_exception (&error))
4626 for (i = 0; i < table->rows; ++i) {
4627 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4628 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4633 ICALL_EXPORT MonoStringHandle
4634 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4637 guint8 aotid_sum = 0;
4638 MonoDomain* domain = mono_domain_get ();
4640 if (!domain->entry_assembly || !domain->entry_assembly->image)
4643 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4645 for (i = 0; i < 16; ++i)
4646 aotid_sum |= (*aotid)[i];
4651 gchar *guid = mono_guid_to_string((guint8*) aotid);
4652 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4657 static MonoAssemblyName*
4658 create_referenced_assembly_name (MonoDomain *domain, MonoImage *image, MonoTableInfo *t, int i, MonoError *error)
4660 mono_error_init (error);
4661 MonoAssemblyName *aname = g_new0 (MonoAssemblyName, 1);
4663 mono_assembly_get_assemblyref (image, i, aname);
4664 aname->hash_alg = ASSEMBLY_HASH_SHA1 /* SHA1 (default) */;
4665 /* name and culture are pointers into the image tables, but we need
4666 * real malloc'd strings (so that we can g_free() them later from
4667 * Mono.RuntimeMarshal.FreeAssemblyName) */
4668 aname->name = g_strdup (aname->name);
4669 aname->culture = g_strdup (aname->culture);
4670 /* Don't need the hash value in managed */
4671 aname->hash_value = NULL;
4672 aname->hash_len = 0;
4673 g_assert (aname->public_key == NULL);
4675 /* note: this function doesn't return the codebase on purpose (i.e. it can
4676 be used under partial trust as path information isn't present). */
4680 ICALL_EXPORT GPtrArray*
4681 ves_icall_System_Reflection_Assembly_InternalGetReferencedAssemblies (MonoReflectionAssemblyHandle assembly, MonoError *error)
4683 mono_error_init (error);
4684 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly);
4685 MonoAssembly *ass = MONO_HANDLE_GETVAL(assembly, assembly);
4686 MonoImage *image = ass->image;
4688 MonoTableInfo *t = &image->tables [MONO_TABLE_ASSEMBLYREF];
4689 int count = t->rows;
4691 GPtrArray *result = g_ptr_array_sized_new (count);
4693 for (int i = 0; i < count; i++) {
4694 MonoAssemblyName *aname = create_referenced_assembly_name (domain, image, t, i, error);
4697 g_ptr_array_add (result, aname);
4702 /* move this in some file in mono/util/ */
4704 g_concat_dir_and_file (const char *dir, const char *file)
4706 g_return_val_if_fail (dir != NULL, NULL);
4707 g_return_val_if_fail (file != NULL, NULL);
4710 * If the directory name doesn't have a / on the end, we need
4711 * to add one so we get a proper path to the file
4713 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4714 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4716 return g_strconcat (dir, file, NULL);
4720 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, gint32 *size, MonoReflectionModuleHandleOut ref_module, MonoError *error)
4722 mono_error_init (error);
4723 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
4724 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4725 MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4727 guint32 cols [MONO_MANIFEST_SIZE];
4728 guint32 impl, file_idx;
4732 char *n = mono_string_handle_to_utf8 (name, error);
4733 return_val_if_nok (error, NULL);
4735 for (i = 0; i < table->rows; ++i) {
4736 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4737 val = mono_metadata_string_heap (assembly->image, cols [MONO_MANIFEST_NAME]);
4738 if (strcmp (val, n) == 0)
4742 if (i == table->rows)
4745 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4748 * this code should only be called after obtaining the
4749 * ResourceInfo and handling the other cases.
4751 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4752 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4754 module = mono_image_load_file_for_image_checked (assembly->image, file_idx, error);
4755 if (!is_ok (error) || !module)
4759 module = assembly->image;
4762 MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, module, error);
4765 MONO_HANDLE_ASSIGN (ref_module, rm);
4767 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4771 get_manifest_resource_info_internal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoManifestResourceInfoHandle info, MonoError *error)
4773 HANDLE_FUNCTION_ENTER ();
4774 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_h);
4775 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4776 MonoTableInfo *table = &assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4778 guint32 cols [MONO_MANIFEST_SIZE];
4779 guint32 file_cols [MONO_FILE_SIZE];
4783 gboolean result = FALSE;
4785 n = mono_string_handle_to_utf8 (name, error);
4789 for (i = 0; i < table->rows; ++i) {
4790 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4791 val = mono_metadata_string_heap (assembly->image, cols [MONO_MANIFEST_NAME]);
4792 if (strcmp (val, n) == 0)
4796 if (i == table->rows)
4799 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4800 MONO_HANDLE_SETVAL (info, location, guint32, RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST);
4803 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4804 case MONO_IMPLEMENTATION_FILE:
4805 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4806 table = &assembly->image->tables [MONO_TABLE_FILE];
4807 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4808 val = mono_metadata_string_heap (assembly->image, file_cols [MONO_FILE_NAME]);
4809 MONO_HANDLE_SET (info, filename, mono_string_new_handle (domain, val, error));
4810 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4811 MONO_HANDLE_SETVAL (info, location, guint32, 0);
4813 MONO_HANDLE_SETVAL (info, location, guint32, RESOURCE_LOCATION_EMBEDDED);
4816 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4817 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4818 mono_assembly_load_reference (assembly->image, i - 1);
4819 if (assembly->image->references [i - 1] == REFERENCE_MISSING) {
4820 mono_error_set_assembly_load (error, NULL, "Assembly %d referenced from assembly %s not found ", i - 1, assembly->image->name);
4823 MonoReflectionAssemblyHandle assm_obj = mono_assembly_get_object_handle (mono_domain_get (), assembly->image->references [i - 1], error);
4826 MONO_HANDLE_SET (info, assembly, assm_obj);
4828 /* Obtain info recursively */
4829 get_manifest_resource_info_internal (assm_obj, name, info, error);
4832 guint32 location = MONO_HANDLE_GETVAL (info, location);
4833 location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4834 MONO_HANDLE_SETVAL (info, location, guint32, location);
4837 case MONO_IMPLEMENTATION_EXP_TYPE:
4838 g_assert_not_reached ();
4845 HANDLE_FUNCTION_RETURN_VAL (result);
4848 ICALL_EXPORT gboolean
4849 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssemblyHandle assembly_h, MonoStringHandle name, MonoManifestResourceInfoHandle info_h, MonoError *error)
4851 mono_error_init (error);
4852 return get_manifest_resource_info_internal (assembly_h, name, info_h, error);
4855 ICALL_EXPORT MonoObject*
4856 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4859 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4860 MonoArray *result = NULL;
4865 /* check hash if needed */
4867 n = mono_string_to_utf8_checked (name, &error);
4868 if (mono_error_set_pending_exception (&error))
4871 for (i = 0; i < table->rows; ++i) {
4872 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4873 if (strcmp (val, n) == 0) {
4876 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4877 fn = mono_string_new (mono_object_domain (assembly), n);
4879 return (MonoObject*)fn;
4887 for (i = 0; i < table->rows; ++i) {
4888 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4892 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4893 if (mono_error_set_pending_exception (&error))
4898 for (i = 0; i < table->rows; ++i) {
4899 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4900 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4901 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4902 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4907 return (MonoObject*)result;
4911 add_module_to_modules_array (MonoDomain *domain, MonoArrayHandle dest, int *dest_idx, MonoImage* module, MonoError *error)
4913 HANDLE_FUNCTION_ENTER ();
4914 mono_error_init (error);
4916 MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, module, error);
4920 MONO_HANDLE_ARRAY_SETREF (dest, *dest_idx, rm);
4925 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
4929 add_file_to_modules_array (MonoDomain *domain, MonoArrayHandle dest, int dest_idx, MonoImage *image, MonoTableInfo *table, int table_idx, MonoError *error)
4931 HANDLE_FUNCTION_ENTER ();
4932 mono_error_init (error);
4934 guint32 cols [MONO_FILE_SIZE];
4935 mono_metadata_decode_row (table, table_idx, cols, MONO_FILE_SIZE);
4936 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
4937 MonoReflectionModuleHandle rm = mono_module_file_get_object_handle (domain, image, table_idx, error);
4940 MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rm);
4942 MonoImage *m = mono_image_load_file_for_image_checked (image, table_idx + 1, error);
4946 const char *filename = mono_metadata_string_heap (image, cols [MONO_FILE_NAME]);
4947 mono_error_set_assembly_load (error, g_strdup (filename), "%s", "");
4950 MonoReflectionModuleHandle rm = mono_module_get_object_handle (domain, m, error);
4953 MONO_HANDLE_ARRAY_SETREF (dest, dest_idx, rm);
4957 HANDLE_FUNCTION_RETURN_VAL (is_ok (error));
4960 ICALL_EXPORT MonoArrayHandle
4961 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssemblyHandle assembly_h, MonoError *error)
4963 mono_error_init (error);
4964 MonoDomain *domain = mono_domain_get();
4965 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_h, assembly);
4967 int i, j, file_count = 0;
4968 MonoImage **modules;
4969 guint32 module_count, real_module_count;
4970 MonoTableInfo *table;
4971 MonoImage *image = assembly->image;
4973 g_assert (image != NULL);
4974 g_assert (!assembly_is_dynamic (assembly));
4976 table = &image->tables [MONO_TABLE_FILE];
4977 file_count = table->rows;
4979 modules = image->modules;
4980 module_count = image->module_count;
4982 real_module_count = 0;
4983 for (i = 0; i < module_count; ++i)
4985 real_module_count ++;
4987 klass = mono_class_get_module_class ();
4988 MonoArrayHandle res = mono_array_new_handle (domain, klass, 1 + real_module_count + file_count, error);
4992 MonoReflectionModuleHandle image_obj = mono_module_get_object_handle (domain, image, error);
4996 MONO_HANDLE_ARRAY_SETREF (res, 0, image_obj);
4999 for (i = 0; i < module_count; ++i)
5000 if (!add_module_to_modules_array (domain, res, &j, modules[i], error))
5003 for (i = 0; i < file_count; ++i, ++j) {
5004 if (!add_file_to_modules_array (domain, res, j, image, table, i, error))
5010 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
5013 ICALL_EXPORT MonoReflectionMethod*
5014 ves_icall_GetCurrentMethod (void)
5016 MonoReflectionMethod *res = NULL;
5019 MonoMethod *m = mono_method_get_last_managed ();
5022 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5026 while (m->is_inflated)
5027 m = ((MonoMethodInflated*)m)->declaring;
5029 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5030 mono_error_set_pending_exception (&error);
5036 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5039 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5042 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5043 //method is inflated, we should inflate it on the other class
5044 MonoGenericContext ctx;
5045 ctx.method_inst = inflated->context.method_inst;
5046 ctx.class_inst = inflated->context.class_inst;
5047 if (mono_class_is_ginst (klass))
5048 ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
5049 else if (mono_class_is_gtd (klass))
5050 ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
5051 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5052 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5056 mono_class_setup_methods (method->klass);
5057 if (mono_class_has_failure (method->klass))
5059 int mcount = mono_class_get_method_count (method->klass);
5060 for (i = 0; i < mcount; ++i) {
5061 if (method->klass->methods [i] == method) {
5066 mono_class_setup_methods (klass);
5067 if (mono_class_has_failure (klass))
5069 g_assert (offset >= 0 && offset < mono_class_get_method_count (klass));
5070 return klass->methods [offset];
5073 ICALL_EXPORT MonoReflectionMethod*
5074 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5076 MonoReflectionMethod *res = NULL;
5079 if (type && generic_check) {
5080 klass = mono_class_from_mono_type (type);
5081 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5084 if (method->klass != klass) {
5085 method = mono_method_get_equivalent_method (method, klass);
5090 klass = mono_class_from_mono_type (type);
5092 klass = method->klass;
5093 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5094 mono_error_set_pending_exception (&error);
5098 ICALL_EXPORT MonoReflectionMethodBody*
5099 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5102 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5103 mono_error_set_pending_exception (&error);
5107 ICALL_EXPORT MonoReflectionAssemblyHandle
5108 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (MonoError *error)
5110 mono_error_init (error);
5112 MonoMethod *dest = NULL;
5113 mono_stack_walk_no_il (get_executing, &dest);
5115 return mono_assembly_get_object_handle (mono_domain_get (), dest->klass->image->assembly, error);
5119 ICALL_EXPORT MonoReflectionAssemblyHandle
5120 ves_icall_System_Reflection_Assembly_GetEntryAssembly (MonoError *error)
5122 mono_error_init (error);
5124 MonoDomain* domain = mono_domain_get ();
5126 if (!domain->entry_assembly)
5127 return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
5129 return mono_assembly_get_object_handle (domain, domain->entry_assembly, error);
5132 ICALL_EXPORT MonoReflectionAssemblyHandle
5133 ves_icall_System_Reflection_Assembly_GetCallingAssembly (MonoError *error)
5135 mono_error_init (error);
5140 mono_stack_walk_no_il (get_executing, &dest);
5142 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5146 mono_error_set_not_supported (error, "Stack walks are not supported on this platform.");
5147 return MONO_HANDLE_CAST (MonoReflectionAssembly, NULL_HANDLE);
5149 return mono_assembly_get_object_handle (mono_domain_get (), dest->klass->image->assembly, error);
5152 ICALL_EXPORT MonoStringHandle
5153 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5154 gboolean assembly_qualified, MonoError *error)
5156 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5157 MonoType *type = MONO_HANDLE_RAW (object)->type;
5158 MonoTypeNameFormat format;
5159 MonoStringHandle res;
5163 format = assembly_qualified ?
5164 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5165 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5167 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5169 name = mono_type_get_name_full (type, format);
5171 return NULL_HANDLE_STRING;
5173 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5175 return NULL_HANDLE_STRING;
5178 res = mono_string_new_handle (domain, name, error);
5185 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5188 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5190 mono_class_init_checked (klass, &error);
5191 mono_error_set_pending_exception (&error);
5192 return mono_security_core_clr_class_level (klass);
5196 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5198 MonoClassField *field = rfield->field;
5199 return mono_security_core_clr_field_level (field, TRUE);
5203 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5205 MonoMethod *method = rfield->method;
5206 return mono_security_core_clr_method_level (method, TRUE);
5209 ICALL_EXPORT MonoString *
5210 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5212 MonoDomain *domain = mono_object_domain (assembly);
5213 MonoAssembly *mass = assembly->assembly;
5217 name = mono_stringify_assembly_name (&mass->aname);
5218 res = mono_string_new (domain, name);
5224 ICALL_EXPORT MonoAssemblyName *
5225 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5227 return &mass->aname;
5231 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoStringHandle fname, MonoAssemblyName *name, MonoStringHandleOut normalized_codebase, MonoError *error)
5234 MonoImageOpenStatus status = MONO_IMAGE_OK;
5235 char *codebase = NULL;
5240 mono_error_init (error);
5242 filename = mono_string_handle_to_utf8 (fname, error);
5243 return_if_nok (error);
5245 dirname = g_path_get_dirname (filename);
5246 replace_shadow_path (mono_domain_get (), dirname, &filename);
5249 image = mono_image_open (filename, &status);
5252 if (status == MONO_IMAGE_IMAGE_INVALID)
5253 mono_error_set_bad_image_name (error, g_strdup (filename), "%s", "");
5255 mono_error_set_assembly_load (error, g_strdup (filename), "%s", "");
5260 res = mono_assembly_fill_assembly_name_full (image, name, TRUE);
5262 mono_image_close (image);
5264 mono_error_set_argument (error, "assemblyFile", "The file does not contain a manifest");
5268 if (filename != NULL && *filename != '\0') {
5271 codebase = g_strdup (filename);
5273 mono_icall_make_platform_path (codebase);
5275 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5277 result = g_strconcat (prepend, codebase, NULL);
5281 MONO_HANDLE_ASSIGN (normalized_codebase, mono_string_new_handle (mono_domain_get (), codebase, error));
5284 mono_image_close (image);
5288 ICALL_EXPORT MonoBoolean
5289 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5290 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5292 MonoBoolean result = FALSE;
5293 MonoDeclSecurityEntry entry;
5295 /* SecurityAction.RequestMinimum */
5296 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5297 *minimum = entry.blob;
5298 *minLength = entry.size;
5301 /* SecurityAction.RequestOptional */
5302 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5303 *optional = entry.blob;
5304 *optLength = entry.size;
5307 /* SecurityAction.RequestRefuse */
5308 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5309 *refused = entry.blob;
5310 *refLength = entry.size;
5318 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5320 guint32 attrs, visibility;
5322 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5323 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5324 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5327 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5333 image_get_type (MonoDomain *domain, MonoImage *image, MonoTableInfo *tdef, int table_idx, int count, MonoArrayHandle res, MonoArrayHandle exceptions, MonoBoolean exportedOnly, MonoError *error)
5335 mono_error_init (error);
5336 HANDLE_FUNCTION_ENTER ();
5337 MonoError klass_error;
5338 MonoClass *klass = mono_class_get_checked (image, table_idx | MONO_TOKEN_TYPE_DEF, &klass_error);
5341 MonoReflectionTypeHandle rt = mono_type_get_object_handle (domain, &klass->byval_arg, error);
5342 return_if_nok (error);
5344 MONO_HANDLE_ARRAY_SETREF (res, count, rt);
5346 MonoException *ex = mono_error_convert_to_exception (error);
5347 MONO_HANDLE_ARRAY_SETRAW (exceptions, count, ex);
5349 HANDLE_FUNCTION_RETURN ();
5352 static MonoArrayHandle
5353 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArrayHandleOut exceptions, MonoBoolean exportedOnly, MonoError *error)
5355 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5358 mono_error_init (error);
5360 /* we start the count from 1 because we skip the special type <Module> */
5363 for (i = 1; i < tdef->rows; ++i) {
5364 if (mono_module_type_is_visible (tdef, image, i + 1))
5368 count = tdef->rows - 1;
5370 MonoArrayHandle res = mono_array_new_handle (domain, mono_defaults.runtimetype_class, count, error);
5371 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5372 MONO_HANDLE_ASSIGN (exceptions, mono_array_new_handle (domain, mono_defaults.exception_class, count, error));
5373 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5375 for (i = 1; i < tdef->rows; ++i) {
5376 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i+1)) {
5377 image_get_type (domain, image, tdef, i + 1, count, res, exceptions, exportedOnly, error);
5378 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5387 append_module_types (MonoDomain *domain, MonoArrayHandleOut res, MonoArrayHandleOut exceptions, MonoImage *image, MonoBoolean exportedOnly, MonoError *error)
5389 HANDLE_FUNCTION_ENTER ();
5390 mono_error_init (error);
5391 MonoArrayHandle ex2 = MONO_HANDLE_NEW (MonoArray, NULL);
5392 MonoArrayHandle res2 = mono_module_get_types (domain, image, ex2, exportedOnly, error);
5396 /* Append the new types to the end of the array */
5397 if (mono_array_handle_length (res2) > 0) {
5400 len1 = mono_array_handle_length (res);
5401 len2 = mono_array_handle_length (res2);
5403 MonoArrayHandle res3 = mono_array_new_handle (domain, mono_defaults.runtimetype_class, len1 + len2, error);
5407 mono_array_handle_memcpy_refs (res3, 0, res, 0, len1);
5408 mono_array_handle_memcpy_refs (res3, len1, res2, 0, len2);
5409 MONO_HANDLE_ASSIGN (res, res3);
5411 MonoArrayHandle ex3 = mono_array_new_handle (domain, mono_defaults.runtimetype_class, len1 + len2, error);
5415 mono_array_handle_memcpy_refs (ex3, 0, exceptions, 0, len1);
5416 mono_array_handle_memcpy_refs (ex3, len1, ex2, 0, len2);
5417 MONO_HANDLE_ASSIGN (exceptions, ex3);
5420 HANDLE_FUNCTION_RETURN ();
5424 set_class_failure_in_array (MonoArrayHandle exl, int i, MonoClass *klass)
5426 HANDLE_FUNCTION_ENTER ();
5427 MonoError unboxed_error;
5428 mono_error_init (&unboxed_error);
5429 mono_error_set_for_class_failure (&unboxed_error, klass);
5431 MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, mono_error_convert_to_exception (&unboxed_error));
5432 MONO_HANDLE_ARRAY_SETREF (exl, i, exc);
5433 HANDLE_FUNCTION_RETURN ();
5436 ICALL_EXPORT MonoArrayHandle
5437 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssemblyHandle assembly_handle, MonoBoolean exportedOnly, MonoError *error)
5439 MonoArrayHandle exceptions = MONO_HANDLE_NEW(MonoArray, NULL);
5442 MonoDomain *domain = MONO_HANDLE_DOMAIN (assembly_handle);
5443 MonoAssembly *assembly = MONO_HANDLE_GETVAL (assembly_handle, assembly);
5445 g_assert (!assembly_is_dynamic (assembly));
5446 MonoImage *image = assembly->image;
5447 MonoTableInfo *table = &image->tables [MONO_TABLE_FILE];
5448 MonoArrayHandle res = mono_module_get_types (domain, image, exceptions, exportedOnly, error);
5449 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5451 /* Append data from all modules in the assembly */
5452 for (i = 0; i < table->rows; ++i) {
5453 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5454 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, error);
5455 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5458 append_module_types (domain, res, exceptions, loaded_image, exportedOnly, error);
5459 return_val_if_nok (error, MONO_HANDLE_CAST (MonoArray, NULL_HANDLE));
5464 /* the ReflectionTypeLoadException must have all the types (Types property),
5465 * NULL replacing types which throws an exception. The LoaderException must
5466 * contain all exceptions for NULL items.
5469 int len = mono_array_handle_length (res);
5473 MonoReflectionTypeHandle t = MONO_HANDLE_NEW (MonoReflectionType, NULL);
5474 for (i = 0; i < len; i++) {
5475 MONO_HANDLE_ARRAY_GETREF (t, res, i);
5477 if (!MONO_HANDLE_IS_NULL (t)) {
5478 MonoClass *klass = mono_type_get_class (MONO_HANDLE_GETVAL (t, type));
5479 if ((klass != NULL) && mono_class_has_failure (klass)) {
5480 /* keep the class in the list */
5481 list = g_list_append (list, klass);
5482 /* and replace Type with NULL */
5483 MONO_HANDLE_ARRAY_SETRAW (res, i, NULL);
5490 if (list || ex_count) {
5492 int j, length = g_list_length (list) + ex_count;
5494 MonoArrayHandle exl = mono_array_new_handle (domain, mono_defaults.exception_class, length, error);
5495 if (!is_ok (error)) {
5497 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
5499 /* Types for which mono_class_get_checked () succeeded */
5500 MonoExceptionHandle exc = MONO_HANDLE_NEW (MonoException, NULL);
5501 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5502 set_class_failure_in_array (exl, i, (MonoClass*)tmp->data);
5504 /* Types for which it don't */
5505 for (j = 0; j < mono_array_handle_length (exceptions); ++j) {
5506 MONO_HANDLE_ARRAY_GETREF (exc, exceptions, j);
5507 if (!MONO_HANDLE_IS_NULL (exc)) {
5508 g_assert (i < length);
5509 MONO_HANDLE_ARRAY_SETREF (exl, i, exc);
5516 MONO_HANDLE_ASSIGN (exc, mono_get_exception_reflection_type_load_checked (res, exl, error));
5517 if (!is_ok (error)) {
5518 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
5520 mono_error_set_exception_handle (error, exc);
5521 return MONO_HANDLE_CAST (MonoArray, NULL_HANDLE);
5528 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname, gboolean free_struct)
5530 mono_assembly_name_free (aname);
5535 ICALL_EXPORT gboolean
5536 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5538 *is_version_definited = *is_token_defined = FALSE;
5540 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5543 ICALL_EXPORT MonoReflectionTypeHandle
5544 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModuleHandle module, MonoError *error)
5546 MonoDomain *domain = MONO_HANDLE_DOMAIN (module);
5547 MonoImage *image = MONO_HANDLE_GETVAL (module, image);
5552 MonoReflectionTypeHandle ret = MONO_HANDLE_CAST (MonoReflectionType, NULL_HANDLE);
5554 if (image_is_dynamic (image) && ((MonoDynamicImage*)image)->initial_image)
5555 /* These images do not have a global type */
5558 klass = mono_class_get_checked (image, 1 | MONO_TOKEN_TYPE_DEF, error);
5562 ret = mono_type_get_object_handle (domain, &klass->byval_arg, error);
5568 ves_icall_System_Reflection_Module_Close (MonoReflectionModuleHandle module, MonoError *error)
5570 /*if (module->image)
5571 mono_image_close (module->image);*/
5574 ICALL_EXPORT MonoStringHandle
5575 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5577 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5578 MonoImage *image = MONO_HANDLE_GETVAL (refmodule, image);
5581 return mono_string_new_handle (domain, image->guid, error);
5585 static inline gpointer
5586 mono_icall_module_get_hinstance (MonoReflectionModuleHandle module)
5588 return (gpointer) (-1);
5590 #endif /* HOST_WIN32 */
5592 ICALL_EXPORT gpointer
5593 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModuleHandle module, MonoError *error)
5595 return mono_icall_module_get_hinstance (module);
5599 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine, MonoError *error)
5601 if (image_is_dynamic (image)) {
5602 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5603 *pe_kind = dyn->pe_kind;
5604 *machine = dyn->machine;
5607 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5608 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5613 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image, MonoError *error)
5615 return (image->md_version_major << 16) | (image->md_version_minor);
5618 ICALL_EXPORT MonoArrayHandle
5619 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModuleHandle module, MonoError *error)
5621 mono_error_init (error);
5623 MonoImage *image = MONO_HANDLE_GETVAL (module, image);
5624 MonoDomain *domain = MONO_HANDLE_DOMAIN (module);
5627 MonoArrayHandle arr = mono_array_new_handle (domain, mono_defaults.runtimetype_class, 0, error);
5630 MonoArrayHandle exceptions = MONO_HANDLE_NEW (MonoArray, NULL);
5631 MonoArrayHandle res = mono_module_get_types (domain, image, exceptions, FALSE, error);
5632 return_val_if_nok (error, MONO_HANDLE_CAST(MonoArray, NULL_HANDLE));
5634 int n = mono_array_handle_length (exceptions);
5635 MonoExceptionHandle ex = MONO_HANDLE_NEW (MonoException, NULL);
5636 for (int i = 0; i < n; ++i) {
5637 MONO_HANDLE_ARRAY_GETREF(ex, exceptions, i);
5638 if (!MONO_HANDLE_IS_NULL (ex)) {
5639 mono_error_set_exception_handle (error, ex);
5640 return MONO_HANDLE_CAST(MonoArray, NULL_HANDLE);
5648 mono_memberref_is_method (MonoImage *image, guint32 token)
5650 if (!image_is_dynamic (image)) {
5651 guint32 cols [MONO_MEMBERREF_SIZE];
5653 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5654 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5655 mono_metadata_decode_blob_size (sig, &sig);
5656 return (*sig != 0x6);
5659 MonoClass *handle_class;
5661 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5662 mono_error_cleanup (&error); /* just probing, ignore error */
5666 return mono_defaults.methodhandle_class == handle_class;
5671 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5674 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5675 mono_array_addr (type_args, MonoType*, 0));
5677 context->class_inst = NULL;
5679 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5680 mono_array_addr (method_args, MonoType*, 0));
5682 context->method_inst = NULL;
5685 ICALL_EXPORT MonoType*
5686 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5689 int table = mono_metadata_token_table (token);
5690 int index = mono_metadata_token_index (token);
5691 MonoGenericContext context;
5694 *resolve_error = ResolveTokenError_Other;
5696 /* Validate token */
5697 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5698 (table != MONO_TABLE_TYPESPEC)) {
5699 *resolve_error = ResolveTokenError_BadTable;
5703 if (image_is_dynamic (image)) {
5704 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5705 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5706 mono_error_cleanup (&error);
5707 return klass ? &klass->byval_arg : NULL;
5710 init_generic_context_from_args (&context, type_args, method_args);
5711 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5712 mono_error_cleanup (&error);
5713 return klass ? &klass->byval_arg : NULL;
5716 if ((index <= 0) || (index > image->tables [table].rows)) {
5717 *resolve_error = ResolveTokenError_OutOfRange;
5721 init_generic_context_from_args (&context, type_args, method_args);
5722 klass = mono_class_get_checked (image, token, &error);
5724 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5725 if (!mono_error_ok (&error)) {
5726 mono_error_set_pending_exception (&error);
5731 return &klass->byval_arg;
5736 ICALL_EXPORT MonoMethod*
5737 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5740 int table = mono_metadata_token_table (token);
5741 int index = mono_metadata_token_index (token);
5742 MonoGenericContext context;
5745 *resolve_error = ResolveTokenError_Other;
5747 /* Validate token */
5748 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5749 (table != MONO_TABLE_MEMBERREF)) {
5750 *resolve_error = ResolveTokenError_BadTable;
5754 if (image_is_dynamic (image)) {
5755 if (table == MONO_TABLE_METHOD) {
5756 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5757 mono_error_cleanup (&error);
5761 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5762 *resolve_error = ResolveTokenError_BadTable;
5766 init_generic_context_from_args (&context, type_args, method_args);
5767 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5768 mono_error_cleanup (&error);
5772 if ((index <= 0) || (index > image->tables [table].rows)) {
5773 *resolve_error = ResolveTokenError_OutOfRange;
5776 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5777 *resolve_error = ResolveTokenError_BadTable;
5781 init_generic_context_from_args (&context, type_args, method_args);
5782 method = mono_get_method_checked (image, token, NULL, &context, &error);
5783 mono_error_set_pending_exception (&error);
5788 ICALL_EXPORT MonoString*
5789 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5792 int index = mono_metadata_token_index (token);
5794 *resolve_error = ResolveTokenError_Other;
5796 /* Validate token */
5797 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5798 *resolve_error = ResolveTokenError_BadTable;
5802 if (image_is_dynamic (image)) {
5803 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5804 mono_error_cleanup (&error);
5808 if ((index <= 0) || (index >= image->heap_us.size)) {
5809 *resolve_error = ResolveTokenError_OutOfRange;
5813 /* FIXME: What to do if the index points into the middle of a string ? */
5815 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5816 mono_error_set_pending_exception (&error);
5820 ICALL_EXPORT MonoClassField*
5821 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5825 int table = mono_metadata_token_table (token);
5826 int index = mono_metadata_token_index (token);
5827 MonoGenericContext context;
5828 MonoClassField *field;
5830 *resolve_error = ResolveTokenError_Other;
5832 /* Validate token */
5833 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5834 *resolve_error = ResolveTokenError_BadTable;
5838 if (image_is_dynamic (image)) {
5839 if (table == MONO_TABLE_FIELD) {
5840 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5841 mono_error_cleanup (&error);
5845 if (mono_memberref_is_method (image, token)) {
5846 *resolve_error = ResolveTokenError_BadTable;
5850 init_generic_context_from_args (&context, type_args, method_args);
5851 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5852 mono_error_cleanup (&error);
5856 if ((index <= 0) || (index > image->tables [table].rows)) {
5857 *resolve_error = ResolveTokenError_OutOfRange;
5860 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5861 *resolve_error = ResolveTokenError_BadTable;
5865 init_generic_context_from_args (&context, type_args, method_args);
5866 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5867 mono_error_set_pending_exception (&error);
5873 ICALL_EXPORT MonoObject*
5874 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5878 int table = mono_metadata_token_table (token);
5880 *error = ResolveTokenError_Other;
5883 case MONO_TABLE_TYPEDEF:
5884 case MONO_TABLE_TYPEREF:
5885 case MONO_TABLE_TYPESPEC: {
5886 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5888 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5889 mono_error_set_pending_exception (&merror);
5896 case MONO_TABLE_METHOD:
5897 case MONO_TABLE_METHODSPEC: {
5898 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5900 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5901 mono_error_set_pending_exception (&merror);
5907 case MONO_TABLE_FIELD: {
5908 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5910 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5911 mono_error_set_pending_exception (&merror);
5917 case MONO_TABLE_MEMBERREF:
5918 if (mono_memberref_is_method (image, token)) {
5919 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5921 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5922 mono_error_set_pending_exception (&merror);
5929 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5931 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5932 mono_error_set_pending_exception (&merror);
5941 *error = ResolveTokenError_BadTable;
5947 ICALL_EXPORT MonoArray*
5948 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5951 int table = mono_metadata_token_table (token);
5952 int idx = mono_metadata_token_index (token);
5953 MonoTableInfo *tables = image->tables;
5958 *resolve_error = ResolveTokenError_OutOfRange;
5960 /* FIXME: Support other tables ? */
5961 if (table != MONO_TABLE_STANDALONESIG)
5964 if (image_is_dynamic (image))
5967 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5970 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5972 ptr = mono_metadata_blob_heap (image, sig);
5973 len = mono_metadata_decode_blob_size (ptr, &ptr);
5975 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
5976 if (mono_error_set_pending_exception (&error))
5978 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5982 ICALL_EXPORT MonoBoolean
5983 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
5989 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5995 check_for_invalid_type (MonoClass *klass, MonoError *error)
5999 mono_error_init (error);
6001 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6004 name = mono_type_get_full_name (klass);
6005 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6007 ICALL_EXPORT MonoReflectionType *
6008 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6011 MonoReflectionType *ret;
6012 MonoClass *klass, *aklass;
6014 klass = mono_class_from_mono_type (type->type);
6015 check_for_invalid_type (klass, &error);
6016 if (mono_error_set_pending_exception (&error))
6019 if (rank == 0) //single dimentional array
6020 aklass = mono_array_class_get (klass, 1);
6022 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6024 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6025 mono_error_set_pending_exception (&error);
6030 ICALL_EXPORT MonoReflectionType *
6031 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6034 MonoReflectionType *ret;
6037 klass = mono_class_from_mono_type (type->type);
6038 mono_class_init_checked (klass, &error);
6039 if (mono_error_set_pending_exception (&error))
6042 check_for_invalid_type (klass, &error);
6043 if (mono_error_set_pending_exception (&error))
6046 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6047 mono_error_set_pending_exception (&error);
6052 ICALL_EXPORT MonoReflectionType *
6053 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6056 MonoReflectionType *ret;
6057 MonoClass *klass, *pklass;
6059 klass = mono_class_from_mono_type (type->type);
6060 mono_class_init_checked (klass, &error);
6061 if (mono_error_set_pending_exception (&error))
6063 check_for_invalid_type (klass, &error);
6064 if (mono_error_set_pending_exception (&error))
6067 pklass = mono_ptr_class_get (type->type);
6069 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6070 mono_error_set_pending_exception (&error);
6075 ICALL_EXPORT MonoObject *
6076 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6077 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6080 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6081 MonoObject *delegate;
6083 MonoMethod *method = info->method;
6084 MonoMethodSignature *sig = mono_method_signature(method);
6086 mono_class_init_checked (delegate_class, &error);
6087 if (mono_error_set_pending_exception (&error))
6090 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6091 /* FIXME improve this exception message */
6092 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6094 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6095 mono_error_set_pending_exception (&error);
6099 if (mono_security_core_clr_enabled ()) {
6100 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6101 if (throwOnBindFailure)
6102 mono_error_set_pending_exception (&error);
6104 mono_error_cleanup (&error);
6109 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6110 if (!method->is_inflated) {
6111 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"));
6116 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6117 if (mono_error_set_pending_exception (&error))
6120 if (method_is_dynamic (method)) {
6121 /* Creating a trampoline would leak memory */
6122 func = mono_compile_method_checked (method, &error);
6123 if (mono_error_set_pending_exception (&error))
6126 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6127 method = mono_object_get_virtual_method (target, method);
6128 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6129 if (mono_error_set_pending_exception (&error))
6131 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6134 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6135 if (mono_error_set_pending_exception (&error))
6140 ICALL_EXPORT MonoMulticastDelegate *
6141 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6144 MonoMulticastDelegate *ret;
6146 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6148 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6149 if (mono_error_set_pending_exception (&error))
6152 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6157 ICALL_EXPORT MonoReflectionMethod*
6158 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6160 MonoReflectionMethod *ret = NULL;
6162 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6163 mono_error_set_pending_exception (&error);
6169 static inline gint32
6170 mono_array_get_byte_length (MonoArray *array)
6176 klass = array->obj.vtable->klass;
6178 if (array->bounds == NULL)
6179 length = array->max_length;
6182 for (i = 0; i < klass->rank; ++ i)
6183 length *= array->bounds [i].length;
6186 switch (klass->element_class->byval_arg.type) {
6189 case MONO_TYPE_BOOLEAN:
6193 case MONO_TYPE_CHAR:
6201 return length * sizeof (gpointer);
6212 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6214 return mono_array_get_byte_length (array);
6218 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6220 return mono_array_get (array, gint8, idx);
6224 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6226 mono_array_set (array, gint8, idx, value);
6229 ICALL_EXPORT MonoBoolean
6230 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6232 guint8 *src_buf, *dest_buf;
6235 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6239 g_assert (count >= 0);
6241 /* This is called directly from the class libraries without going through the managed wrapper */
6242 MONO_CHECK_ARG_NULL (src, FALSE);
6243 MONO_CHECK_ARG_NULL (dest, FALSE);
6245 /* watch out for integer overflow */
6246 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6249 src_buf = (guint8 *)src->vector + src_offset;
6250 dest_buf = (guint8 *)dest->vector + dest_offset;
6253 memcpy (dest_buf, src_buf, count);
6255 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6260 #ifndef DISABLE_REMOTING
6261 ICALL_EXPORT MonoObject *
6262 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6265 MonoDomain *domain = mono_object_domain (this_obj);
6267 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6268 MonoTransparentProxy *tp;
6272 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6273 if (mono_error_set_pending_exception (&error))
6276 tp = (MonoTransparentProxy*) res;
6278 MONO_OBJECT_SETREF (tp, rp, rp);
6279 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6280 klass = mono_class_from_mono_type (type);
6282 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6283 mono_class_setup_vtable (klass);
6284 if (mono_class_has_failure (klass)) {
6285 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6289 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6290 if (mono_error_set_pending_exception (&error))
6292 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6293 if (mono_error_set_pending_exception (&error))
6296 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6297 if (mono_error_set_pending_exception (&error))
6302 ICALL_EXPORT MonoReflectionType *
6303 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6306 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6307 mono_error_set_pending_exception (&error);
6313 /* System.Environment */
6316 ves_icall_System_Environment_get_UserName (void)
6318 /* using glib is more portable */
6319 return mono_string_new (mono_domain_get (), g_get_user_name ());
6324 mono_icall_get_machine_name (void)
6326 #if !defined(DISABLE_SOCKETS)
6330 #if defined _SC_HOST_NAME_MAX
6331 n = sysconf (_SC_HOST_NAME_MAX);
6335 buf = g_malloc (n+1);
6337 if (gethostname (buf, n) == 0){
6339 result = mono_string_new (mono_domain_get (), buf);
6346 return mono_string_new (mono_domain_get (), "mono");
6349 #endif /* !HOST_WIN32 */
6351 ICALL_EXPORT MonoString *
6352 ves_icall_System_Environment_get_MachineName (void)
6354 return mono_icall_get_machine_name ();
6359 mono_icall_get_platform (void)
6361 #if defined(__MACH__)
6364 // Notice that the value is hidden from user code, and only exposed
6365 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6366 // define and making assumptions based on Unix/128/4 values before there
6367 // was a MacOS define. Lots of code would assume that not-Unix meant
6368 // Windows, but in this case, it would be OSX.
6376 #endif /* !HOST_WIN32 */
6379 ves_icall_System_Environment_get_Platform (void)
6381 return mono_icall_get_platform ();
6385 static inline MonoString *
6386 mono_icall_get_new_line (void)
6388 return mono_string_new (mono_domain_get (), "\n");
6390 #endif /* !HOST_WIN32 */
6392 ICALL_EXPORT MonoString *
6393 ves_icall_System_Environment_get_NewLine (void)
6395 return mono_icall_get_new_line ();
6399 static inline MonoBoolean
6400 mono_icall_is_64bit_os (void)
6402 #if SIZEOF_VOID_P == 8
6405 #if defined(HAVE_SYS_UTSNAME_H)
6406 struct utsname name;
6408 if (uname (&name) >= 0) {
6409 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6415 #endif /* !HOST_WIN32 */
6417 ICALL_EXPORT MonoBoolean
6418 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6420 return mono_icall_is_64bit_os ();
6423 ICALL_EXPORT MonoStringHandle
6424 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6428 if (utf8_name == NULL)
6429 return NULL_HANDLE_STRING;
6431 value = g_getenv (utf8_name);
6434 return NULL_HANDLE_STRING;
6436 return mono_string_new_handle (mono_domain_get (), value, error);
6440 * There is no standard way to get at environ.
6443 #ifndef __MINGW32_VERSION
6444 #if defined(__APPLE__)
6445 #if defined (TARGET_OSX)
6446 /* Apple defines this in crt_externs.h but doesn't provide that header for
6447 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6448 * in fact exist on all implementations (so far)
6450 gchar ***_NSGetEnviron(void);
6451 #define environ (*_NSGetEnviron())
6453 static char *mono_environ[1] = { NULL };
6454 #define environ mono_environ
6455 #endif /* defined (TARGET_OSX) */
6463 ICALL_EXPORT MonoArray *
6464 ves_icall_System_Environment_GetCoomandLineArgs (void)
6467 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6468 mono_error_set_pending_exception (&error);
6474 mono_icall_get_environment_variable_names (void)
6484 for (e = environ; *e != 0; ++ e)
6487 domain = mono_domain_get ();
6488 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6489 if (mono_error_set_pending_exception (&error))
6493 for (e = environ; *e != 0; ++ e) {
6494 parts = g_strsplit (*e, "=", 2);
6496 str = mono_string_new (domain, *parts);
6497 mono_array_setref (names, n, str);
6507 #endif /* !HOST_WIN32 */
6509 ICALL_EXPORT MonoArray *
6510 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6512 return mono_icall_get_environment_variable_names ();
6517 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6519 gchar *utf8_name, *utf8_value;
6522 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6523 if (mono_error_set_pending_exception (&error))
6526 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6527 g_unsetenv (utf8_name);
6532 utf8_value = mono_string_to_utf8_checked (value, &error);
6533 if (!mono_error_ok (&error)) {
6535 mono_error_set_pending_exception (&error);
6538 g_setenv (utf8_name, utf8_value, TRUE);
6541 g_free (utf8_value);
6543 #endif /* !HOST_WIN32 */
6546 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6548 mono_icall_set_environment_variable (name, value);
6552 ves_icall_System_Environment_Exit (int result)
6554 mono_environment_exitcode_set (result);
6556 /* FIXME: There are some cleanup hangs that should be worked out, but
6557 * if the program is going to exit, everything will be cleaned up when
6558 * NaCl exits anyway.
6560 #ifndef __native_client__
6561 if (!mono_runtime_try_shutdown ())
6562 mono_thread_exit ();
6564 /* Suspend all managed threads since the runtime is going away */
6565 mono_thread_suspend_all_other_threads ();
6567 mono_runtime_quit ();
6570 /* we may need to do some cleanup here... */
6574 ICALL_EXPORT MonoStringHandle
6575 ves_icall_System_Environment_GetGacPath (MonoError *error)
6577 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6581 static inline MonoString *
6582 mono_icall_get_windows_folder_path (int folder)
6584 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6585 return mono_string_new (mono_domain_get (), "");
6587 #endif /* !HOST_WIN32 */
6589 ICALL_EXPORT MonoString*
6590 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6592 return mono_icall_get_windows_folder_path (folder);
6595 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6597 mono_icall_get_logical_drives (void)
6600 gunichar2 buf [256], *ptr, *dname;
6602 guint initial_size = 127, size = 128;
6605 MonoString *drivestr;
6606 MonoDomain *domain = mono_domain_get ();
6612 while (size > initial_size) {
6613 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6614 if (size > initial_size) {
6617 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6618 initial_size = size;
6632 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6633 if (mono_error_set_pending_exception (&error))
6640 while (*u16) { u16++; len ++; }
6641 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6642 if (mono_error_set_pending_exception (&error))
6645 mono_array_setref (result, ndrives++, drivestr);
6655 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6657 ICALL_EXPORT MonoArray *
6658 ves_icall_System_Environment_GetLogicalDrives (void)
6660 return mono_icall_get_logical_drives ();
6663 ICALL_EXPORT MonoString *
6664 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6667 gunichar2 volume_name [MAX_PATH + 1];
6669 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6671 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6672 mono_error_set_pending_exception (&error);
6676 ICALL_EXPORT MonoStringHandle
6677 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6679 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6682 static const char *encodings [] = {
6684 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6685 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6686 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6688 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6689 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6690 "x_unicode_2_0_utf_7",
6692 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6693 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6695 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6698 "unicodefffe", "utf_16be",
6705 * Returns the internal codepage, if the value of "int_code_page" is
6706 * 1 at entry, and we can not compute a suitable code page number,
6707 * returns the code page as a string
6709 ICALL_EXPORT MonoString*
6710 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6715 char *codepage = NULL;
6717 int want_name = *int_code_page;
6720 *int_code_page = -1;
6722 g_get_charset (&cset);
6723 c = codepage = g_strdup (cset);
6724 for (c = codepage; *c; c++){
6725 if (isascii (*c) && isalpha (*c))
6730 /* g_print ("charset: %s\n", cset); */
6732 /* handle some common aliases */
6735 for (i = 0; p != 0; ){
6738 p = encodings [++i];
6741 if (strcmp (p, codepage) == 0){
6742 *int_code_page = code;
6745 p = encodings [++i];
6748 if (strstr (codepage, "utf_8") != NULL)
6749 *int_code_page |= 0x10000000;
6752 if (want_name && *int_code_page == -1)
6753 return mono_string_new (mono_domain_get (), cset);
6758 ICALL_EXPORT MonoBoolean
6759 ves_icall_System_Environment_get_HasShutdownStarted (void)
6761 if (mono_runtime_is_shutting_down ())
6764 if (mono_domain_is_unloading (mono_domain_get ()))
6772 mono_icall_broadcast_setting_change (void)
6776 #endif /* !HOST_WIN32 */
6779 ves_icall_System_Environment_BroadcastSettingChange (void)
6781 mono_icall_broadcast_setting_change ();
6786 ves_icall_System_Environment_get_TickCount (void)
6788 /* this will overflow after ~24 days */
6789 return (gint32) (mono_msec_boottime () & 0xffffffff);
6793 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6798 #ifndef DISABLE_REMOTING
6799 ICALL_EXPORT MonoBoolean
6800 ves_icall_IsTransparentProxy (MonoObject *proxy)
6805 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6811 ICALL_EXPORT MonoReflectionMethod *
6812 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6813 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6815 MonoReflectionMethod *ret = NULL;
6820 MonoMethod **vtable;
6821 MonoMethod *res = NULL;
6823 MONO_CHECK_ARG_NULL (rtype, NULL);
6824 MONO_CHECK_ARG_NULL (rmethod, NULL);
6826 method = rmethod->method;
6827 klass = mono_class_from_mono_type (rtype->type);
6828 mono_class_init_checked (klass, &error);
6829 if (mono_error_set_pending_exception (&error))
6832 if (MONO_CLASS_IS_INTERFACE (klass))
6835 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6838 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6839 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6845 mono_class_setup_vtable (klass);
6846 vtable = klass->vtable;
6848 if (mono_class_is_interface (method->klass)) {
6849 gboolean variance_used = FALSE;
6850 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6851 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6853 res = vtable [offs + method->slot];
6855 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6858 if (method->slot != -1)
6859 res = vtable [method->slot];
6865 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
6866 mono_error_set_pending_exception (&error);
6871 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6877 klass = mono_class_from_mono_type (type->type);
6878 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
6879 if (!is_ok (&error)) {
6880 mono_error_set_pending_exception (&error);
6884 mono_vtable_set_is_remote (vtable, enable);
6887 #else /* DISABLE_REMOTING */
6890 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6892 g_assert_not_reached ();
6897 ICALL_EXPORT MonoObject *
6898 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6905 domain = mono_object_domain (type);
6906 klass = mono_class_from_mono_type (type->type);
6907 mono_class_init_checked (klass, &error);
6908 if (mono_error_set_pending_exception (&error))
6911 if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
6912 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6916 if (klass->rank >= 1) {
6917 g_assert (klass->rank == 1);
6918 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
6919 mono_error_set_pending_exception (&error);
6922 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
6923 if (!is_ok (&error)) {
6924 mono_error_set_pending_exception (&error);
6927 /* Bypass remoting object creation check */
6928 ret = mono_object_new_alloc_specific_checked (vtable, &error);
6929 mono_error_set_pending_exception (&error);
6935 ICALL_EXPORT MonoStringHandle
6936 ves_icall_System_IO_get_temp_path (MonoError *error)
6938 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
6941 #ifndef PLATFORM_NO_DRIVEINFO
6942 ICALL_EXPORT MonoBoolean
6943 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6944 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6948 ULARGE_INTEGER wapi_free_bytes_avail;
6949 ULARGE_INTEGER wapi_total_number_of_bytes;
6950 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6952 *error = ERROR_SUCCESS;
6953 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6954 &wapi_total_number_of_free_bytes);
6957 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6958 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6959 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6961 *free_bytes_avail = 0;
6962 *total_number_of_bytes = 0;
6963 *total_number_of_free_bytes = 0;
6964 *error = GetLastError ();
6970 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6971 static inline guint32
6972 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
6974 return GetDriveType (mono_string_chars (root_path_name));
6976 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6978 ICALL_EXPORT guint32
6979 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6981 return mono_icall_drive_info_get_drive_type (root_path_name);
6984 #endif /* PLATFORM_NO_DRIVEINFO */
6986 ICALL_EXPORT gpointer
6987 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
6990 gpointer result = mono_compile_method_checked (method, &error);
6991 mono_error_set_pending_exception (&error);
6995 ICALL_EXPORT MonoString *
6996 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7001 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7003 mono_icall_make_platform_path (path);
7005 mcpath = mono_string_new (mono_domain_get (), path);
7011 /* this is an icall */
7013 get_bundled_app_config (void)
7016 const gchar *app_config;
7019 gchar *config_file_name, *config_file_path;
7020 gsize len, config_file_path_length, config_ext_length;
7023 domain = mono_domain_get ();
7024 file = domain->setup->configuration_file;
7025 if (!file || file->length == 0)
7028 // Retrieve config file and remove the extension
7029 config_file_name = mono_string_to_utf8_checked (file, &error);
7030 if (mono_error_set_pending_exception (&error))
7032 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7033 if (!config_file_path)
7034 config_file_path = config_file_name;
7036 config_file_path_length = strlen (config_file_path);
7037 config_ext_length = strlen (".config");
7038 if (config_file_path_length <= config_ext_length)
7041 len = config_file_path_length - config_ext_length;
7042 module = (gchar *)g_malloc0 (len + 1);
7043 memcpy (module, config_file_path, len);
7044 // Get the config file from the module name
7045 app_config = mono_config_string_for_assembly_file (module);
7048 if (config_file_name != config_file_path)
7049 g_free (config_file_name);
7050 g_free (config_file_path);
7055 return mono_string_new (mono_domain_get (), app_config);
7058 static MonoStringHandle
7059 get_bundled_machine_config (MonoError *error)
7061 const gchar *machine_config;
7063 machine_config = mono_get_machine_config ();
7065 if (!machine_config)
7066 return NULL_HANDLE_STRING;
7068 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7071 ICALL_EXPORT MonoStringHandle
7072 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7074 return get_bundled_machine_config (error);
7078 ICALL_EXPORT MonoStringHandle
7079 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7081 return get_bundled_machine_config (error);
7084 ICALL_EXPORT MonoStringHandle
7085 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7087 return get_bundled_machine_config (error);
7091 ICALL_EXPORT MonoString *
7092 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7097 path = g_path_get_dirname (mono_get_config_dir ());
7099 mono_icall_make_platform_path (path);
7101 ipath = mono_string_new (mono_domain_get (), path);
7107 ICALL_EXPORT gboolean
7108 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7110 MonoPEResourceDataEntry *entry;
7113 if (!assembly || !result || !size)
7118 image = assembly->assembly->image;
7119 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7123 *result = mono_image_rva_map (image, entry->rde_data_offset);
7128 *size = entry->rde_size;
7133 ICALL_EXPORT MonoBoolean
7134 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7136 return mono_is_debugger_attached ();
7139 ICALL_EXPORT MonoBoolean
7140 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7142 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7143 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7149 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7151 if (mono_get_runtime_callbacks ()->debug_log)
7152 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7157 mono_icall_write_windows_debug_string (MonoString *message)
7159 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7161 #endif /* !HOST_WIN32 */
7164 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7166 mono_icall_write_windows_debug_string (message);
7169 /* Only used for value types */
7170 ICALL_EXPORT MonoObject *
7171 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7178 domain = mono_object_domain (type);
7179 klass = mono_class_from_mono_type (type->type);
7180 mono_class_init_checked (klass, &error);
7181 if (mono_error_set_pending_exception (&error))
7184 if (mono_class_is_nullable (klass))
7185 /* No arguments -> null */
7188 result = mono_object_new_checked (domain, klass, &error);
7189 mono_error_set_pending_exception (&error);
7193 ICALL_EXPORT MonoReflectionMethod *
7194 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7196 MonoReflectionMethod *ret = NULL;
7199 MonoClass *klass, *parent;
7200 MonoGenericContext *generic_inst = NULL;
7201 MonoMethod *method = m->method;
7202 MonoMethod *result = NULL;
7205 if (method->klass == NULL)
7208 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7209 MONO_CLASS_IS_INTERFACE (method->klass) ||
7210 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7213 slot = mono_method_get_vtable_slot (method);
7217 klass = method->klass;
7218 if (mono_class_is_ginst (klass)) {
7219 generic_inst = mono_class_get_context (klass);
7220 klass = mono_class_get_generic_class (klass)->container_class;
7225 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7226 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7227 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7228 or klass is the generic container class and generic_inst is the instantiation.
7230 when we go to the parent, if the parent is an open constructed type, we need to
7231 replace the type parameters by the definitions from the generic_inst, and then take it
7232 apart again into the klass and the generic_inst.
7234 For cases like this:
7235 class C<T> : B<T, int> {
7236 public override void Foo () { ... }
7238 class B<U,V> : A<HashMap<U,V>> {
7239 public override void Foo () { ... }
7242 public virtual void Foo () { ... }
7245 if at each iteration the parent isn't open, we can skip inflating it. if at some
7246 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7249 MonoGenericContext *parent_inst = NULL;
7250 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7251 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7252 if (!mono_error_ok (&error)) {
7253 mono_error_set_pending_exception (&error);
7257 if (mono_class_is_ginst (parent)) {
7258 parent_inst = mono_class_get_context (parent);
7259 parent = mono_class_get_generic_class (parent)->container_class;
7262 mono_class_setup_vtable (parent);
7263 if (parent->vtable_size <= slot)
7266 generic_inst = parent_inst;
7269 klass = klass->parent;
7272 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7273 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7274 if (!mono_error_ok (&error)) {
7275 mono_error_set_pending_exception (&error);
7279 generic_inst = NULL;
7281 if (mono_class_is_ginst (klass)) {
7282 generic_inst = mono_class_get_context (klass);
7283 klass = mono_class_get_generic_class (klass)->container_class;
7289 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7290 if (!mono_error_ok (&error)) {
7291 mono_error_set_pending_exception (&error);
7296 if (klass == method->klass)
7299 /*This is possible if definition == FALSE.
7300 * Do it here to be really sure we don't read invalid memory.
7302 if (slot >= klass->vtable_size)
7305 mono_class_setup_vtable (klass);
7307 result = klass->vtable [slot];
7308 if (result == NULL) {
7309 /* It is an abstract method */
7310 gboolean found = FALSE;
7311 gpointer iter = NULL;
7312 while ((result = mono_class_get_methods (klass, &iter))) {
7313 if (result->slot == slot) {
7318 /* found might be FALSE if we looked in an abstract class
7319 * that doesn't override an abstract method of its
7321 * abstract class Base {
7322 * public abstract void Foo ();
7324 * abstract class Derived : Base { }
7325 * class Child : Derived {
7326 * public override void Foo () { }
7329 * if m was Child.Foo and we ask for the base method,
7330 * then we get here with klass == Derived and found == FALSE
7332 /* but it shouldn't be the case that if we're looking
7333 * for the definition and didn't find a result; the
7334 * loop above should've taken us as far as we could
7336 g_assert (!(definition && !found));
7341 g_assert (result != NULL);
7343 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7344 mono_error_set_pending_exception (&error);
7348 ICALL_EXPORT MonoString*
7349 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7351 MonoMethod *method = m->method;
7353 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7358 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7360 iter->sig = *(MonoMethodSignature**)argsp;
7362 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7363 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7366 /* FIXME: it's not documented what start is exactly... */
7370 iter->args = argsp + sizeof (gpointer);
7372 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7374 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7377 ICALL_EXPORT MonoTypedRef
7378 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7380 guint32 i, arg_size;
7384 i = iter->sig->sentinelpos + iter->next_arg;
7386 g_assert (i < iter->sig->param_count);
7388 res.type = iter->sig->params [i];
7389 res.klass = mono_class_from_mono_type (res.type);
7390 arg_size = mono_type_stack_size (res.type, &align);
7391 #if defined(__arm__) || defined(__mips__)
7392 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7394 res.value = iter->args;
7395 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7396 /* Values are stored as 8 byte register sized objects, but 'value'
7397 * is dereferenced as a pointer in other routines.
7399 res.value = (char*)res.value + 4;
7401 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7402 if (arg_size <= sizeof (gpointer)) {
7404 int padding = arg_size - mono_type_size (res.type, &dummy);
7405 res.value = (guint8*)res.value + padding;
7408 iter->args = (char*)iter->args + arg_size;
7411 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7416 ICALL_EXPORT MonoTypedRef
7417 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7419 guint32 i, arg_size;
7423 i = iter->sig->sentinelpos + iter->next_arg;
7425 g_assert (i < iter->sig->param_count);
7427 while (i < iter->sig->param_count) {
7428 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7430 res.type = iter->sig->params [i];
7431 res.klass = mono_class_from_mono_type (res.type);
7432 /* FIXME: endianess issue... */
7433 arg_size = mono_type_stack_size (res.type, &align);
7434 #if defined(__arm__) || defined(__mips__)
7435 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7437 res.value = iter->args;
7438 iter->args = (char*)iter->args + arg_size;
7440 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7443 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7451 ICALL_EXPORT MonoType*
7452 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7456 i = iter->sig->sentinelpos + iter->next_arg;
7458 g_assert (i < iter->sig->param_count);
7460 return iter->sig->params [i];
7463 ICALL_EXPORT MonoObject*
7464 mono_TypedReference_ToObject (MonoTypedRef* tref)
7467 MonoObject *result = NULL;
7468 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7469 MonoObject** objp = (MonoObject **)tref->value;
7473 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7474 mono_error_set_pending_exception (&error);
7478 ICALL_EXPORT MonoTypedRef
7479 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7482 MonoReflectionField *f;
7484 MonoType *ftype = NULL;
7488 memset (&res, 0, sizeof (res));
7491 g_assert (mono_array_length (fields) > 0);
7493 klass = target->vtable->klass;
7495 for (i = 0; i < mono_array_length (fields); ++i) {
7496 f = mono_array_get (fields, MonoReflectionField*, i);
7498 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7501 if (f->field->parent != klass) {
7502 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7506 p = (guint8*)target + f->field->offset;
7508 p += f->field->offset - sizeof (MonoObject);
7509 klass = mono_class_from_mono_type (f->field->type);
7510 ftype = f->field->type;
7514 res.klass = mono_class_from_mono_type (ftype);
7521 prelink_method (MonoMethod *method, MonoError *error)
7523 const char *exc_class, *exc_arg;
7525 mono_error_init (error);
7526 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7528 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7530 mono_error_set_exception_instance (error,
7531 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7534 /* create the wrapper, too? */
7538 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7542 prelink_method (method->method, &error);
7543 mono_error_set_pending_exception (&error);
7547 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7550 MonoClass *klass = mono_class_from_mono_type (type->type);
7552 gpointer iter = NULL;
7554 mono_class_init_checked (klass, &error);
7555 if (mono_error_set_pending_exception (&error))
7558 while ((m = mono_class_get_methods (klass, &iter))) {
7559 prelink_method (m, &error);
7560 if (mono_error_set_pending_exception (&error))
7565 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7567 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7568 gint32 const **exponents,
7569 gunichar2 const **digitLowerTable,
7570 gunichar2 const **digitUpperTable,
7571 gint64 const **tenPowersList,
7572 gint32 const **decHexDigits)
7574 *mantissas = Formatter_MantissaBitsTable;
7575 *exponents = Formatter_TensExponentTable;
7576 *digitLowerTable = Formatter_DigitLowerTable;
7577 *digitUpperTable = Formatter_DigitUpperTable;
7578 *tenPowersList = Formatter_TenPowersList;
7579 *decHexDigits = Formatter_DecHexDigits;
7583 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7584 * and avoid useless allocations.
7587 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7589 MonoReflectionType *rt;
7593 mono_error_init (error);
7594 for (i = 0; i < type->num_mods; ++i) {
7595 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7600 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7601 return_val_if_nok (error, NULL);
7603 for (i = 0; i < type->num_mods; ++i) {
7604 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7605 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7606 return_val_if_nok (error, NULL);
7608 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7609 return_val_if_nok (error, NULL);
7611 mono_array_setref (res, count, rt);
7618 ICALL_EXPORT MonoArray*
7619 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7622 MonoType *type = param->ClassImpl->type;
7623 MonoClass *member_class = mono_object_class (param->MemberImpl);
7624 MonoMethod *method = NULL;
7627 MonoMethodSignature *sig;
7630 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7631 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7632 method = rmethod->method;
7633 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7634 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7635 if (!(method = prop->property->get))
7636 method = prop->property->set;
7639 char *type_name = mono_type_get_full_name (member_class);
7640 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7641 MonoException *ex = mono_get_exception_not_supported (msg);
7644 mono_set_pending_exception (ex);
7648 image = method->klass->image;
7649 pos = param->PositionImpl;
7650 sig = mono_method_signature (method);
7654 type = sig->params [pos];
7656 res = type_array_from_modifiers (image, type, optional, &error);
7657 mono_error_set_pending_exception (&error);
7662 get_property_type (MonoProperty *prop)
7664 MonoMethodSignature *sig;
7666 sig = mono_method_signature (prop->get);
7668 } else if (prop->set) {
7669 sig = mono_method_signature (prop->set);
7670 return sig->params [sig->param_count - 1];
7675 ICALL_EXPORT MonoArray*
7676 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7679 MonoType *type = get_property_type (property->property);
7680 MonoImage *image = property->klass->image;
7685 res = type_array_from_modifiers (image, type, optional, &error);
7686 mono_error_set_pending_exception (&error);
7691 *Construct a MonoType suited to be used to decode a constant blob object.
7693 * @type is the target type which will be constructed
7694 * @blob_type is the blob type, for example, that comes from the constant table
7695 * @real_type is the expected constructed type.
7698 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7700 type->type = blob_type;
7701 type->data.klass = NULL;
7702 if (blob_type == MONO_TYPE_CLASS)
7703 type->data.klass = mono_defaults.object_class;
7704 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7705 /* For enums, we need to use the base type */
7706 type->type = MONO_TYPE_VALUETYPE;
7707 type->data.klass = mono_class_from_mono_type (real_type);
7709 type->data.klass = mono_class_from_mono_type (real_type);
7712 ICALL_EXPORT MonoObject*
7713 property_info_get_default_value (MonoReflectionProperty *property)
7717 MonoProperty *prop = property->property;
7718 MonoType *type = get_property_type (prop);
7719 MonoDomain *domain = mono_object_domain (property);
7720 MonoTypeEnum def_type;
7721 const char *def_value;
7724 mono_class_init (prop->parent);
7726 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7727 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7731 def_value = mono_class_get_property_default_value (prop, &def_type);
7733 mono_type_from_blob_type (&blob_type, def_type, type);
7734 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7736 mono_error_set_pending_exception (&error);
7740 ICALL_EXPORT MonoBoolean
7741 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7744 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7745 MonoCustomAttrInfo *cinfo;
7748 mono_class_init_checked (attr_class, &error);
7749 if (mono_error_set_pending_exception (&error))
7752 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7753 if (!is_ok (&error)) {
7754 mono_error_set_pending_exception (&error);
7759 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7761 mono_custom_attrs_free (cinfo);
7765 ICALL_EXPORT MonoArray*
7766 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7768 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7773 mono_class_init_checked (attr_class, &error);
7774 if (mono_error_set_pending_exception (&error))
7778 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7779 if (!mono_error_ok (&error)) {
7780 mono_error_set_pending_exception (&error);
7787 ICALL_EXPORT MonoArray*
7788 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7792 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7793 mono_error_set_pending_exception (&error);
7798 ICALL_EXPORT MonoStringHandle
7799 ves_icall_Mono_Runtime_GetDisplayName (MonoError *error)
7802 MonoStringHandle display_name;
7804 mono_error_init (error);
7805 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7806 display_name = mono_string_new_handle (mono_domain_get (), info, error);
7808 return display_name;
7812 static inline gint32
7813 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
7815 return WAIT_TIMEOUT;
7817 #endif /* !HOST_WIN32 */
7820 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7822 return mono_icall_wait_for_input_idle (handle, milliseconds);
7826 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7828 return mono_process_current_pid ();
7831 ICALL_EXPORT MonoBoolean
7832 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
7844 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
7846 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
7850 ICALL_EXPORT MonoObject*
7851 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
7853 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
7858 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
7860 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
7864 ICALL_EXPORT MonoObject*
7865 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
7867 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
7871 ICALL_EXPORT MonoBoolean
7872 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
7874 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
7879 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
7881 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
7885 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
7887 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
7892 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
7894 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
7898 ICALL_EXPORT mono_unichar2*
7899 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
7901 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
7908 #ifndef DISABLE_ICALL_TABLES
7910 #define ICALL_TYPE(id,name,first)
7911 #define ICALL(id,name,func) Icall_ ## id,
7912 #define HANDLES(inner) inner
7915 #include "metadata/icall-def.h"
7921 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7922 #define ICALL(id,name,func)
7924 #define HANDLES(inner) inner
7926 #include "metadata/icall-def.h"
7932 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7933 #define ICALL(id,name,func)
7935 #define HANDLES(inner) inner
7937 guint16 first_icall;
7940 static const IcallTypeDesc
7941 icall_type_descs [] = {
7942 #include "metadata/icall-def.h"
7946 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7949 #define HANDLES(inner) inner
7951 #define ICALL_TYPE(id,name,first)
7954 #ifdef HAVE_ARRAY_ELEM_INIT
7955 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7956 #define MSGSTRFIELD1(line) str##line
7958 static const struct msgstrtn_t {
7959 #define ICALL(id,name,func)
7961 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7962 #include "metadata/icall-def.h"
7964 } icall_type_names_str = {
7965 #define ICALL_TYPE(id,name,first) (name),
7966 #include "metadata/icall-def.h"
7969 static const guint16 icall_type_names_idx [] = {
7970 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7971 #include "metadata/icall-def.h"
7974 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7976 static const struct msgstr_t {
7978 #define ICALL_TYPE(id,name,first)
7979 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7980 #include "metadata/icall-def.h"
7982 } icall_names_str = {
7983 #define ICALL(id,name,func) (name),
7984 #include "metadata/icall-def.h"
7987 static const guint16 icall_names_idx [] = {
7988 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7989 #include "metadata/icall-def.h"
7992 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7998 #define ICALL_TYPE(id,name,first) name,
7999 #define ICALL(id,name,func)
8000 static const char* const
8001 icall_type_names [] = {
8002 #include "metadata/icall-def.h"
8006 #define icall_type_name_get(id) (icall_type_names [(id)])
8010 #define ICALL_TYPE(id,name,first)
8011 #define ICALL(id,name,func) name,
8012 static const char* const
8014 #include "metadata/icall-def.h"
8017 #define icall_name_get(id) icall_names [(id)]
8019 #endif /* !HAVE_ARRAY_ELEM_INIT */
8022 #define HANDLES(inner) inner
8025 #define ICALL_TYPE(id,name,first)
8026 #define ICALL(id,name,func) func,
8027 static const gconstpointer
8028 icall_functions [] = {
8029 #include "metadata/icall-def.h"
8033 #ifdef ENABLE_ICALL_SYMBOL_MAP
8035 #define HANDLES(inner) inner
8038 #define ICALL_TYPE(id,name,first)
8039 #define ICALL(id,name,func) #func,
8040 static const gconstpointer
8041 icall_symbols [] = {
8042 #include "metadata/icall-def.h"
8049 #define ICALL_TYPE(id,name,first)
8050 #define ICALL(id,name,func) 0,
8052 #define HANDLES(inner) 1,
8054 icall_uses_handles [] = {
8055 #include "metadata/icall-def.h"
8060 #endif /* DISABLE_ICALL_TABLES */
8062 static mono_mutex_t icall_mutex;
8063 static GHashTable *icall_hash = NULL;
8064 static GHashTable *jit_icall_hash_name = NULL;
8065 static GHashTable *jit_icall_hash_addr = NULL;
8068 mono_icall_init (void)
8070 #ifndef DISABLE_ICALL_TABLES
8073 /* check that tables are sorted: disable in release */
8076 const char *prev_class = NULL;
8077 const char *prev_method;
8079 for (i = 0; i < Icall_type_num; ++i) {
8080 const IcallTypeDesc *desc;
8083 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8084 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8085 prev_class = icall_type_name_get (i);
8086 desc = &icall_type_descs [i];
8087 num_icalls = icall_desc_num_icalls (desc);
8088 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8089 for (j = 0; j < num_icalls; ++j) {
8090 const char *methodn = icall_name_get (desc->first_icall + j);
8091 if (prev_method && strcmp (prev_method, methodn) >= 0)
8092 g_print ("method %s should come before method %s\n", methodn, prev_method);
8093 prev_method = methodn;
8099 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8100 mono_os_mutex_init (&icall_mutex);
8104 mono_icall_lock (void)
8106 mono_locks_os_acquire (&icall_mutex, IcallLock);
8110 mono_icall_unlock (void)
8112 mono_locks_os_release (&icall_mutex, IcallLock);
8116 mono_icall_cleanup (void)
8118 g_hash_table_destroy (icall_hash);
8119 g_hash_table_destroy (jit_icall_hash_name);
8120 g_hash_table_destroy (jit_icall_hash_addr);
8121 mono_os_mutex_destroy (&icall_mutex);
8125 * mono_add_internal_call:
8126 * @name: method specification to surface to the managed world
8127 * @method: pointer to a C method to invoke when the method is called
8129 * This method surfaces the C function pointed by @method as a method
8130 * that has been surfaced in managed code with the method specified in
8131 * @name as an internal call.
8133 * Internal calls are surfaced to all app domains loaded and they are
8134 * accessibly by a type with the specified name.
8136 * You must provide a fully qualified type name, that is namespaces
8137 * and type name, followed by a colon and the method name, with an
8138 * optional signature to bind.
8140 * For example, the following are all valid declarations:
8142 * "MyApp.Services.ScriptService:Accelerate"
8143 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8145 * You use method parameters in cases where there might be more than
8146 * one surface method to managed code. That way you can register different
8147 * internal calls for different method overloads.
8149 * The internal calls are invoked with no marshalling. This means that .NET
8150 * types like System.String are exposed as `MonoString *` parameters. This is
8151 * different than the way that strings are surfaced in P/Invoke.
8153 * For more information on how the parameters are marshalled, see the
8154 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8157 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8158 * reference for more information on the format of method descriptions.
8161 mono_add_internal_call (const char *name, gconstpointer method)
8165 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8167 mono_icall_unlock ();
8170 #ifndef DISABLE_ICALL_TABLES
8172 #ifdef HAVE_ARRAY_ELEM_INIT
8174 compare_method_imap (const void *key, const void *elem)
8176 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8177 return strcmp (key, method_name);
8181 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8183 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);
8186 return (nameslot - &icall_names_idx [0]);
8190 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8192 gsize slotnum = find_slot_icall (imap, name);
8195 return (gboolean)icall_uses_handles [slotnum];
8199 find_method_icall (const IcallTypeDesc *imap, const char *name)
8201 gsize slotnum = find_slot_icall (imap, name);
8204 return (gpointer)icall_functions [slotnum];
8208 compare_class_imap (const void *key, const void *elem)
8210 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8211 return strcmp (key, class_name);
8214 static const IcallTypeDesc*
8215 find_class_icalls (const char *name)
8217 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);
8220 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8223 #else /* HAVE_ARRAY_ELEM_INIT */
8226 compare_method_imap (const void *key, const void *elem)
8228 const char** method_name = (const char**)elem;
8229 return strcmp (key, *method_name);
8233 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8235 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8238 return nameslot - icall_names;
8242 find_method_icall (const IcallTypeDesc *imap, const char *name)
8244 gsize slotnum = find_slot_icall (imap, name);
8247 return (gpointer)icall_functions [slotnum];
8251 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8253 gsize slotnum = find_slot_icall (imap, name);
8256 return (gboolean)icall_uses_handles [slotnum];
8260 compare_class_imap (const void *key, const void *elem)
8262 const char** class_name = (const char**)elem;
8263 return strcmp (key, *class_name);
8266 static const IcallTypeDesc*
8267 find_class_icalls (const char *name)
8269 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8272 return &icall_type_descs [nameslot - icall_type_names];
8275 #endif /* HAVE_ARRAY_ELEM_INIT */
8277 #endif /* DISABLE_ICALL_TABLES */
8280 * we should probably export this as an helper (handle nested types).
8281 * Returns the number of chars written in buf.
8284 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8286 int nspacelen, cnamelen;
8287 nspacelen = strlen (klass->name_space);
8288 cnamelen = strlen (klass->name);
8289 if (nspacelen + cnamelen + 2 > bufsize)
8292 memcpy (buf, klass->name_space, nspacelen);
8293 buf [nspacelen ++] = '.';
8295 memcpy (buf + nspacelen, klass->name, cnamelen);
8296 buf [nspacelen + cnamelen] = 0;
8297 return nspacelen + cnamelen;
8300 #ifdef DISABLE_ICALL_TABLES
8302 no_icall_table (void)
8304 g_assert_not_reached ();
8309 * mono_lookup_internal_call_full:
8310 * @method: the method to look up
8311 * @uses_handles: out argument if method needs handles around managed objects.
8313 * Returns a pointer to the icall code for the given method. If
8314 * uses_handles is not NULL, it will be set to TRUE if the method
8315 * needs managed objects wrapped using the infrastructure in handle.h
8317 * If the method is not found, warns and returns NULL.
8320 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8325 int typelen = 0, mlen, siglen;
8327 #ifndef DISABLE_ICALL_TABLES
8328 const IcallTypeDesc *imap = NULL;
8331 g_assert (method != NULL);
8333 if (method->is_inflated)
8334 method = ((MonoMethodInflated *) method)->declaring;
8336 if (method->klass->nested_in) {
8337 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8341 mname [pos++] = '/';
8344 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8350 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8355 #ifndef DISABLE_ICALL_TABLES
8356 imap = find_class_icalls (mname);
8359 mname [typelen] = ':';
8360 mname [typelen + 1] = ':';
8362 mlen = strlen (method->name);
8363 memcpy (mname + typelen + 2, method->name, mlen);
8364 sigstart = mname + typelen + 2 + mlen;
8367 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8368 siglen = strlen (tmpsig);
8369 if (typelen + mlen + siglen + 6 > sizeof (mname))
8372 memcpy (sigstart + 1, tmpsig, siglen);
8373 sigstart [siglen + 1] = ')';
8374 sigstart [siglen + 2] = 0;
8379 res = g_hash_table_lookup (icall_hash, mname);
8382 *uses_handles = FALSE;
8383 mono_icall_unlock ();;
8386 /* try without signature */
8388 res = g_hash_table_lookup (icall_hash, mname);
8391 *uses_handles = FALSE;
8392 mono_icall_unlock ();
8396 #ifdef DISABLE_ICALL_TABLES
8397 mono_icall_unlock ();
8398 /* Fail only when the result is actually used */
8399 /* mono_marshal_get_native_wrapper () depends on this */
8400 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8401 return ves_icall_System_String_ctor_RedirectToCreateString;
8403 return no_icall_table;
8405 /* it wasn't found in the static call tables */
8408 *uses_handles = FALSE;
8409 mono_icall_unlock ();
8412 res = find_method_icall (imap, sigstart - mlen);
8415 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8416 mono_icall_unlock ();
8419 /* try _with_ signature */
8421 res = find_method_icall (imap, sigstart - mlen);
8424 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8425 mono_icall_unlock ();
8429 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8430 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8431 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8432 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8433 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");
8434 g_print ("If you see other errors or faults after this message they are probably related\n");
8435 g_print ("and you need to fix your mono install first.\n");
8437 mono_icall_unlock ();
8444 mono_lookup_internal_call (MonoMethod *method)
8446 return mono_lookup_internal_call_full (method, NULL);
8449 #ifdef ENABLE_ICALL_SYMBOL_MAP
8451 func_cmp (gconstpointer key, gconstpointer p)
8453 return (gsize)key - (gsize)*(gsize*)p;
8458 * mono_lookup_icall_symbol:
8460 * Given the icall METHOD, returns its C symbol.
8463 mono_lookup_icall_symbol (MonoMethod *m)
8465 #ifdef DISABLE_ICALL_TABLES
8466 g_assert_not_reached ();
8469 #ifdef ENABLE_ICALL_SYMBOL_MAP
8473 static gconstpointer *functions_sorted;
8474 static const char**symbols_sorted;
8475 static gboolean inited;
8480 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8481 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8482 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8483 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8484 /* Bubble sort the two arrays */
8488 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8489 if (functions_sorted [i] > functions_sorted [i + 1]) {
8492 tmp = functions_sorted [i];
8493 functions_sorted [i] = functions_sorted [i + 1];
8494 functions_sorted [i + 1] = tmp;
8495 tmp = symbols_sorted [i];
8496 symbols_sorted [i] = symbols_sorted [i + 1];
8497 symbols_sorted [i + 1] = tmp;
8504 func = mono_lookup_internal_call (m);
8507 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8511 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8513 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8514 g_assert_not_reached ();
8521 type_from_typename (char *type_name)
8523 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8525 if (!strcmp (type_name, "int"))
8526 klass = mono_defaults.int_class;
8527 else if (!strcmp (type_name, "ptr"))
8528 klass = mono_defaults.int_class;
8529 else if (!strcmp (type_name, "void"))
8530 klass = mono_defaults.void_class;
8531 else if (!strcmp (type_name, "int32"))
8532 klass = mono_defaults.int32_class;
8533 else if (!strcmp (type_name, "uint32"))
8534 klass = mono_defaults.uint32_class;
8535 else if (!strcmp (type_name, "int8"))
8536 klass = mono_defaults.sbyte_class;
8537 else if (!strcmp (type_name, "uint8"))
8538 klass = mono_defaults.byte_class;
8539 else if (!strcmp (type_name, "int16"))
8540 klass = mono_defaults.int16_class;
8541 else if (!strcmp (type_name, "uint16"))
8542 klass = mono_defaults.uint16_class;
8543 else if (!strcmp (type_name, "long"))
8544 klass = mono_defaults.int64_class;
8545 else if (!strcmp (type_name, "ulong"))
8546 klass = mono_defaults.uint64_class;
8547 else if (!strcmp (type_name, "float"))
8548 klass = mono_defaults.single_class;
8549 else if (!strcmp (type_name, "double"))
8550 klass = mono_defaults.double_class;
8551 else if (!strcmp (type_name, "object"))
8552 klass = mono_defaults.object_class;
8553 else if (!strcmp (type_name, "obj"))
8554 klass = mono_defaults.object_class;
8555 else if (!strcmp (type_name, "string"))
8556 klass = mono_defaults.string_class;
8557 else if (!strcmp (type_name, "bool"))
8558 klass = mono_defaults.boolean_class;
8559 else if (!strcmp (type_name, "boolean"))
8560 klass = mono_defaults.boolean_class;
8562 g_error ("%s", type_name);
8563 g_assert_not_reached ();
8565 return &klass->byval_arg;
8569 * LOCKING: Take the corlib image lock.
8571 MonoMethodSignature*
8572 mono_create_icall_signature (const char *sigstr)
8577 MonoMethodSignature *res, *res2;
8578 MonoImage *corlib = mono_defaults.corlib;
8580 mono_image_lock (corlib);
8581 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8582 mono_image_unlock (corlib);
8587 parts = g_strsplit (sigstr, " ", 256);
8596 res = mono_metadata_signature_alloc (corlib, len - 1);
8601 * Under windows, the default pinvoke calling convention is STDCALL but
8604 res->call_convention = MONO_CALL_C;
8607 res->ret = type_from_typename (parts [0]);
8608 for (i = 1; i < len; ++i) {
8609 res->params [i - 1] = type_from_typename (parts [i]);
8614 mono_image_lock (corlib);
8615 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8617 res = res2; /*Value is allocated in the image pool*/
8619 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8620 mono_image_unlock (corlib);
8626 mono_find_jit_icall_by_name (const char *name)
8628 MonoJitICallInfo *info;
8629 g_assert (jit_icall_hash_name);
8632 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8633 mono_icall_unlock ();
8638 mono_find_jit_icall_by_addr (gconstpointer addr)
8640 MonoJitICallInfo *info;
8641 g_assert (jit_icall_hash_addr);
8644 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8645 mono_icall_unlock ();
8651 * mono_get_jit_icall_info:
8653 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8654 * caller should access it while holding the icall lock.
8657 mono_get_jit_icall_info (void)
8659 return jit_icall_hash_name;
8663 * mono_lookup_jit_icall_symbol:
8665 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8668 mono_lookup_jit_icall_symbol (const char *name)
8670 MonoJitICallInfo *info;
8671 const char *res = NULL;
8674 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8676 res = info->c_symbol;
8677 mono_icall_unlock ();
8682 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8685 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8686 mono_icall_unlock ();
8690 * 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
8691 * icalls without wrappers in some cases.
8694 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8696 MonoJitICallInfo *info;
8703 if (!jit_icall_hash_name) {
8704 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8705 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8708 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8709 g_warning ("jit icall already defined \"%s\"\n", name);
8710 g_assert_not_reached ();
8713 info = g_new0 (MonoJitICallInfo, 1);
8718 info->c_symbol = c_symbol;
8719 info->no_raise = no_raise;
8722 info->wrapper = func;
8724 info->wrapper = NULL;
8727 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8728 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8730 mono_icall_unlock ();
8735 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8737 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);