5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
14 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
25 #ifdef HAVE_SYS_TIME_H
31 #if defined (HAVE_WCHAR_H)
34 #include "mono/metadata/icall-internals.h"
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool-ms.h>
40 #include <mono/metadata/threadpool-ms-io.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/image-internals.h>
44 #include <mono/metadata/assembly.h>
45 #include <mono/metadata/assembly-internals.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/w32process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/metadata/handle.h>
85 #include <mono/metadata/w32mutex.h>
86 #include <mono/metadata/w32semaphore.h>
87 #include <mono/metadata/w32event.h>
88 #include <mono/io-layer/io-layer.h>
89 #include <mono/utils/monobitset.h>
90 #include <mono/utils/mono-time.h>
91 #include <mono/utils/mono-proclib.h>
92 #include <mono/utils/mono-string.h>
93 #include <mono/utils/mono-error-internals.h>
94 #include <mono/utils/mono-mmap.h>
95 #include <mono/utils/mono-io-portability.h>
96 #include <mono/utils/mono-digest.h>
97 #include <mono/utils/bsearch.h>
98 #include <mono/utils/mono-os-mutex.h>
99 #include <mono/utils/mono-threads.h>
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_for_class_failure (error, klass);
140 mono_icall_make_platform_path (gchar *path)
145 static inline const gchar *
146 mono_icall_get_file_path_prefix (const gchar *path)
150 #endif /* HOST_WIN32 */
152 ICALL_EXPORT MonoObject *
153 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
159 MonoObject *result = NULL;
161 ac = (MonoClass *)arr->obj.vtable->klass;
163 esize = mono_array_element_size (ac);
164 ea = (gpointer*)((char*)arr->vector + (pos * esize));
166 if (ac->element_class->valuetype) {
167 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
168 mono_error_set_pending_exception (&error);
170 result = (MonoObject *)*ea;
174 ICALL_EXPORT MonoObject *
175 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
181 MONO_CHECK_ARG_NULL (idxs, NULL);
184 ic = (MonoClass *)io->obj.vtable->klass;
186 ac = (MonoClass *)arr->obj.vtable->klass;
188 g_assert (ic->rank == 1);
189 if (io->bounds != NULL || io->max_length != ac->rank) {
190 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
194 ind = (gint32 *)io->vector;
196 if (arr->bounds == NULL) {
197 if (*ind < 0 || *ind >= arr->max_length) {
198 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
202 return ves_icall_System_Array_GetValueImpl (arr, *ind);
205 for (i = 0; i < ac->rank; i++) {
206 if ((ind [i] < arr->bounds [i].lower_bound) ||
207 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
208 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
213 pos = ind [0] - arr->bounds [0].lower_bound;
214 for (i = 1; i < ac->rank; i++)
215 pos = pos * arr->bounds [i].length + ind [i] -
216 arr->bounds [i].lower_bound;
218 return ves_icall_System_Array_GetValueImpl (arr, pos);
222 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
225 MonoClass *ac, *vc, *ec;
234 mono_error_init (&error);
237 vc = value->vtable->klass;
241 ac = arr->obj.vtable->klass;
242 ec = ac->element_class;
244 esize = mono_array_element_size (ac);
245 ea = (gpointer*)((char*)arr->vector + (pos * esize));
246 va = (gpointer*)((char*)value + sizeof (MonoObject));
248 if (mono_class_is_nullable (ec)) {
249 mono_nullable_init ((guint8*)ea, value, ec);
254 mono_gc_bzero_atomic (ea, esize);
258 #define NO_WIDENING_CONVERSION G_STMT_START{\
259 mono_set_pending_exception (mono_get_exception_argument ( \
260 "value", "not a widening conversion")); \
264 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
265 if (esize < vsize + (extra)) { \
266 mono_set_pending_exception (mono_get_exception_argument ( \
267 "value", "not a widening conversion")); \
272 #define INVALID_CAST G_STMT_START{ \
273 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
274 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
278 /* Check element (destination) type. */
279 switch (ec->byval_arg.type) {
280 case MONO_TYPE_STRING:
281 switch (vc->byval_arg.type) {
282 case MONO_TYPE_STRING:
288 case MONO_TYPE_BOOLEAN:
289 switch (vc->byval_arg.type) {
290 case MONO_TYPE_BOOLEAN:
303 NO_WIDENING_CONVERSION;
312 if (!ec->valuetype) {
313 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
314 if (mono_error_set_pending_exception (&error))
318 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
322 if (mono_object_isinst_checked (value, ec, &error)) {
323 if (ec->has_references)
324 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
326 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
329 if (mono_error_set_pending_exception (&error))
335 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
337 et = ec->byval_arg.type;
338 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
339 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
341 vt = vc->byval_arg.type;
342 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
343 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
345 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
351 case MONO_TYPE_CHAR: \
352 CHECK_WIDENING_CONVERSION(0); \
353 *(etype *) ea = (etype) u64; \
355 /* You can't assign a signed value to an unsigned array. */ \
360 /* You can't assign a floating point number to an integer array. */ \
363 NO_WIDENING_CONVERSION; \
367 #define ASSIGN_SIGNED(etype) G_STMT_START{\
373 CHECK_WIDENING_CONVERSION(0); \
374 *(etype *) ea = (etype) i64; \
376 /* You can assign an unsigned value to a signed array if the array's */ \
377 /* element size is larger than the value size. */ \
382 case MONO_TYPE_CHAR: \
383 CHECK_WIDENING_CONVERSION(1); \
384 *(etype *) ea = (etype) u64; \
386 /* You can't assign a floating point number to an integer array. */ \
389 NO_WIDENING_CONVERSION; \
393 #define ASSIGN_REAL(etype) G_STMT_START{\
397 CHECK_WIDENING_CONVERSION(0); \
398 *(etype *) ea = (etype) r64; \
400 /* All integer values fit into a floating point array, so we don't */ \
401 /* need to CHECK_WIDENING_CONVERSION here. */ \
406 *(etype *) ea = (etype) i64; \
412 case MONO_TYPE_CHAR: \
413 *(etype *) ea = (etype) u64; \
420 u64 = *(guint8 *) va;
423 u64 = *(guint16 *) va;
426 u64 = *(guint32 *) va;
429 u64 = *(guint64 *) va;
435 i64 = *(gint16 *) va;
438 i64 = *(gint32 *) va;
441 i64 = *(gint64 *) va;
444 r64 = *(gfloat *) va;
447 r64 = *(gdouble *) va;
450 u64 = *(guint16 *) va;
452 case MONO_TYPE_BOOLEAN:
453 /* Boolean is only compatible with itself. */
466 NO_WIDENING_CONVERSION;
473 /* If we can't do a direct copy, let's try a widening conversion. */
476 ASSIGN_UNSIGNED (guint16);
478 ASSIGN_UNSIGNED (guint8);
480 ASSIGN_UNSIGNED (guint16);
482 ASSIGN_UNSIGNED (guint32);
484 ASSIGN_UNSIGNED (guint64);
486 ASSIGN_SIGNED (gint8);
488 ASSIGN_SIGNED (gint16);
490 ASSIGN_SIGNED (gint32);
492 ASSIGN_SIGNED (gint64);
494 ASSIGN_REAL (gfloat);
496 ASSIGN_REAL (gdouble);
500 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
504 #undef NO_WIDENING_CONVERSION
505 #undef CHECK_WIDENING_CONVERSION
506 #undef ASSIGN_UNSIGNED
512 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
518 MONO_CHECK_ARG_NULL (idxs,);
520 ic = idxs->obj.vtable->klass;
521 ac = arr->obj.vtable->klass;
523 g_assert (ic->rank == 1);
524 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
525 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
529 ind = (gint32 *)idxs->vector;
531 if (arr->bounds == NULL) {
532 if (*ind < 0 || *ind >= arr->max_length) {
533 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
537 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
541 for (i = 0; i < ac->rank; i++)
542 if ((ind [i] < arr->bounds [i].lower_bound) ||
543 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
544 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
548 pos = ind [0] - arr->bounds [0].lower_bound;
549 for (i = 1; i < ac->rank; i++)
550 pos = pos * arr->bounds [i].length + ind [i] -
551 arr->bounds [i].lower_bound;
553 ves_icall_System_Array_SetValueImpl (arr, value, pos);
556 ICALL_EXPORT MonoArray *
557 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
560 MonoClass *aklass, *klass;
563 gboolean bounded = FALSE;
565 MONO_CHECK_ARG_NULL (type, NULL);
566 MONO_CHECK_ARG_NULL (lengths, NULL);
568 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
570 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
572 for (i = 0; i < mono_array_length (lengths); i++) {
573 if (mono_array_get (lengths, gint32, i) < 0) {
574 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
579 klass = mono_class_from_mono_type (type->type);
580 mono_class_init_checked (klass, &error);
581 if (mono_error_set_pending_exception (&error))
584 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
585 /* vectors are not the same as one dimensional arrays with no-zero bounds */
590 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
592 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
593 for (i = 0; i < aklass->rank; ++i) {
594 sizes [i] = mono_array_get (lengths, guint32, i);
596 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
598 sizes [i + aklass->rank] = 0;
601 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
602 mono_error_set_pending_exception (&error);
607 ICALL_EXPORT MonoArray *
608 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
611 MonoClass *aklass, *klass;
614 gboolean bounded = FALSE;
616 MONO_CHECK_ARG_NULL (type, NULL);
617 MONO_CHECK_ARG_NULL (lengths, NULL);
619 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
621 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
623 for (i = 0; i < mono_array_length (lengths); i++) {
624 if ((mono_array_get (lengths, gint64, i) < 0) ||
625 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
626 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
631 klass = mono_class_from_mono_type (type->type);
632 mono_class_init_checked (klass, &error);
633 if (mono_error_set_pending_exception (&error))
636 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
637 /* vectors are not the same as one dimensional arrays with no-zero bounds */
642 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
644 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
645 for (i = 0; i < aklass->rank; ++i) {
646 sizes [i] = mono_array_get (lengths, guint64, i);
648 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
650 sizes [i + aklass->rank] = 0;
653 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
654 mono_error_set_pending_exception (&error);
660 ves_icall_System_Array_GetRank (MonoObject *arr)
662 return arr->vtable->klass->rank;
666 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
668 gint32 rank = arr->obj.vtable->klass->rank;
671 if ((dimension < 0) || (dimension >= rank)) {
672 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
676 if (arr->bounds == NULL)
677 length = arr->max_length;
679 length = arr->bounds [dimension].length;
681 #ifdef MONO_BIG_ARRAYS
682 if (length > G_MAXINT32) {
683 mono_set_pending_exception (mono_get_exception_overflow ());
691 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
693 gint32 rank = arr->obj.vtable->klass->rank;
695 if ((dimension < 0) || (dimension >= rank)) {
696 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
700 if (arr->bounds == NULL)
701 return arr->max_length;
703 return arr->bounds [dimension].length;
707 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
709 gint32 rank = arr->obj.vtable->klass->rank;
711 if ((dimension < 0) || (dimension >= rank)) {
712 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
716 if (arr->bounds == NULL)
719 return arr->bounds [dimension].lower_bound;
723 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
725 int sz = mono_array_element_size (mono_object_class (arr));
726 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
729 ICALL_EXPORT MonoArray*
730 ves_icall_System_Array_Clone (MonoArray *arr)
733 MonoArray *result = mono_array_clone_checked (arr, &error);
734 mono_error_set_pending_exception (&error);
738 ICALL_EXPORT gboolean
739 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
744 MonoVTable *src_vtable;
745 MonoVTable *dest_vtable;
746 MonoClass *src_class;
747 MonoClass *dest_class;
749 src_vtable = source->obj.vtable;
750 dest_vtable = dest->obj.vtable;
752 if (src_vtable->rank != dest_vtable->rank)
755 if (source->bounds || dest->bounds)
758 /* there's no integer overflow since mono_array_length returns an unsigned integer */
759 if ((dest_idx + length > mono_array_length_fast (dest)) ||
760 (source_idx + length > mono_array_length_fast (source)))
763 src_class = src_vtable->klass->element_class;
764 dest_class = dest_vtable->klass->element_class;
767 * Handle common cases.
770 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
771 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
773 if (src_class == mono_defaults.object_class && dest_class->valuetype)
776 /* Check if we're copying a char[] <==> (u)short[] */
777 if (src_class != dest_class) {
778 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
781 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
782 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
786 if (dest_class->valuetype) {
787 element_size = mono_array_element_size (source->obj.vtable->klass);
788 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
789 if (dest_class->has_references) {
790 mono_value_copy_array (dest, dest_idx, source_addr, length);
792 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
793 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
796 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
803 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
809 ac = (MonoClass *)arr->obj.vtable->klass;
811 esize = mono_array_element_size (ac);
812 ea = (gpointer*)((char*)arr->vector + (pos * esize));
814 mono_gc_memmove_atomic (value, ea, esize);
818 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
824 ac = (MonoClass *)arr->obj.vtable->klass;
825 ec = ac->element_class;
827 esize = mono_array_element_size (ac);
828 ea = (gpointer*)((char*)arr->vector + (pos * esize));
830 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
831 g_assert (esize == sizeof (gpointer));
832 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
834 g_assert (ec->inited);
835 g_assert (esize == mono_class_value_size (ec, NULL));
836 if (ec->has_references)
837 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
839 mono_gc_memmove_atomic (ea, value, esize);
844 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (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 current = (guint8 *)&stack_addr;
1002 if (current > stack_addr) {
1003 if ((current - stack_addr) < min_size)
1006 if (current - (stack_addr - stack_size) < min_size)
1013 ICALL_EXPORT MonoObject *
1014 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1017 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1018 mono_error_set_pending_exception (&error);
1024 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1028 MonoObject **values = NULL;
1031 gint32 result = (int)(gsize)mono_defaults.int32_class;
1032 MonoClassField* field;
1035 klass = mono_object_class (this_obj);
1037 if (mono_class_num_fields (klass) == 0)
1041 * Compute the starting value of the hashcode for fields of primitive
1042 * types, and return the remaining fields in an array to the managed side.
1043 * This way, we can avoid costly reflection operations in managed code.
1046 while ((field = mono_class_get_fields (klass, &iter))) {
1047 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1049 if (mono_field_is_deleted (field))
1051 /* FIXME: Add more types */
1052 switch (field->type->type) {
1054 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1056 case MONO_TYPE_STRING: {
1058 s = *(MonoString**)((guint8*)this_obj + field->offset);
1060 result ^= mono_string_hash (s);
1065 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1066 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1067 if (!is_ok (&error)) {
1068 mono_error_set_pending_exception (&error);
1071 values [count++] = o;
1077 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1078 if (mono_error_set_pending_exception (&error))
1080 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1081 for (i = 0; i < count; ++i)
1082 mono_array_setref (*fields, i, values [i]);
1089 ICALL_EXPORT MonoBoolean
1090 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1094 MonoObject **values = NULL;
1096 MonoClassField* field;
1100 MONO_CHECK_ARG_NULL (that, FALSE);
1102 if (this_obj->vtable != that->vtable)
1105 klass = mono_object_class (this_obj);
1107 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1108 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1111 * Do the comparison for fields of primitive type and return a result if
1112 * possible. Otherwise, return the remaining fields in an array to the
1113 * managed side. This way, we can avoid costly reflection operations in
1118 while ((field = mono_class_get_fields (klass, &iter))) {
1119 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1121 if (mono_field_is_deleted (field))
1123 /* FIXME: Add more types */
1124 switch (field->type->type) {
1127 case MONO_TYPE_BOOLEAN:
1128 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1133 case MONO_TYPE_CHAR:
1134 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1139 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1144 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1148 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1152 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1157 case MONO_TYPE_STRING: {
1158 MonoString *s1, *s2;
1159 guint32 s1len, s2len;
1160 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1161 s2 = *(MonoString**)((guint8*)that + field->offset);
1164 if ((s1 == NULL) || (s2 == NULL))
1166 s1len = mono_string_length (s1);
1167 s2len = mono_string_length (s2);
1171 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1177 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1178 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1179 if (!is_ok (&error)) {
1180 mono_error_set_pending_exception (&error);
1183 values [count++] = o;
1184 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1185 if (!is_ok (&error)) {
1186 mono_error_set_pending_exception (&error);
1189 values [count++] = o;
1192 if (klass->enumtype)
1193 /* enums only have one non-static field */
1199 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1200 if (mono_error_set_pending_exception (&error))
1202 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1203 for (i = 0; i < count; ++i)
1204 mono_array_setref_fast (*fields, i, values [i]);
1211 ICALL_EXPORT MonoReflectionType *
1212 ves_icall_System_Object_GetType (MonoObject *obj)
1215 MonoReflectionType *ret;
1216 #ifndef DISABLE_REMOTING
1217 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1218 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1221 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1223 mono_error_set_pending_exception (&error);
1228 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1230 MonoMethod **dest = (MonoMethod **)data;
1232 /* skip unmanaged frames */
1237 if (!strcmp (m->klass->name_space, "System.Reflection"))
1246 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1248 MonoMethod **dest = (MonoMethod **)data;
1250 /* skip unmanaged frames */
1254 if (m->wrapper_type != MONO_WRAPPER_NONE)
1262 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1273 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1275 MonoMethod **dest = (MonoMethod **)data;
1277 /* skip unmanaged frames */
1281 if (m->wrapper_type != MONO_WRAPPER_NONE)
1289 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1290 || (!strcmp (m->klass->name_space, "System"))))
1300 static MonoReflectionType *
1301 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoAssembly **caller_assembly, MonoError *error)
1303 MonoMethod *m, *dest;
1305 MonoType *type = NULL;
1306 MonoAssembly *assembly = NULL;
1307 gboolean type_resolve = FALSE;
1308 MonoImage *rootimage = NULL;
1310 mono_error_init (error);
1313 * We must compute the calling assembly as type loading must happen under a metadata context.
1314 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1315 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1317 m = mono_method_get_last_managed ();
1319 if (m && m->klass->image != mono_defaults.corlib) {
1320 /* Happens with inlining */
1322 /* Ugly hack: type_from_parsed_name is called from
1323 * System.Type.internal_from_name, which is called most
1324 * directly from System.Type.GetType(string,bool,bool) but
1325 * also indirectly from places such as
1326 * System.Type.GetType(string,func,func) (via
1327 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1328 * so we need to skip over all of those to find the true caller.
1330 * It would be nice if we had stack marks.
1332 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1338 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1339 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1340 * to crash. This only seems to happen in some strange remoting
1341 * scenarios and I was unable to figure out what's happening there.
1342 * Dec 10, 2005 - Martin.
1346 assembly = dest->klass->image->assembly;
1347 type_resolve = TRUE;
1348 rootimage = assembly->image;
1350 g_warning (G_STRLOC);
1352 *caller_assembly = assembly;
1354 if (info->assembly.name)
1355 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1358 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1359 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1360 return_val_if_nok (error, NULL);
1364 // Say we're looking for System.Generic.Dict<int, Local>
1365 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1366 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1367 // is messed up when we go to construct the Local as the type arg...
1369 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1370 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1371 if (!info->assembly.name && !type) {
1373 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1374 return_val_if_nok (error, NULL);
1376 if (assembly && !type && type_resolve) {
1377 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1378 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1379 return_val_if_nok (error, NULL);
1385 return mono_type_get_object_checked (mono_domain_get (), type, error);
1388 ICALL_EXPORT MonoReflectionType*
1389 ves_icall_System_Type_internal_from_name (MonoString *name,
1390 MonoBoolean throwOnError,
1391 MonoBoolean ignoreCase)
1394 MonoTypeNameParse info;
1395 MonoReflectionType *type = NULL;
1397 MonoAssembly *caller_assembly;
1399 char *str = mono_string_to_utf8_checked (name, &error);
1400 if (!is_ok (&error))
1403 parsedOk = mono_reflection_parse_type (str, &info);
1405 /* mono_reflection_parse_type() mangles the string */
1407 mono_reflection_free_type_info (&info);
1409 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1413 type = type_from_parsed_name (&info, ignoreCase, &caller_assembly, &error);
1415 if (!is_ok (&error)) {
1416 mono_reflection_free_type_info (&info);
1422 char *tname = info.name_space ? g_strdup_printf ("%s.%s", info.name_space, info.name) : g_strdup (info.name);
1424 if (info.assembly.name)
1425 aname = mono_stringify_assembly_name (&info.assembly);
1426 else if (caller_assembly)
1427 aname = mono_stringify_assembly_name (mono_assembly_get_name (caller_assembly));
1429 aname = g_strdup ("");
1430 mono_error_set_type_load_name (&error, tname, aname, "");
1432 mono_reflection_free_type_info (&info);
1438 if (!is_ok (&error)) {
1440 mono_error_set_pending_exception (&error);
1442 mono_error_cleanup (&error);
1450 ICALL_EXPORT MonoReflectionType*
1451 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1454 MonoReflectionType *ret;
1455 MonoDomain *domain = mono_domain_get ();
1457 ret = mono_type_get_object_checked (domain, handle, &error);
1458 mono_error_set_pending_exception (&error);
1463 ICALL_EXPORT MonoType*
1464 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1466 return mono_class_get_type (klass);
1470 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1472 g_ptr_array_free (ptr_array, TRUE);
1476 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1482 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1485 char *res = mono_string_to_utf8_checked (s, &error);
1486 mono_error_set_pending_exception (&error);
1490 /* System.TypeCode */
1509 TYPECODE_STRING = 18
1512 ICALL_EXPORT guint32
1513 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1515 int t = type->type->type;
1517 if (type->type->byref)
1518 return TYPECODE_OBJECT;
1522 case MONO_TYPE_VOID:
1523 return TYPECODE_OBJECT;
1524 case MONO_TYPE_BOOLEAN:
1525 return TYPECODE_BOOLEAN;
1527 return TYPECODE_BYTE;
1529 return TYPECODE_SBYTE;
1531 return TYPECODE_UINT16;
1533 return TYPECODE_INT16;
1534 case MONO_TYPE_CHAR:
1535 return TYPECODE_CHAR;
1539 return TYPECODE_OBJECT;
1541 return TYPECODE_UINT32;
1543 return TYPECODE_INT32;
1545 return TYPECODE_UINT64;
1547 return TYPECODE_INT64;
1549 return TYPECODE_SINGLE;
1551 return TYPECODE_DOUBLE;
1552 case MONO_TYPE_VALUETYPE: {
1553 MonoClass *klass = type->type->data.klass;
1555 if (klass->enumtype) {
1556 t = mono_class_enum_basetype (klass)->type;
1558 } else if (mono_is_corlib_image (klass->image)) {
1559 if (strcmp (klass->name_space, "System") == 0) {
1560 if (strcmp (klass->name, "Decimal") == 0)
1561 return TYPECODE_DECIMAL;
1562 else if (strcmp (klass->name, "DateTime") == 0)
1563 return TYPECODE_DATETIME;
1566 return TYPECODE_OBJECT;
1568 case MONO_TYPE_STRING:
1569 return TYPECODE_STRING;
1570 case MONO_TYPE_SZARRAY:
1571 case MONO_TYPE_ARRAY:
1572 case MONO_TYPE_OBJECT:
1574 case MONO_TYPE_MVAR:
1575 case MONO_TYPE_TYPEDBYREF:
1576 return TYPECODE_OBJECT;
1577 case MONO_TYPE_CLASS:
1579 MonoClass *klass = type->type->data.klass;
1580 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1581 if (strcmp (klass->name, "DBNull") == 0)
1582 return TYPECODE_DBNULL;
1585 return TYPECODE_OBJECT;
1586 case MONO_TYPE_GENERICINST:
1587 return TYPECODE_OBJECT;
1589 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1595 mono_type_is_primitive (MonoType *type)
1597 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1598 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1602 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1604 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1605 return mono_class_enum_basetype (type->data.klass);
1606 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1607 return mono_class_enum_basetype (type->data.generic_class->container_class);
1611 ICALL_EXPORT guint32
1612 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1617 g_assert (type != NULL);
1619 klass = mono_class_from_mono_type (type->type);
1620 klassc = mono_class_from_mono_type (c->type);
1622 if (type->type->byref ^ c->type->byref)
1625 if (type->type->byref) {
1626 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1627 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1629 klass = mono_class_from_mono_type (t);
1630 klassc = mono_class_from_mono_type (ot);
1632 if (mono_type_is_primitive (t)) {
1633 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1634 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1635 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1636 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1637 return t->type == ot->type;
1639 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1642 if (klass->valuetype)
1643 return klass == klassc;
1644 return klass->valuetype == klassc->valuetype;
1647 return mono_class_is_assignable_from (klass, klassc);
1650 ICALL_EXPORT guint32
1651 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1654 MonoClass *klass = mono_class_from_mono_type (type->type);
1655 mono_class_init_checked (klass, &error);
1656 if (!is_ok (&error)) {
1657 mono_error_set_pending_exception (&error);
1660 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1661 mono_error_set_pending_exception (&error);
1665 ICALL_EXPORT guint32
1666 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1668 MonoClass *klass = mono_class_from_mono_type (type->type);
1669 return mono_class_get_flags (klass);
1672 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1673 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1676 MonoClass *klass = field->field->parent;
1677 MonoMarshalType *info;
1681 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1682 if (mono_class_is_gtd (klass) ||
1683 (gklass && gklass->context.class_inst->is_open))
1686 ftype = mono_field_get_type (field->field);
1687 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1690 info = mono_marshal_load_type_info (klass);
1692 for (i = 0; i < info->num_fields; ++i) {
1693 if (info->fields [i].field == field->field) {
1694 if (!info->fields [i].mspec)
1697 MonoReflectionMarshalAsAttribute* obj;
1698 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1699 if (!mono_error_ok (&error))
1700 mono_error_set_pending_exception (&error);
1709 ICALL_EXPORT MonoReflectionField*
1710 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1713 gboolean found = FALSE;
1719 klass = handle->parent;
1721 klass = mono_class_from_mono_type (type);
1723 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1726 /* The managed code will throw the exception */
1730 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1731 mono_error_set_pending_exception (&error);
1735 ICALL_EXPORT MonoReflectionEvent*
1736 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1744 klass = handle->parent;
1746 klass = mono_class_from_mono_type (type);
1748 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1750 /* Managed code will throw an exception */
1754 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1755 mono_error_set_pending_exception (&error);
1760 ICALL_EXPORT MonoReflectionProperty*
1761 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1769 klass = handle->parent;
1771 klass = mono_class_from_mono_type (type);
1773 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1775 /* Managed code will throw an exception */
1779 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1780 mono_error_set_pending_exception (&error);
1784 ICALL_EXPORT MonoArray*
1785 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1788 MonoType *type = mono_field_get_type_checked (field->field, &error);
1791 if (!mono_error_ok (&error)) {
1792 mono_error_set_pending_exception (&error);
1796 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1797 mono_error_set_pending_exception (&error);
1802 vell_icall_get_method_attributes (MonoMethod *method)
1804 return method->flags;
1808 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1811 MonoReflectionType *rt;
1812 MonoDomain *domain = mono_domain_get ();
1813 MonoMethodSignature* sig;
1815 sig = mono_method_signature_checked (method, &error);
1816 if (!mono_error_ok (&error)) {
1817 mono_error_set_pending_exception (&error);
1821 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1822 if (!mono_error_ok (&error)) {
1823 mono_error_set_pending_exception (&error);
1827 MONO_STRUCT_SETREF (info, parent, rt);
1829 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1830 if (!mono_error_ok (&error)) {
1831 mono_error_set_pending_exception (&error);
1835 MONO_STRUCT_SETREF (info, ret, rt);
1837 info->attrs = method->flags;
1838 info->implattrs = method->iflags;
1839 if (sig->call_convention == MONO_CALL_DEFAULT)
1840 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1842 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1847 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1850 ICALL_EXPORT MonoArray*
1851 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1854 MonoDomain *domain = mono_domain_get ();
1856 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1857 mono_error_set_pending_exception (&error);
1861 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1862 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1865 MonoDomain *domain = mono_domain_get ();
1866 MonoReflectionMarshalAsAttribute* res = NULL;
1867 MonoMarshalSpec **mspecs;
1870 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1871 mono_method_get_marshal_info (method, mspecs);
1874 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1875 if (!mono_error_ok (&error)) {
1876 mono_error_set_pending_exception (&error);
1881 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1883 mono_metadata_free_marshal_spec (mspecs [i]);
1890 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1892 MonoClass *parent = field->field->parent;
1893 mono_class_setup_fields (parent);
1895 return field->field->offset - sizeof (MonoObject);
1898 ICALL_EXPORT MonoReflectionType*
1899 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1902 MonoReflectionType *ret;
1905 parent = declaring? field->field->parent: field->klass;
1907 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1908 mono_error_set_pending_exception (&error);
1914 ICALL_EXPORT MonoObject *
1915 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1918 MonoClass *fklass = field->klass;
1919 MonoClassField *cf = field->field;
1920 MonoDomain *domain = mono_object_domain (field);
1922 if (fklass->image->assembly->ref_only) {
1923 mono_set_pending_exception (mono_get_exception_invalid_operation (
1924 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1928 if (mono_security_core_clr_enabled () &&
1929 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1930 mono_error_set_pending_exception (&error);
1934 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1935 mono_error_set_pending_exception (&error);
1940 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1943 MonoClassField *cf = field->field;
1947 if (field->klass->image->assembly->ref_only) {
1948 mono_set_pending_exception (mono_get_exception_invalid_operation (
1949 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1953 if (mono_security_core_clr_enabled () &&
1954 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1955 mono_error_set_pending_exception (&error);
1959 type = mono_field_get_type_checked (cf, &error);
1960 if (!mono_error_ok (&error)) {
1961 mono_error_set_pending_exception (&error);
1965 v = (gchar *) value;
1967 switch (type->type) {
1970 case MONO_TYPE_BOOLEAN:
1973 case MONO_TYPE_CHAR:
1982 case MONO_TYPE_VALUETYPE:
1985 v += sizeof (MonoObject);
1987 case MONO_TYPE_STRING:
1988 case MONO_TYPE_OBJECT:
1989 case MONO_TYPE_CLASS:
1990 case MONO_TYPE_ARRAY:
1991 case MONO_TYPE_SZARRAY:
1994 case MONO_TYPE_GENERICINST: {
1995 MonoGenericClass *gclass = type->data.generic_class;
1996 g_assert (!gclass->context.class_inst->is_open);
1998 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1999 MonoClass *nklass = mono_class_from_mono_type (type);
2000 MonoObject *nullable;
2003 * Convert the boxed vtype into a Nullable structure.
2004 * This is complicated by the fact that Nullables have
2005 * a variable structure.
2007 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2008 if (!mono_error_ok (&error)) {
2009 mono_error_set_pending_exception (&error);
2013 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2015 v = (gchar *)mono_object_unbox (nullable);
2018 if (gclass->container_class->valuetype && (v != NULL))
2019 v += sizeof (MonoObject);
2023 g_error ("type 0x%x not handled in "
2024 "ves_icall_FieldInfo_SetValueInternal", type->type);
2029 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2030 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2031 if (!is_ok (&error)) {
2032 mono_error_set_pending_exception (&error);
2035 if (!vtable->initialized) {
2036 if (!mono_runtime_class_init_full (vtable, &error)) {
2037 mono_error_set_pending_exception (&error);
2041 mono_field_static_set_value (vtable, cf, v);
2043 mono_field_set_value (obj, cf, v);
2048 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2057 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2058 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2062 if (MONO_TYPE_IS_REFERENCE (f->type))
2063 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2065 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2068 ICALL_EXPORT MonoObject *
2069 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2071 MonoObject *o = NULL;
2072 MonoClassField *field = rfield->field;
2074 MonoDomain *domain = mono_object_domain (rfield);
2076 MonoTypeEnum def_type;
2077 const char *def_value;
2081 mono_class_init (field->parent);
2083 t = mono_field_get_type_checked (field, &error);
2084 if (!mono_error_ok (&error)) {
2085 mono_error_set_pending_exception (&error);
2089 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2090 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2094 if (image_is_dynamic (field->parent->image)) {
2095 MonoClass *klass = field->parent;
2096 int fidx = field - klass->fields;
2097 MonoClassExt *ext = mono_class_get_ext (klass);
2100 g_assert (ext->field_def_values);
2101 def_type = ext->field_def_values [fidx].def_type;
2102 def_value = ext->field_def_values [fidx].data;
2104 if (def_type == MONO_TYPE_END) {
2105 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2109 def_value = mono_class_get_field_default_value (field, &def_type);
2110 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2112 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2117 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2121 case MONO_TYPE_BOOLEAN:
2124 case MONO_TYPE_CHAR:
2132 case MONO_TYPE_R8: {
2135 /* boxed value type */
2136 t = g_new0 (MonoType, 1);
2138 klass = mono_class_from_mono_type (t);
2140 o = mono_object_new_checked (domain, klass, &error);
2141 if (!mono_error_ok (&error)) {
2142 mono_error_set_pending_exception (&error);
2145 v = ((gchar *) o) + sizeof (MonoObject);
2146 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2147 if (mono_error_set_pending_exception (&error))
2151 case MONO_TYPE_STRING:
2152 case MONO_TYPE_CLASS:
2153 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2154 if (mono_error_set_pending_exception (&error))
2158 g_assert_not_reached ();
2164 ICALL_EXPORT MonoReflectionType*
2165 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2168 MonoReflectionType *ret;
2171 type = mono_field_get_type_checked (ref_field->field, &error);
2172 if (!mono_error_ok (&error)) {
2173 mono_error_set_pending_exception (&error);
2177 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2178 if (!mono_error_ok (&error)) {
2179 mono_error_set_pending_exception (&error);
2186 /* From MonoProperty.cs */
2188 PInfo_Attributes = 1,
2189 PInfo_GetMethod = 1 << 1,
2190 PInfo_SetMethod = 1 << 2,
2191 PInfo_ReflectedType = 1 << 3,
2192 PInfo_DeclaringType = 1 << 4,
2197 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2200 MonoReflectionType *rt;
2201 MonoReflectionMethod *rm;
2202 MonoDomain *domain = mono_object_domain (property);
2203 const MonoProperty *pproperty = property->property;
2205 if ((req_info & PInfo_ReflectedType) != 0) {
2206 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2207 if (mono_error_set_pending_exception (&error))
2210 MONO_STRUCT_SETREF (info, parent, rt);
2212 if ((req_info & PInfo_DeclaringType) != 0) {
2213 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2214 if (mono_error_set_pending_exception (&error))
2217 MONO_STRUCT_SETREF (info, declaring_type, rt);
2220 if ((req_info & PInfo_Name) != 0)
2221 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2223 if ((req_info & PInfo_Attributes) != 0)
2224 info->attrs = pproperty->attrs;
2226 if ((req_info & PInfo_GetMethod) != 0) {
2227 if (pproperty->get &&
2228 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2229 pproperty->get->klass == property->klass)) {
2230 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2231 if (mono_error_set_pending_exception (&error))
2237 MONO_STRUCT_SETREF (info, get, rm);
2239 if ((req_info & PInfo_SetMethod) != 0) {
2240 if (pproperty->set &&
2241 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2242 pproperty->set->klass == property->klass)) {
2243 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2244 if (mono_error_set_pending_exception (&error))
2250 MONO_STRUCT_SETREF (info, set, rm);
2253 * There may be other methods defined for properties, though, it seems they are not exposed
2254 * in the reflection API
2259 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2262 MonoReflectionType *rt;
2263 MonoReflectionMethod *rm;
2264 MonoDomain *domain = mono_object_domain (event);
2266 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2267 if (mono_error_set_pending_exception (&error))
2270 MONO_STRUCT_SETREF (info, reflected_type, rt);
2272 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2273 if (mono_error_set_pending_exception (&error))
2276 MONO_STRUCT_SETREF (info, declaring_type, rt);
2278 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2279 info->attrs = event->event->attrs;
2281 if (event->event->add) {
2282 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2283 if (mono_error_set_pending_exception (&error))
2289 MONO_STRUCT_SETREF (info, add_method, rm);
2291 if (event->event->remove) {
2292 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2293 if (mono_error_set_pending_exception (&error))
2299 MONO_STRUCT_SETREF (info, remove_method, rm);
2301 if (event->event->raise) {
2302 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2303 if (mono_error_set_pending_exception (&error))
2309 MONO_STRUCT_SETREF (info, raise_method, rm);
2311 #ifndef MONO_SMALL_CONFIG
2312 if (event->event->other) {
2314 while (event->event->other [n])
2316 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2317 if (mono_error_set_pending_exception (&error))
2319 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2321 for (i = 0; i < n; i++) {
2322 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2323 if (mono_error_set_pending_exception (&error))
2325 mono_array_setref (info->other_methods, i, rm);
2332 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2337 mono_class_setup_interfaces (klass, error);
2338 if (!mono_error_ok (error))
2341 for (i = 0; i < klass->interface_count; i++) {
2342 ic = klass->interfaces [i];
2343 g_hash_table_insert (ifaces, ic, ic);
2345 collect_interfaces (ic, ifaces, error);
2346 if (!mono_error_ok (error))
2352 MonoArray *iface_array;
2353 MonoGenericContext *context;
2357 } FillIfaceArrayData;
2360 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2362 MonoReflectionType *rt;
2363 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2364 MonoClass *ic = (MonoClass *)key;
2365 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2367 if (!mono_error_ok (data->error))
2370 if (data->context && mono_class_is_ginst (ic) && mono_class_get_generic_class (ic)->context.class_inst->is_open) {
2371 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2372 if (!mono_error_ok (data->error))
2376 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2377 if (!mono_error_ok (data->error))
2380 mono_array_setref (data->iface_array, data->next_idx++, rt);
2383 mono_metadata_free_type (inflated);
2387 get_interfaces_hash (gconstpointer v1)
2389 MonoClass *k = (MonoClass*)v1;
2391 return k->type_token;
2394 ICALL_EXPORT MonoArray*
2395 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2398 MonoClass *klass = mono_class_from_mono_type (type->type);
2400 FillIfaceArrayData data = { 0 };
2403 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2405 if (mono_class_is_ginst (klass) && mono_class_get_generic_class (klass)->context.class_inst->is_open) {
2406 data.context = mono_class_get_context (klass);
2407 klass = mono_class_get_generic_class (klass)->container_class;
2410 for (parent = klass; parent; parent = parent->parent) {
2411 mono_class_setup_interfaces (parent, &error);
2412 if (!mono_error_ok (&error))
2414 collect_interfaces (parent, iface_hash, &error);
2415 if (!mono_error_ok (&error))
2419 data.error = &error;
2420 data.domain = mono_object_domain (type);
2422 len = g_hash_table_size (iface_hash);
2424 g_hash_table_destroy (iface_hash);
2425 if (!data.domain->empty_types) {
2426 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2427 if (!is_ok (&error))
2430 return data.domain->empty_types;
2433 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2434 if (!is_ok (&error))
2436 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2437 if (!mono_error_ok (&error))
2440 g_hash_table_destroy (iface_hash);
2441 return data.iface_array;
2444 g_hash_table_destroy (iface_hash);
2445 mono_error_set_pending_exception (&error);
2450 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2452 gboolean variance_used;
2453 MonoClass *klass = mono_class_from_mono_type (type->type);
2454 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2455 MonoReflectionMethod *member;
2458 int i = 0, len, ioffset;
2462 mono_class_init_checked (klass, &error);
2463 if (mono_error_set_pending_exception (&error))
2465 mono_class_init_checked (iclass, &error);
2466 if (mono_error_set_pending_exception (&error))
2469 mono_class_setup_vtable (klass);
2471 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2475 len = mono_class_num_methods (iclass);
2476 domain = mono_object_domain (type);
2477 MonoArray *targets_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 (targets, (MonoObject*) targets_arr);
2481 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2482 if (mono_error_set_pending_exception (&error))
2484 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2486 while ((method = mono_class_get_methods (iclass, &iter))) {
2487 member = mono_method_get_object_checked (domain, method, iclass, &error);
2488 if (mono_error_set_pending_exception (&error))
2490 mono_array_setref (*methods, i, member);
2491 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2492 if (mono_error_set_pending_exception (&error))
2494 mono_array_setref (*targets, i, member);
2501 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2504 MonoClass *klass = mono_class_from_mono_type (type->type);
2506 mono_class_init_checked (klass, &error);
2507 if (mono_error_set_pending_exception (&error))
2510 if (image_is_dynamic (klass->image)) {
2511 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2512 *packing = tb->packing_size;
2513 *size = tb->class_size;
2515 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2519 ICALL_EXPORT MonoReflectionType*
2520 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2523 MonoReflectionType *ret;
2526 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2527 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2528 mono_error_set_pending_exception (&error);
2532 klass = mono_class_from_mono_type (type->type);
2533 mono_class_init_checked (klass, &error);
2534 if (mono_error_set_pending_exception (&error))
2538 // GetElementType should only return a type for:
2539 // Array Pointer PassedByRef
2540 if (type->type->byref)
2541 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2542 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2543 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2544 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2545 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2549 mono_error_set_pending_exception (&error);
2554 ICALL_EXPORT MonoReflectionType*
2555 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2558 MonoReflectionType *ret;
2560 if (type->type->byref)
2563 MonoClass *klass = mono_class_from_mono_type (type->type);
2567 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2568 mono_error_set_pending_exception (&error);
2573 ICALL_EXPORT MonoBoolean
2574 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2576 return type->type->type == MONO_TYPE_PTR;
2579 ICALL_EXPORT MonoBoolean
2580 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2582 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)));
2585 ICALL_EXPORT MonoBoolean
2586 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2588 return type->type->byref;
2591 ICALL_EXPORT MonoBoolean
2592 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2595 MonoClass *klass = mono_class_from_mono_type (type->type);
2596 mono_class_init_checked (klass, &error);
2597 if (mono_error_set_pending_exception (&error))
2600 return mono_class_is_com_object (klass);
2603 ICALL_EXPORT guint32
2604 ves_icall_reflection_get_token (MonoObject* obj)
2607 guint32 result = mono_reflection_get_token_checked (obj, &error);
2608 mono_error_set_pending_exception (&error);
2612 ICALL_EXPORT MonoReflectionModule*
2613 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2616 MonoReflectionModule *result = NULL;
2617 MonoClass *klass = mono_class_from_mono_type (type->type);
2618 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2619 mono_error_set_pending_exception (&error);
2623 ICALL_EXPORT MonoReflectionAssembly*
2624 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2627 MonoDomain *domain = mono_domain_get ();
2628 MonoClass *klass = mono_class_from_mono_type (type->type);
2629 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2630 mono_error_set_pending_exception (&error);
2634 ICALL_EXPORT MonoReflectionType*
2635 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2638 MonoReflectionType *ret;
2639 MonoDomain *domain = mono_domain_get ();
2642 if (type->type->byref)
2644 if (type->type->type == MONO_TYPE_VAR) {
2645 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2646 klass = param ? param->owner.klass : NULL;
2647 } else if (type->type->type == MONO_TYPE_MVAR) {
2648 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2649 klass = param ? param->owner.method->klass : NULL;
2651 klass = mono_class_from_mono_type (type->type)->nested_in;
2657 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2658 mono_error_set_pending_exception (&error);
2663 ICALL_EXPORT MonoStringHandle
2664 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2666 MonoDomain *domain = mono_domain_get ();
2667 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2668 MonoClass *klass = mono_class_from_mono_type (type);
2671 char *n = g_strdup_printf ("%s&", klass->name);
2672 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2678 return mono_string_new_handle (domain, klass->name, error);
2682 ICALL_EXPORT MonoStringHandle
2683 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2685 MonoDomain *domain = mono_domain_get ();
2686 MonoClass *klass = mono_class_from_mono_type_handle (type);
2688 while (klass->nested_in)
2689 klass = klass->nested_in;
2691 if (klass->name_space [0] == '\0')
2692 return NULL_HANDLE_STRING;
2694 return mono_string_new_handle (domain, klass->name_space, error);
2698 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2702 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2703 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2707 klass = mono_class_from_mono_type (type->type);
2713 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2715 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2718 ICALL_EXPORT MonoArray*
2719 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2722 MonoReflectionType *rt;
2724 MonoClass *klass, *pklass;
2725 MonoDomain *domain = mono_object_domain (type);
2728 klass = mono_class_from_mono_type (type->type);
2730 if (mono_class_is_gtd (klass)) {
2731 MonoGenericContainer *container = mono_class_get_generic_container (klass);
2732 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2733 if (mono_error_set_pending_exception (&error))
2735 for (i = 0; i < container->type_argc; ++i) {
2736 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2738 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2739 if (mono_error_set_pending_exception (&error))
2742 mono_array_setref (res, i, rt);
2744 } else if (mono_class_is_ginst (klass)) {
2745 MonoGenericInst *inst = mono_class_get_generic_class (klass)->context.class_inst;
2746 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2747 if (mono_error_set_pending_exception (&error))
2749 for (i = 0; i < inst->type_argc; ++i) {
2750 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2751 if (mono_error_set_pending_exception (&error))
2754 mono_array_setref (res, i, rt);
2762 ICALL_EXPORT gboolean
2763 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2767 if (!IS_MONOTYPE (type))
2770 if (type->type->byref)
2773 klass = mono_class_from_mono_type (type->type);
2774 return mono_class_is_gtd (klass);
2777 ICALL_EXPORT MonoReflectionType*
2778 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2781 MonoReflectionType *ret;
2784 if (type->type->byref)
2787 klass = mono_class_from_mono_type (type->type);
2789 if (mono_class_is_gtd (klass)) {
2790 return type; /* check this one */
2792 if (mono_class_is_ginst (klass)) {
2793 MonoClass *generic_class = mono_class_get_generic_class (klass)->container_class;
2796 tb = mono_class_get_ref_info (generic_class);
2798 if (generic_class->wastypebuilder && tb)
2799 return (MonoReflectionType *)tb;
2801 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2802 mono_error_set_pending_exception (&error);
2810 ICALL_EXPORT MonoReflectionType*
2811 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2814 MonoReflectionType *ret;
2816 MonoType *geninst, **types;
2819 g_assert (IS_MONOTYPE (type));
2820 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2821 if (mono_error_set_pending_exception (&error))
2824 count = mono_array_length (type_array);
2825 types = g_new0 (MonoType *, count);
2827 for (i = 0; i < count; i++) {
2828 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2829 types [i] = t->type;
2832 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2835 mono_error_set_pending_exception (&error);
2839 klass = mono_class_from_mono_type (geninst);
2841 /*we might inflate to the GTD*/
2842 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2843 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2847 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2848 mono_error_set_pending_exception (&error);
2853 ICALL_EXPORT gboolean
2854 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2858 if (!IS_MONOTYPE (type))
2861 if (type->type->byref)
2864 klass = mono_class_from_mono_type (type->type);
2865 return mono_class_is_ginst (klass) || mono_class_is_gtd (klass);
2869 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2871 if (!IS_MONOTYPE (type))
2874 if (is_generic_parameter (type->type))
2875 return mono_type_get_generic_param_num (type->type);
2879 ICALL_EXPORT MonoGenericParamInfo *
2880 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2882 return mono_generic_param_info (type->type->data.generic_param);
2885 ICALL_EXPORT MonoBoolean
2886 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2888 return is_generic_parameter (type->type);
2891 ICALL_EXPORT MonoReflectionMethod*
2892 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2893 MonoReflectionMethod* generic)
2900 MonoReflectionMethod *ret = NULL;
2902 domain = ((MonoObject *)type)->vtable->domain;
2904 klass = mono_class_from_mono_type (type->type);
2905 mono_class_init_checked (klass, &error);
2906 if (mono_error_set_pending_exception (&error))
2910 while ((method = mono_class_get_methods (klass, &iter))) {
2911 if (method->token == generic->method->token) {
2912 ret = mono_method_get_object_checked (domain, method, klass, &error);
2913 if (mono_error_set_pending_exception (&error))
2921 ICALL_EXPORT MonoReflectionMethod *
2922 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2925 MonoType *type = ref_type->type;
2927 MonoReflectionMethod *ret = NULL;
2929 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2930 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2933 if (type->type == MONO_TYPE_VAR)
2936 method = mono_type_get_generic_param_owner (type)->owner.method;
2939 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2940 if (!mono_error_ok (&error))
2941 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2945 ICALL_EXPORT MonoBoolean
2946 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2948 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2952 ICALL_EXPORT MonoBoolean
2953 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2955 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2960 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2962 MonoDomain *domain = mono_domain_get ();
2963 MonoImage *image = method->method->klass->image;
2964 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2965 MonoTableInfo *tables = image->tables;
2966 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2967 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2968 guint32 im_cols [MONO_IMPLMAP_SIZE];
2969 guint32 scope_token;
2970 const char *import = NULL;
2971 const char *scope = NULL;
2973 if (image_is_dynamic (image)) {
2974 MonoReflectionMethodAux *method_aux =
2975 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2977 import = method_aux->dllentry;
2978 scope = method_aux->dll;
2981 if (!import || !scope) {
2982 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2987 if (piinfo->implmap_idx) {
2988 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2990 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2991 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2992 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2993 scope = mono_metadata_string_heap (image, scope_token);
2997 *flags = piinfo->piflags;
2998 *entry_point = mono_string_new (domain, import);
2999 *dll_name = mono_string_new (domain, scope);
3002 ICALL_EXPORT MonoReflectionMethod *
3003 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3005 MonoMethodInflated *imethod;
3007 MonoReflectionMethod *ret = NULL;
3010 if (method->method->is_generic)
3013 if (!method->method->is_inflated)
3016 imethod = (MonoMethodInflated *) method->method;
3018 result = imethod->declaring;
3019 /* Not a generic method. */
3020 if (!result->is_generic)
3023 if (image_is_dynamic (method->method->klass->image)) {
3024 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3025 MonoReflectionMethod *res;
3028 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3029 * the dynamic case as well ?
3031 mono_image_lock ((MonoImage*)image);
3032 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3033 mono_image_unlock ((MonoImage*)image);
3039 if (imethod->context.class_inst) {
3040 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3041 /*Generic methods gets the context of the GTD.*/
3042 if (mono_class_get_context (klass)) {
3043 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3044 if (!mono_error_ok (&error))
3049 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3051 if (!mono_error_ok (&error))
3052 mono_error_set_pending_exception (&error);
3056 ICALL_EXPORT gboolean
3057 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3059 return mono_method_signature (method->method)->generic_param_count != 0;
3062 ICALL_EXPORT gboolean
3063 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3065 return method->method->is_generic;
3068 ICALL_EXPORT MonoArray*
3069 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3072 MonoReflectionType *rt;
3077 domain = mono_object_domain (method);
3079 if (method->method->is_inflated) {
3080 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3083 count = inst->type_argc;
3084 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3085 if (mono_error_set_pending_exception (&error))
3088 for (i = 0; i < count; i++) {
3089 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3090 if (mono_error_set_pending_exception (&error))
3093 mono_array_setref (res, i, rt);
3100 count = mono_method_signature (method->method)->generic_param_count;
3101 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3102 if (mono_error_set_pending_exception (&error))
3105 for (i = 0; i < count; i++) {
3106 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3107 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3108 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3110 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3111 if (mono_error_set_pending_exception (&error))
3114 mono_array_setref (res, i, rt);
3120 ICALL_EXPORT MonoObject *
3121 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3125 * Invoke from reflection is supposed to always be a virtual call (the API
3126 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3127 * greater flexibility.
3129 MonoMethod *m = method->method;
3130 MonoMethodSignature *sig = mono_method_signature (m);
3133 void *obj = this_arg;
3137 if (mono_security_core_clr_enabled () &&
3138 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3139 mono_error_set_pending_exception (&error);
3143 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3144 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3145 mono_error_cleanup (&error); /* FIXME does this make sense? */
3146 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3151 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3152 if (!is_ok (&error)) {
3153 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3156 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3157 char *target_name = mono_type_get_full_name (m->klass);
3158 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3159 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3161 g_free (target_name);
3165 m = mono_object_get_virtual_method (this_arg, m);
3166 /* must pass the pointer to the value for valuetype methods */
3167 if (m->klass->valuetype)
3168 obj = mono_object_unbox (this_arg);
3169 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3170 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3175 if (sig->ret->byref) {
3176 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"));
3180 pcount = params? mono_array_length (params): 0;
3181 if (pcount != sig->param_count) {
3182 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3186 if (mono_class_is_abstract (m->klass) && !strcmp (m->name, ".ctor") && !this_arg) {
3187 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."));
3191 image = m->klass->image;
3192 if (image->assembly->ref_only) {
3193 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."));
3197 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3198 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3202 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3206 intptr_t *lower_bounds;
3207 pcount = mono_array_length (params);
3208 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3209 /* Note: the synthetized array .ctors have int32 as argument type */
3210 for (i = 0; i < pcount; ++i)
3211 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3213 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3214 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3215 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3216 if (!mono_error_ok (&error)) {
3217 mono_error_set_pending_exception (&error);
3221 for (i = 0; i < mono_array_length (arr); ++i) {
3222 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3223 if (!mono_error_ok (&error)) {
3224 mono_error_set_pending_exception (&error);
3227 mono_array_setref_fast (arr, i, subarray);
3229 return (MonoObject*)arr;
3232 if (m->klass->rank == pcount) {
3233 /* Only lengths provided. */
3234 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3235 if (!mono_error_ok (&error)) {
3236 mono_error_set_pending_exception (&error);
3240 return (MonoObject*)arr;
3242 g_assert (pcount == (m->klass->rank * 2));
3243 /* The arguments are lower-bound-length pairs */
3244 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3246 for (i = 0; i < pcount / 2; ++i) {
3247 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3248 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3251 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3252 if (!mono_error_ok (&error)) {
3253 mono_error_set_pending_exception (&error);
3257 return (MonoObject*)arr;
3260 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3261 mono_error_set_pending_exception (&error);
3265 #ifndef DISABLE_REMOTING
3266 ICALL_EXPORT MonoObject *
3267 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3270 MonoDomain *domain = mono_object_domain (method);
3271 MonoMethod *m = method->method;
3272 MonoMethodSignature *sig = mono_method_signature (m);
3273 MonoArray *out_args;
3275 int i, j, outarg_count = 0;
3277 if (m->klass == mono_defaults.object_class) {
3278 if (!strcmp (m->name, "FieldGetter")) {
3279 MonoClass *k = this_arg->vtable->klass;
3283 /* If this is a proxy, then it must be a CBO */
3284 if (k == mono_defaults.transparent_proxy_class) {
3285 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3286 this_arg = tp->rp->unwrapped_server;
3287 g_assert (this_arg);
3288 k = this_arg->vtable->klass;
3291 name = mono_array_get (params, MonoString *, 1);
3292 str = mono_string_to_utf8_checked (name, &error);
3293 if (mono_error_set_pending_exception (&error))
3297 MonoClassField* field = mono_class_get_field_from_name (k, str);
3300 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3301 if (field_klass->valuetype) {
3302 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3303 if (mono_error_set_pending_exception (&error))
3306 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3308 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3309 if (mono_error_set_pending_exception (&error))
3311 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3312 mono_array_setref (out_args, 0, result);
3319 g_assert_not_reached ();
3321 } else if (!strcmp (m->name, "FieldSetter")) {
3322 MonoClass *k = this_arg->vtable->klass;
3328 /* If this is a proxy, then it must be a CBO */
3329 if (k == mono_defaults.transparent_proxy_class) {
3330 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3331 this_arg = tp->rp->unwrapped_server;
3332 g_assert (this_arg);
3333 k = this_arg->vtable->klass;
3336 name = mono_array_get (params, MonoString *, 1);
3337 str = mono_string_to_utf8_checked (name, &error);
3338 if (mono_error_set_pending_exception (&error))
3342 MonoClassField* field = mono_class_get_field_from_name (k, str);
3345 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3346 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3348 if (field_klass->valuetype) {
3349 size = mono_type_size (field->type, &align);
3350 g_assert (size == mono_class_value_size (field_klass, NULL));
3351 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3353 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3356 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3357 if (mono_error_set_pending_exception (&error))
3359 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3368 g_assert_not_reached ();
3373 for (i = 0; i < mono_array_length (params); i++) {
3374 if (sig->params [i]->byref)
3378 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3379 if (mono_error_set_pending_exception (&error))
3382 /* handle constructors only for objects already allocated */
3383 if (!strcmp (method->method->name, ".ctor"))
3384 g_assert (this_arg);
3386 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3387 g_assert (!method->method->klass->valuetype);
3388 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3389 if (mono_error_set_pending_exception (&error))
3392 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3393 if (sig->params [i]->byref) {
3395 arg = mono_array_get (params, gpointer, i);
3396 mono_array_setref (out_args, j, arg);
3401 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3408 read_enum_value (const char *mem, int type)
3411 case MONO_TYPE_BOOLEAN:
3413 return *(guint8*)mem;
3415 return *(gint8*)mem;
3416 case MONO_TYPE_CHAR:
3418 return read16 (mem);
3420 return (gint16) read16 (mem);
3422 return read32 (mem);
3424 return (gint32) read32 (mem);
3427 return read64 (mem);
3429 g_assert_not_reached ();
3435 write_enum_value (char *mem, int type, guint64 value)
3439 case MONO_TYPE_I1: {
3440 guint8 *p = (guint8*)mem;
3446 case MONO_TYPE_CHAR: {
3447 guint16 *p = (guint16 *)mem;
3452 case MONO_TYPE_I4: {
3453 guint32 *p = (guint32 *)mem;
3458 case MONO_TYPE_I8: {
3459 guint64 *p = (guint64 *)mem;
3464 g_assert_not_reached ();
3469 ICALL_EXPORT MonoObject *
3470 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3478 domain = mono_object_domain (enumType);
3479 enumc = mono_class_from_mono_type (enumType->type);
3481 mono_class_init_checked (enumc, &error);
3482 if (mono_error_set_pending_exception (&error))
3485 etype = mono_class_enum_basetype (enumc);
3487 res = mono_object_new_checked (domain, enumc, &error);
3488 if (mono_error_set_pending_exception (&error))
3490 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3495 ICALL_EXPORT MonoBoolean
3496 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3498 int size = mono_class_value_size (a->vtable->klass, NULL);
3499 guint64 a_val = 0, b_val = 0;
3501 memcpy (&a_val, mono_object_unbox (a), size);
3502 memcpy (&b_val, mono_object_unbox (b), size);
3504 return (a_val & b_val) == b_val;
3507 ICALL_EXPORT MonoObject *
3508 ves_icall_System_Enum_get_value (MonoObject *eobj)
3520 g_assert (eobj->vtable->klass->enumtype);
3522 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3523 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3524 if (mono_error_set_pending_exception (&error))
3526 dst = (char *)res + sizeof (MonoObject);
3527 src = (char *)eobj + sizeof (MonoObject);
3528 size = mono_class_value_size (enumc, NULL);
3530 memcpy (dst, src, size);
3535 ICALL_EXPORT MonoReflectionType *
3536 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3539 MonoReflectionType *ret;
3543 klass = mono_class_from_mono_type (type->type);
3544 mono_class_init_checked (klass, &error);
3545 if (mono_error_set_pending_exception (&error))
3548 etype = mono_class_enum_basetype (klass);
3550 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3554 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3555 mono_error_set_pending_exception (&error);
3561 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3563 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3564 gpointer odata = (char *)other + sizeof (MonoObject);
3565 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3566 g_assert (basetype);
3571 if (eobj->vtable->klass != other->vtable->klass)
3574 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3575 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3576 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3579 return me > other ? 1 : -1; \
3582 switch (basetype->type) {
3584 COMPARE_ENUM_VALUES (guint8);
3586 COMPARE_ENUM_VALUES (gint8);
3587 case MONO_TYPE_CHAR:
3589 COMPARE_ENUM_VALUES (guint16);
3591 COMPARE_ENUM_VALUES (gint16);
3593 COMPARE_ENUM_VALUES (guint32);
3595 COMPARE_ENUM_VALUES (gint32);
3597 COMPARE_ENUM_VALUES (guint64);
3599 COMPARE_ENUM_VALUES (gint64);
3603 #undef COMPARE_ENUM_VALUES
3604 /* indicates that the enum was of an unsupported unerlying type */
3609 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3611 gpointer data = (char *)eobj + sizeof (MonoObject);
3612 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3613 g_assert (basetype);
3615 switch (basetype->type) {
3616 case MONO_TYPE_I1: {
3617 gint8 value = *((gint8*)data);
3618 return ((int)value ^ (int)value << 8);
3621 return *((guint8*)data);
3622 case MONO_TYPE_CHAR:
3624 return *((guint16*)data);
3626 case MONO_TYPE_I2: {
3627 gint16 value = *((gint16*)data);
3628 return ((int)(guint16)value | (((int)value) << 16));
3631 return *((guint32*)data);
3633 return *((gint32*)data);
3635 case MONO_TYPE_I8: {
3636 gint64 value = *((gint64*)data);
3637 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3640 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3646 get_enum_field (MonoDomain *domain, MonoArrayHandle names, MonoArrayHandle values, int base_type, MonoClassField *field, guint* j, guint64 *previous_value, gboolean *sorted, MonoError *error)
3648 mono_error_init (error);
3649 HANDLE_FUNCTION_ENTER();
3650 guint64 field_value;
3652 MonoTypeEnum def_type;
3654 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3656 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3658 if (mono_field_is_deleted (field))
3660 MonoStringHandle name = mono_string_new_handle (domain, mono_field_get_name (field), error);
3663 MONO_HANDLE_ARRAY_SETREF (names, *j, name);
3665 p = mono_class_get_field_default_value (field, &def_type);
3666 /* len = */ mono_metadata_decode_blob_size (p, &p);
3668 field_value = read_enum_value (p, base_type);
3669 MONO_HANDLE_ARRAY_SETVAL (values, guint64, *j, field_value);
3671 if (*previous_value > field_value)
3674 *previous_value = field_value;
3677 HANDLE_FUNCTION_RETURN();
3680 ICALL_EXPORT MonoBoolean
3681 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionTypeHandle type, MonoArrayHandleOut values, MonoArrayHandleOut names, MonoError *error)
3683 MonoDomain *domain = MONO_HANDLE_DOMAIN (type);
3684 MonoClass *enumc = mono_class_from_mono_type (MONO_HANDLE_RAW(type)->type);
3685 guint j = 0, nvalues;
3687 MonoClassField *field;
3689 guint64 previous_value = 0;
3690 gboolean sorted = TRUE;
3692 mono_error_init (error);
3693 mono_class_init_checked (enumc, error);
3694 return_val_if_nok (error, FALSE);
3696 if (!enumc->enumtype) {
3697 mono_error_set_argument (error, "enumType", "Type provided must be an Enum.");
3701 base_type = mono_class_enum_basetype (enumc)->type;
3703 nvalues = mono_class_num_fields (enumc) > 0 ? mono_class_num_fields (enumc) - 1 : 0;
3704 MONO_HANDLE_ASSIGN(names, mono_array_new_handle (domain, mono_defaults.string_class, nvalues, error));
3705 return_val_if_nok (error, FALSE);
3706 MONO_HANDLE_ASSIGN(values, mono_array_new_handle (domain, mono_defaults.uint64_class, nvalues, error));
3707 return_val_if_nok (error, FALSE);
3710 while ((field = mono_class_get_fields (enumc, &iter))) {
3711 get_enum_field(domain, names, values, base_type, field, &j, &previous_value, &sorted, error);
3715 return_val_if_nok (error, FALSE);
3721 BFLAGS_IgnoreCase = 1,
3722 BFLAGS_DeclaredOnly = 2,
3723 BFLAGS_Instance = 4,
3725 BFLAGS_Public = 0x10,
3726 BFLAGS_NonPublic = 0x20,
3727 BFLAGS_FlattenHierarchy = 0x40,
3728 BFLAGS_InvokeMethod = 0x100,
3729 BFLAGS_CreateInstance = 0x200,
3730 BFLAGS_GetField = 0x400,
3731 BFLAGS_SetField = 0x800,
3732 BFLAGS_GetProperty = 0x1000,
3733 BFLAGS_SetProperty = 0x2000,
3734 BFLAGS_ExactBinding = 0x10000,
3735 BFLAGS_SuppressChangeType = 0x20000,
3736 BFLAGS_OptionalParamBinding = 0x40000
3739 ICALL_EXPORT GPtrArray*
3740 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3743 MonoClass *startklass, *klass;
3746 int (*compare_func) (const char *s1, const char *s2) = NULL;
3747 MonoClassField *field;
3749 if (type->type->byref) {
3750 return g_ptr_array_new ();
3753 mono_error_init (&error);
3755 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3757 klass = startklass = mono_class_from_mono_type (type->type);
3759 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3762 if (mono_class_has_failure (klass)) {
3763 mono_error_set_for_class_failure (&error, klass);
3768 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3769 guint32 flags = mono_field_get_flags (field);
3771 if (mono_field_is_deleted_with_flags (field, flags))
3773 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3774 if (bflags & BFLAGS_Public)
3776 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3777 if (bflags & BFLAGS_NonPublic) {
3784 if (flags & FIELD_ATTRIBUTE_STATIC) {
3785 if (bflags & BFLAGS_Static)
3786 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3789 if (bflags & BFLAGS_Instance)
3796 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3799 g_ptr_array_add (ptr_array, field);
3801 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3807 g_ptr_array_free (ptr_array, TRUE);
3808 mono_error_set_pending_exception (&error);
3813 method_nonpublic (MonoMethod* method, gboolean start_klass)
3815 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3816 case METHOD_ATTRIBUTE_ASSEM:
3817 return (start_klass || mono_defaults.generic_ilist_class);
3818 case METHOD_ATTRIBUTE_PRIVATE:
3820 case METHOD_ATTRIBUTE_PUBLIC:
3828 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3831 MonoClass *startklass;
3835 /*FIXME, use MonoBitSet*/
3836 guint32 method_slots_default [8];
3837 guint32 *method_slots = NULL;
3838 int (*compare_func) (const char *s1, const char *s2) = NULL;
3840 array = g_ptr_array_new ();
3842 mono_error_init (error);
3845 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3847 /* An optimization for calls made from Delegate:CreateDelegate () */
3848 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3849 method = mono_get_delegate_invoke (klass);
3852 g_ptr_array_add (array, method);
3856 mono_class_setup_methods (klass);
3857 mono_class_setup_vtable (klass);
3858 if (mono_class_has_failure (klass))
3861 if (is_generic_parameter (&klass->byval_arg))
3862 nslots = mono_class_get_vtable_size (klass->parent);
3864 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3865 if (nslots >= sizeof (method_slots_default) * 8) {
3866 method_slots = g_new0 (guint32, nslots / 32 + 1);
3868 method_slots = method_slots_default;
3869 memset (method_slots, 0, sizeof (method_slots_default));
3872 mono_class_setup_methods (klass);
3873 mono_class_setup_vtable (klass);
3874 if (mono_class_has_failure (klass))
3878 while ((method = mono_class_get_methods (klass, &iter))) {
3880 if (method->slot != -1) {
3881 g_assert (method->slot < nslots);
3882 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3884 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3885 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3888 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3890 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3891 if (bflags & BFLAGS_Public)
3893 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3899 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3900 if (bflags & BFLAGS_Static)
3901 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3904 if (bflags & BFLAGS_Instance)
3912 if (compare_func (name, method->name))
3917 g_ptr_array_add (array, method);
3919 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3921 if (method_slots != method_slots_default)
3922 g_free (method_slots);
3927 if (method_slots != method_slots_default)
3928 g_free (method_slots);
3929 g_ptr_array_free (array, TRUE);
3931 g_assert (mono_class_has_failure (klass));
3932 mono_error_set_for_class_failure (error, klass);
3936 ICALL_EXPORT GPtrArray*
3937 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3940 GPtrArray *method_array;
3943 klass = mono_class_from_mono_type (type->type);
3944 if (type->type->byref) {
3945 return g_ptr_array_new ();
3948 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3949 mono_error_set_pending_exception (&error);
3950 return method_array;
3953 ICALL_EXPORT GPtrArray*
3954 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3956 MonoClass *startklass, *klass;
3959 gpointer iter = NULL;
3960 GPtrArray *res_array;
3963 if (type->type->byref) {
3964 return g_ptr_array_new ();
3967 klass = startklass = mono_class_from_mono_type (type->type);
3969 mono_class_setup_methods (klass);
3970 if (mono_class_has_failure (klass)) {
3971 mono_error_init (&error);
3972 mono_error_set_for_class_failure (&error, klass);
3973 mono_error_set_pending_exception (&error);
3977 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3980 while ((method = mono_class_get_methods (klass, &iter))) {
3982 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3984 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3985 if (bflags & BFLAGS_Public)
3988 if (bflags & BFLAGS_NonPublic)
3994 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3995 if (bflags & BFLAGS_Static)
3996 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3999 if (bflags & BFLAGS_Instance)
4005 g_ptr_array_add (res_array, method);
4012 property_hash (gconstpointer data)
4014 MonoProperty *prop = (MonoProperty*)data;
4016 return g_str_hash (prop->name);
4020 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4022 if (method1->slot != -1 && method1->slot == method2->slot)
4025 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4026 if (method1->is_inflated)
4027 method1 = ((MonoMethodInflated*) method1)->declaring;
4028 if (method2->is_inflated)
4029 method2 = ((MonoMethodInflated*) method2)->declaring;
4032 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4036 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4038 // Properties are hide-by-name-and-signature
4039 if (!g_str_equal (prop1->name, prop2->name))
4042 /* If we see a property in a generic method, we want to
4043 compare the generic signatures, not the inflated signatures
4044 because we might conflate two properties that were
4048 public T this[T t] { getter { return t; } } // method 1
4049 public U this[U u] { getter { return u; } } // method 2
4052 If we see int Foo<int,int>::Item[int] we need to know if
4053 the indexer came from method 1 or from method 2, and we
4054 shouldn't conflate them. (Bugzilla 36283)
4056 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4059 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4066 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4071 return method_nonpublic (accessor, start_klass);
4074 ICALL_EXPORT GPtrArray*
4075 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4078 MonoClass *startklass, *klass;
4083 int (*compare_func) (const char *s1, const char *s2) = NULL;
4085 GHashTable *properties = NULL;
4086 GPtrArray *res_array;
4088 if (type->type->byref) {
4089 return g_ptr_array_new ();
4092 mono_error_init (&error);
4094 klass = startklass = mono_class_from_mono_type (type->type);
4096 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4098 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4100 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4102 mono_class_setup_methods (klass);
4103 mono_class_setup_vtable (klass);
4104 if (mono_class_has_failure (klass)) {
4105 mono_error_set_for_class_failure (&error, klass);
4110 while ((prop = mono_class_get_properties (klass, &iter))) {
4116 flags = method->flags;
4119 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4120 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4121 if (bflags & BFLAGS_Public)
4123 } else if (bflags & BFLAGS_NonPublic) {
4124 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4125 property_accessor_nonpublic(prop->set, startklass == klass)) {
4132 if (flags & METHOD_ATTRIBUTE_STATIC) {
4133 if (bflags & BFLAGS_Static)
4134 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4137 if (bflags & BFLAGS_Instance)
4145 if (propname != NULL && compare_func (propname, prop->name))
4148 if (g_hash_table_lookup (properties, prop))
4151 g_ptr_array_add (res_array, prop);
4153 g_hash_table_insert (properties, prop, prop);
4155 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4158 g_hash_table_destroy (properties);
4165 g_hash_table_destroy (properties);
4166 g_ptr_array_free (res_array, TRUE);
4168 mono_error_set_pending_exception (&error);
4174 event_hash (gconstpointer data)
4176 MonoEvent *event = (MonoEvent*)data;
4178 return g_str_hash (event->name);
4182 event_equal (MonoEvent *event1, MonoEvent *event2)
4184 // Events are hide-by-name
4185 return g_str_equal (event1->name, event2->name);
4188 ICALL_EXPORT GPtrArray*
4189 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4192 MonoClass *startklass, *klass;
4197 int (*compare_func) (const char *s1, const char *s2) = NULL;
4198 GHashTable *events = NULL;
4199 GPtrArray *res_array;
4201 if (type->type->byref) {
4202 return g_ptr_array_new ();
4205 mono_error_init (&error);
4207 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4209 res_array = g_ptr_array_sized_new (4);
4211 klass = startklass = mono_class_from_mono_type (type->type);
4213 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4215 mono_class_setup_methods (klass);
4216 mono_class_setup_vtable (klass);
4217 if (mono_class_has_failure (klass)) {
4218 mono_error_set_for_class_failure (&error, klass);
4223 while ((event = mono_class_get_events (klass, &iter))) {
4225 method = event->add;
4227 method = event->remove;
4229 method = event->raise;
4231 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4232 if (bflags & BFLAGS_Public)
4234 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4235 if (bflags & BFLAGS_NonPublic)
4240 if (bflags & BFLAGS_NonPublic)
4246 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4247 if (bflags & BFLAGS_Static)
4248 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4251 if (bflags & BFLAGS_Instance)
4256 if (bflags & BFLAGS_Instance)
4261 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4264 if (g_hash_table_lookup (events, event))
4267 g_ptr_array_add (res_array, event);
4269 g_hash_table_insert (events, event, event);
4271 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4274 g_hash_table_destroy (events);
4280 g_hash_table_destroy (events);
4282 g_ptr_array_free (res_array, TRUE);
4284 mono_error_set_pending_exception (&error);
4288 ICALL_EXPORT GPtrArray *
4289 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4295 GPtrArray *res_array;
4297 if (type->type->byref) {
4298 return g_ptr_array_new ();
4301 klass = mono_class_from_mono_type (type->type);
4304 * If a nested type is generic, return its generic type definition.
4305 * Note that this means that the return value is essentially the set
4306 * of nested types of the generic type definition of @klass.
4308 * A note in MSDN claims that a generic type definition can have
4309 * nested types that aren't generic. In any case, the container of that
4310 * nested type would be the generic type definition.
4312 if (mono_class_is_ginst (klass))
4313 klass = mono_class_get_generic_class (klass)->container_class;
4315 res_array = g_ptr_array_new ();
4318 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4320 if ((mono_class_get_flags (nested) & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4321 if (bflags & BFLAGS_Public)
4324 if (bflags & BFLAGS_NonPublic)
4330 if (str != NULL && strcmp (nested->name, str))
4333 g_ptr_array_add (res_array, &nested->byval_arg);
4339 ICALL_EXPORT MonoReflectionType*
4340 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4343 MonoReflectionType *ret;
4345 MonoType *type = NULL;
4346 MonoTypeNameParse info;
4347 gboolean type_resolve;
4349 /* On MS.NET, this does not fire a TypeResolve event */
4350 type_resolve = TRUE;
4351 str = mono_string_to_utf8_checked (name, &error);
4352 if (mono_error_set_pending_exception (&error))
4354 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4355 if (!mono_reflection_parse_type (str, &info)) {
4357 mono_reflection_free_type_info (&info);
4359 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4362 /*g_print ("failed parse\n");*/
4366 if (info.assembly.name) {
4368 mono_reflection_free_type_info (&info);
4370 /* 1.0 and 2.0 throw different exceptions */
4371 if (mono_defaults.generic_ilist_class)
4372 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4374 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4380 if (module != NULL) {
4381 if (module->image) {
4382 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4383 if (!is_ok (&error)) {
4385 mono_reflection_free_type_info (&info);
4386 mono_error_set_pending_exception (&error);
4393 if (assembly_is_dynamic (assembly->assembly)) {
4394 /* Enumerate all modules */
4395 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4399 if (abuilder->modules) {
4400 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4401 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4402 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4403 if (!is_ok (&error)) {
4405 mono_reflection_free_type_info (&info);
4406 mono_error_set_pending_exception (&error);
4414 if (!type && abuilder->loaded_modules) {
4415 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4416 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4417 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4418 if (!is_ok (&error)) {
4420 mono_reflection_free_type_info (&info);
4421 mono_error_set_pending_exception (&error);
4430 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4431 if (!is_ok (&error)) {
4433 mono_reflection_free_type_info (&info);
4434 mono_error_set_pending_exception (&error);
4439 mono_reflection_free_type_info (&info);
4441 MonoException *e = NULL;
4444 e = mono_get_exception_type_load (name, NULL);
4447 mono_set_pending_exception (e);
4451 if (type->type == MONO_TYPE_CLASS) {
4452 MonoClass *klass = mono_type_get_class (type);
4454 /* need to report exceptions ? */
4455 if (throwOnError && mono_class_has_failure (klass)) {
4456 /* report SecurityException (or others) that occured when loading the assembly */
4457 mono_error_set_for_class_failure (&error, klass);
4458 mono_error_set_pending_exception (&error);
4463 /* g_print ("got it\n"); */
4464 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4465 mono_error_set_pending_exception (&error);
4471 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4474 gchar *shadow_ini_file;
4477 /* Check for shadow-copied assembly */
4478 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4479 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4481 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4482 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4488 g_free (shadow_ini_file);
4489 if (content != NULL) {
4492 *filename = content;
4499 ICALL_EXPORT MonoString *
4500 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4502 MonoDomain *domain = mono_object_domain (assembly);
4503 MonoAssembly *mass = assembly->assembly;
4504 MonoString *res = NULL;
4509 if (g_path_is_absolute (mass->image->name)) {
4510 absolute = g_strdup (mass->image->name);
4511 dirname = g_path_get_dirname (absolute);
4513 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4514 dirname = g_strdup (mass->basedir);
4517 replace_shadow_path (domain, dirname, &absolute);
4520 mono_icall_make_platform_path (absolute);
4523 uri = g_filename_to_uri (absolute, NULL, NULL);
4525 const gchar *prepend = mono_icall_get_file_path_prefix (absolute);
4526 uri = g_strconcat (prepend, absolute, NULL);
4530 res = mono_string_new (domain, uri);
4537 ICALL_EXPORT MonoBoolean
4538 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4540 MonoAssembly *mass = assembly->assembly;
4542 return mass->in_gac;
4545 ICALL_EXPORT MonoReflectionAssembly*
4546 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4551 MonoImageOpenStatus status;
4552 MonoReflectionAssembly* result = NULL;
4554 name = mono_string_to_utf8_checked (mname, &error);
4555 if (mono_error_set_pending_exception (&error))
4557 res = mono_assembly_load_with_partial_name (name, &status);
4563 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4565 mono_error_set_pending_exception (&error);
4569 ICALL_EXPORT MonoStringHandle
4570 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4572 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4573 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4574 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4577 ICALL_EXPORT MonoBoolean
4578 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4580 return assembly->assembly->ref_only;
4583 ICALL_EXPORT MonoStringHandle
4584 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4586 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4587 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4589 return mono_string_new_handle (domain, assembly->image->version, error);
4592 ICALL_EXPORT MonoReflectionMethod*
4593 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4596 MonoReflectionMethod *res = NULL;
4599 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4603 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4604 if (!mono_error_ok (&error))
4607 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4610 if (!mono_error_ok (&error))
4611 mono_error_set_pending_exception (&error);
4615 ICALL_EXPORT MonoReflectionModule*
4616 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4619 MonoReflectionModule *result = NULL;
4620 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4621 if (!mono_error_ok (&error))
4622 mono_error_set_pending_exception (&error);
4626 ICALL_EXPORT MonoArray*
4627 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4630 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4631 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4632 if (mono_error_set_pending_exception (&error))
4637 for (i = 0; i < table->rows; ++i) {
4638 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4639 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4644 ICALL_EXPORT MonoStringHandle
4645 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4648 guint8 aotid_sum = 0;
4649 MonoDomain* domain = mono_domain_get ();
4651 if (!domain->entry_assembly || !domain->entry_assembly->image)
4654 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4656 for (i = 0; i < 16; ++i)
4657 aotid_sum |= (*aotid)[i];
4662 gchar *guid = mono_guid_to_string((guint8*) aotid);
4663 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4669 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4671 static MonoMethod *create_version = NULL;
4675 mono_error_init (error);
4678 if (!create_version) {
4679 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4680 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4681 g_assert (create_version);
4682 mono_method_desc_free (desc);
4688 args [3] = &revision;
4689 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4690 return_val_if_nok (error, NULL);
4692 mono_runtime_invoke_checked (create_version, result, args, error);
4693 return_val_if_nok (error, NULL);
4698 ICALL_EXPORT MonoArray*
4699 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4703 MonoDomain *domain = mono_object_domain (assembly);
4705 static MonoMethod *create_culture = NULL;
4706 MonoImage *image = assembly->assembly->image;
4710 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4713 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4714 if (mono_error_set_pending_exception (&error))
4718 if (count > 0 && !create_culture) {
4719 MonoMethodDesc *desc = mono_method_desc_new (
4720 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4721 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4722 g_assert (create_culture);
4723 mono_method_desc_free (desc);
4726 for (i = 0; i < count; i++) {
4727 MonoObject *version;
4728 MonoReflectionAssemblyName *aname;
4729 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4731 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4733 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4734 domain, mono_class_get_assembly_name_class (), &error);
4735 if (mono_error_set_pending_exception (&error))
4738 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4740 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4741 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4742 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4743 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4744 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4745 aname->versioncompat = 1; /* SameMachine (default) */
4746 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4748 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4749 if (mono_error_set_pending_exception (&error))
4752 MONO_OBJECT_SETREF (aname, version, version);
4754 if (create_culture) {
4756 MonoBoolean assembly_ref = 1;
4757 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4758 args [1] = &assembly_ref;
4760 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4761 if (mono_error_set_pending_exception (&error))
4764 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4767 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4768 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4769 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4771 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4772 /* public key token isn't copied - the class library will
4773 automatically generate it from the public key if required */
4774 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4775 if (mono_error_set_pending_exception (&error))
4778 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4779 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4781 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4782 if (mono_error_set_pending_exception (&error))
4785 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4786 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4789 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4790 if (mono_error_set_pending_exception (&error))
4793 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4796 /* note: this function doesn't return the codebase on purpose (i.e. it can
4797 be used under partial trust as path information isn't present). */
4799 mono_array_setref (result, i, aname);
4804 /* move this in some file in mono/util/ */
4806 g_concat_dir_and_file (const char *dir, const char *file)
4808 g_return_val_if_fail (dir != NULL, NULL);
4809 g_return_val_if_fail (file != NULL, NULL);
4812 * If the directory name doesn't have a / on the end, we need
4813 * to add one so we get a proper path to the file
4815 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4816 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4818 return g_strconcat (dir, file, NULL);
4822 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4825 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4827 guint32 cols [MONO_MANIFEST_SIZE];
4828 guint32 impl, file_idx;
4832 char *n = mono_string_to_utf8_checked (name, &error);
4833 if (mono_error_set_pending_exception (&error))
4836 for (i = 0; i < table->rows; ++i) {
4837 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4838 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4839 if (strcmp (val, n) == 0)
4843 if (i == table->rows)
4846 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4849 * this code should only be called after obtaining the
4850 * ResourceInfo and handling the other cases.
4852 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4853 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4855 module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
4856 if (mono_error_set_pending_exception (&error) || !module)
4860 module = assembly->assembly->image;
4863 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4864 if (mono_error_set_pending_exception (&error))
4866 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4868 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4871 ICALL_EXPORT gboolean
4872 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4875 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4877 guint32 cols [MONO_MANIFEST_SIZE];
4878 guint32 file_cols [MONO_FILE_SIZE];
4882 n = mono_string_to_utf8_checked (name, &error);
4883 if (mono_error_set_pending_exception (&error))
4885 for (i = 0; i < table->rows; ++i) {
4886 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4887 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4888 if (strcmp (val, n) == 0)
4892 if (i == table->rows)
4895 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4896 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4899 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4900 case MONO_IMPLEMENTATION_FILE:
4901 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4902 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4903 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4904 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4905 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4906 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4909 info->location = RESOURCE_LOCATION_EMBEDDED;
4912 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4913 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4914 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4915 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4916 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4917 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4919 mono_set_pending_exception (ex);
4922 MonoReflectionAssembly *assm_obj;
4923 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4925 mono_error_set_pending_exception (&error);
4928 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4930 /* Obtain info recursively */
4931 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4932 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4935 case MONO_IMPLEMENTATION_EXP_TYPE:
4936 g_assert_not_reached ();
4944 ICALL_EXPORT MonoObject*
4945 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4948 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4949 MonoArray *result = NULL;
4954 /* check hash if needed */
4956 n = mono_string_to_utf8_checked (name, &error);
4957 if (mono_error_set_pending_exception (&error))
4960 for (i = 0; i < table->rows; ++i) {
4961 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4962 if (strcmp (val, n) == 0) {
4965 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4966 fn = mono_string_new (mono_object_domain (assembly), n);
4968 return (MonoObject*)fn;
4976 for (i = 0; i < table->rows; ++i) {
4977 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4981 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4982 if (mono_error_set_pending_exception (&error))
4987 for (i = 0; i < table->rows; ++i) {
4988 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4989 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4990 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4991 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4996 return (MonoObject*)result;
4999 ICALL_EXPORT MonoArray*
5000 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5003 MonoDomain *domain = mono_domain_get();
5006 int i, j, file_count = 0;
5007 MonoImage **modules;
5008 guint32 module_count, real_module_count;
5009 MonoTableInfo *table;
5010 guint32 cols [MONO_FILE_SIZE];
5011 MonoImage *image = assembly->assembly->image;
5013 g_assert (image != NULL);
5014 g_assert (!assembly_is_dynamic (assembly->assembly));
5016 table = &image->tables [MONO_TABLE_FILE];
5017 file_count = table->rows;
5019 modules = image->modules;
5020 module_count = image->module_count;
5022 real_module_count = 0;
5023 for (i = 0; i < module_count; ++i)
5025 real_module_count ++;
5027 klass = mono_class_get_module_class ();
5028 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5029 if (mono_error_set_pending_exception (&error))
5032 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5033 if (mono_error_set_pending_exception (&error))
5036 mono_array_setref (res, 0, image_obj);
5038 for (i = 0; i < module_count; ++i)
5040 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5041 if (mono_error_set_pending_exception (&error))
5043 mono_array_setref (res, j, rm);
5047 for (i = 0; i < file_count; ++i, ++j) {
5048 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5049 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5050 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5051 if (mono_error_set_pending_exception (&error))
5053 mono_array_setref (res, j, rm);
5056 MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
5057 if (mono_error_set_pending_exception (&error))
5060 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5061 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5064 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5065 if (mono_error_set_pending_exception (&error))
5067 mono_array_setref (res, j, rm);
5074 ICALL_EXPORT MonoReflectionMethod*
5075 ves_icall_GetCurrentMethod (void)
5077 MonoReflectionMethod *res = NULL;
5080 MonoMethod *m = mono_method_get_last_managed ();
5083 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5087 while (m->is_inflated)
5088 m = ((MonoMethodInflated*)m)->declaring;
5090 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5091 mono_error_set_pending_exception (&error);
5097 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5100 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5103 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5104 //method is inflated, we should inflate it on the other class
5105 MonoGenericContext ctx;
5106 ctx.method_inst = inflated->context.method_inst;
5107 ctx.class_inst = inflated->context.class_inst;
5108 if (mono_class_is_ginst (klass))
5109 ctx.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
5110 else if (mono_class_is_gtd (klass))
5111 ctx.class_inst = mono_class_get_generic_container (klass)->context.class_inst;
5112 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5113 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5117 mono_class_setup_methods (method->klass);
5118 if (mono_class_has_failure (method->klass))
5120 int mcount = mono_class_get_method_count (method->klass);
5121 for (i = 0; i < mcount; ++i) {
5122 if (method->klass->methods [i] == method) {
5127 mono_class_setup_methods (klass);
5128 if (mono_class_has_failure (klass))
5130 g_assert (offset >= 0 && offset < mono_class_get_method_count (klass));
5131 return klass->methods [offset];
5134 ICALL_EXPORT MonoReflectionMethod*
5135 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5137 MonoReflectionMethod *res = NULL;
5140 if (type && generic_check) {
5141 klass = mono_class_from_mono_type (type);
5142 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5145 if (method->klass != klass) {
5146 method = mono_method_get_equivalent_method (method, klass);
5151 klass = mono_class_from_mono_type (type);
5153 klass = method->klass;
5154 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5155 mono_error_set_pending_exception (&error);
5159 ICALL_EXPORT MonoReflectionMethodBody*
5160 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5163 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5164 mono_error_set_pending_exception (&error);
5168 ICALL_EXPORT MonoReflectionAssembly*
5169 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5172 MonoReflectionAssembly *result;
5173 MonoMethod *dest = NULL;
5175 mono_stack_walk_no_il (get_executing, &dest);
5177 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5179 mono_error_set_pending_exception (&error);
5184 ICALL_EXPORT MonoReflectionAssembly*
5185 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5188 MonoReflectionAssembly *result;
5189 MonoDomain* domain = mono_domain_get ();
5191 if (!domain->entry_assembly)
5194 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5196 mono_error_set_pending_exception (&error);
5200 ICALL_EXPORT MonoReflectionAssembly*
5201 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5206 MonoReflectionAssembly *result;
5209 mono_stack_walk_no_il (get_executing, &dest);
5211 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5215 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5218 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5220 mono_error_set_pending_exception (&error);
5224 ICALL_EXPORT MonoStringHandle
5225 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5226 gboolean assembly_qualified, MonoError *error)
5228 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5229 MonoType *type = MONO_HANDLE_RAW (object)->type;
5230 MonoTypeNameFormat format;
5231 MonoStringHandle res;
5235 format = assembly_qualified ?
5236 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5237 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5239 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5241 name = mono_type_get_name_full (type, format);
5243 return NULL_HANDLE_STRING;
5245 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5247 return NULL_HANDLE_STRING;
5250 res = mono_string_new_handle (domain, name, error);
5257 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5260 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5262 mono_class_init_checked (klass, &error);
5263 mono_error_set_pending_exception (&error);
5264 return mono_security_core_clr_class_level (klass);
5268 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5270 MonoClassField *field = rfield->field;
5271 return mono_security_core_clr_field_level (field, TRUE);
5275 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5277 MonoMethod *method = rfield->method;
5278 return mono_security_core_clr_method_level (method, TRUE);
5282 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token, MonoError *error)
5284 static MonoMethod *create_culture = NULL;
5288 const char *pkey_ptr;
5290 MonoBoolean assembly_ref = 0;
5292 mono_error_init (error);
5294 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5295 aname->major = name->major;
5296 aname->minor = name->minor;
5297 aname->build = name->build;
5298 aname->flags = name->flags;
5299 aname->revision = name->revision;
5300 aname->hashalg = name->hash_alg;
5301 aname->versioncompat = 1; /* SameMachine (default) */
5302 aname->processor_architecture = name->arch;
5304 if (by_default_version) {
5305 MonoObject *version;
5307 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5308 return_if_nok (error);
5310 MONO_OBJECT_SETREF (aname, version, version);
5314 if (absolute != NULL && *absolute != '\0') {
5317 codebase = g_strdup (absolute);
5319 mono_icall_make_platform_path (codebase);
5321 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5323 result = g_strconcat (prepend, codebase, NULL);
5329 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5333 if (!create_culture) {
5334 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5335 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5336 g_assert (create_culture);
5337 mono_method_desc_free (desc);
5340 if (name->culture) {
5341 args [0] = mono_string_new (domain, name->culture);
5342 args [1] = &assembly_ref;
5344 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5345 return_if_nok (error);
5347 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5350 if (name->public_key) {
5351 pkey_ptr = (char*)name->public_key;
5352 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5354 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5355 return_if_nok (error);
5356 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5357 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5358 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5359 } else if (default_publickey) {
5360 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5361 return_if_nok (error);
5362 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5363 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5366 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5367 if (name->public_key_token [0]) {
5371 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5372 return_if_nok (error);
5374 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5375 p = mono_array_addr (keyToken, char, 0);
5377 for (i = 0, j = 0; i < 8; i++) {
5378 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5379 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5382 } else if (default_token) {
5383 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5384 return_if_nok (error);
5385 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5389 ICALL_EXPORT MonoString *
5390 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5392 MonoDomain *domain = mono_object_domain (assembly);
5393 MonoAssembly *mass = assembly->assembly;
5397 name = mono_stringify_assembly_name (&mass->aname);
5398 res = mono_string_new (domain, name);
5404 ICALL_EXPORT MonoAssemblyName *
5405 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5407 return &mass->aname;
5411 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5415 MonoImageOpenStatus status = MONO_IMAGE_OK;
5418 MonoAssemblyName name;
5421 filename = mono_string_to_utf8_checked (fname, &error);
5422 if (mono_error_set_pending_exception (&error))
5425 dirname = g_path_get_dirname (filename);
5426 replace_shadow_path (mono_domain_get (), dirname, &filename);
5429 image = mono_image_open (filename, &status);
5435 if (status == MONO_IMAGE_IMAGE_INVALID)
5436 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5438 exc = mono_get_exception_file_not_found2 (NULL, fname);
5439 mono_set_pending_exception (exc);
5443 res = mono_assembly_fill_assembly_name (image, &name);
5445 mono_image_close (image);
5447 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5451 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5452 mono_error_set_pending_exception (&error);
5454 mono_image_close (image);
5458 ICALL_EXPORT MonoBoolean
5459 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5460 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5462 MonoBoolean result = FALSE;
5463 MonoDeclSecurityEntry entry;
5465 /* SecurityAction.RequestMinimum */
5466 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5467 *minimum = entry.blob;
5468 *minLength = entry.size;
5471 /* SecurityAction.RequestOptional */
5472 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5473 *optional = entry.blob;
5474 *optLength = entry.size;
5477 /* SecurityAction.RequestRefuse */
5478 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5479 *refused = entry.blob;
5480 *refLength = entry.size;
5488 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5490 guint32 attrs, visibility;
5492 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5493 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5494 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5497 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5503 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5505 MonoReflectionType *rt;
5508 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5511 mono_error_init (error);
5513 /* we start the count from 1 because we skip the special type <Module> */
5516 for (i = 1; i < tdef->rows; ++i) {
5517 if (mono_module_type_is_visible (tdef, image, i + 1))
5521 count = tdef->rows - 1;
5523 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5524 return_val_if_nok (error, NULL);
5525 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5526 return_val_if_nok (error, NULL);
5528 for (i = 1; i < tdef->rows; ++i) {
5529 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5530 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5533 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5534 return_val_if_nok (error, NULL);
5536 mono_array_setref (res, count, rt);
5538 MonoException *ex = mono_error_convert_to_exception (error);
5539 mono_array_setref (*exceptions, count, ex);
5548 ICALL_EXPORT MonoArray*
5549 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5552 MonoArray *res = NULL;
5553 MonoArray *exceptions = NULL;
5554 MonoImage *image = NULL;
5555 MonoTableInfo *table = NULL;
5558 int i, len, ex_count;
5560 domain = mono_object_domain (assembly);
5562 g_assert (!assembly_is_dynamic (assembly->assembly));
5563 image = assembly->assembly->image;
5564 table = &image->tables [MONO_TABLE_FILE];
5565 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5566 if (mono_error_set_pending_exception (&error))
5569 /* Append data from all modules in the assembly */
5570 for (i = 0; i < table->rows; ++i) {
5571 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5572 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5573 if (mono_error_set_pending_exception (&error))
5579 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5580 if (mono_error_set_pending_exception (&error))
5584 /* Append the new types to the end of the array */
5585 if (mono_array_length (res2) > 0) {
5587 MonoArray *res3, *ex3;
5589 len1 = mono_array_length (res);
5590 len2 = mono_array_length (res2);
5592 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5593 if (mono_error_set_pending_exception (&error))
5595 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5596 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5599 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5600 if (mono_error_set_pending_exception (&error))
5602 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5603 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5610 /* the ReflectionTypeLoadException must have all the types (Types property),
5611 * NULL replacing types which throws an exception. The LoaderException must
5612 * contain all exceptions for NULL items.
5615 len = mono_array_length (res);
5618 for (i = 0; i < len; i++) {
5619 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5623 klass = mono_type_get_class (t->type);
5624 if ((klass != NULL) && mono_class_has_failure (klass)) {
5625 /* keep the class in the list */
5626 list = g_list_append (list, klass);
5627 /* and replace Type with NULL */
5628 mono_array_setref (res, i, NULL);
5635 if (list || ex_count) {
5637 MonoException *exc = NULL;
5638 MonoArray *exl = NULL;
5639 int j, length = g_list_length (list) + ex_count;
5641 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5642 if (mono_error_set_pending_exception (&error)) {
5646 /* Types for which mono_class_get_checked () succeeded */
5647 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5648 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5649 mono_array_setref (exl, i, exc);
5651 /* Types for which it don't */
5652 for (j = 0; j < mono_array_length (exceptions); ++j) {
5653 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5655 g_assert (i < length);
5656 mono_array_setref (exl, i, exc);
5663 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5664 if (!is_ok (&error)) {
5665 mono_error_set_pending_exception (&error);
5668 mono_set_pending_exception (exc);
5676 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5678 mono_assembly_name_free (aname);
5681 ICALL_EXPORT gboolean
5682 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5684 *is_version_definited = *is_token_defined = FALSE;
5686 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5689 ICALL_EXPORT MonoReflectionType*
5690 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5693 MonoReflectionType *ret;
5694 MonoDomain *domain = mono_object_domain (module);
5697 g_assert (module->image);
5699 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5700 /* These images do not have a global type */
5703 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5704 if (!mono_error_ok (&error)) {
5705 mono_error_set_pending_exception (&error);
5709 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5710 if (!mono_error_ok (&error)) {
5711 mono_error_set_pending_exception (&error);
5719 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5721 /*if (module->image)
5722 mono_image_close (module->image);*/
5725 ICALL_EXPORT MonoStringHandle
5726 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5728 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5729 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5732 return mono_string_new_handle (domain, image->guid, error);
5736 static inline gpointer
5737 mono_icall_module_get_hinstance (MonoReflectionModule *module)
5739 return (gpointer) (-1);
5741 #endif /* HOST_WIN32 */
5743 ICALL_EXPORT gpointer
5744 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5746 return mono_icall_module_get_hinstance (module);
5750 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5752 if (image_is_dynamic (image)) {
5753 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5754 *pe_kind = dyn->pe_kind;
5755 *machine = dyn->machine;
5758 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5759 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5764 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5766 return (image->md_version_major << 16) | (image->md_version_minor);
5769 ICALL_EXPORT MonoArray*
5770 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5773 MonoArray *exceptions;
5776 if (!module->image) {
5777 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5778 mono_error_set_pending_exception (&error);
5783 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5784 if (mono_error_set_pending_exception (&error))
5787 for (i = 0; i < mono_array_length (exceptions); ++i) {
5788 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5790 mono_set_pending_exception (ex);
5799 mono_memberref_is_method (MonoImage *image, guint32 token)
5801 if (!image_is_dynamic (image)) {
5802 guint32 cols [MONO_MEMBERREF_SIZE];
5804 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5805 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5806 mono_metadata_decode_blob_size (sig, &sig);
5807 return (*sig != 0x6);
5810 MonoClass *handle_class;
5812 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5813 mono_error_cleanup (&error); /* just probing, ignore error */
5817 return mono_defaults.methodhandle_class == handle_class;
5822 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5825 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5826 mono_array_addr (type_args, MonoType*, 0));
5828 context->class_inst = NULL;
5830 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5831 mono_array_addr (method_args, MonoType*, 0));
5833 context->method_inst = NULL;
5836 ICALL_EXPORT MonoType*
5837 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5840 int table = mono_metadata_token_table (token);
5841 int index = mono_metadata_token_index (token);
5842 MonoGenericContext context;
5845 *resolve_error = ResolveTokenError_Other;
5847 /* Validate token */
5848 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5849 (table != MONO_TABLE_TYPESPEC)) {
5850 *resolve_error = ResolveTokenError_BadTable;
5854 if (image_is_dynamic (image)) {
5855 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5856 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5857 mono_error_cleanup (&error);
5858 return klass ? &klass->byval_arg : NULL;
5861 init_generic_context_from_args (&context, type_args, method_args);
5862 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5863 mono_error_cleanup (&error);
5864 return klass ? &klass->byval_arg : NULL;
5867 if ((index <= 0) || (index > image->tables [table].rows)) {
5868 *resolve_error = ResolveTokenError_OutOfRange;
5872 init_generic_context_from_args (&context, type_args, method_args);
5873 klass = mono_class_get_checked (image, token, &error);
5875 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5876 if (!mono_error_ok (&error)) {
5877 mono_error_set_pending_exception (&error);
5882 return &klass->byval_arg;
5887 ICALL_EXPORT MonoMethod*
5888 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5891 int table = mono_metadata_token_table (token);
5892 int index = mono_metadata_token_index (token);
5893 MonoGenericContext context;
5896 *resolve_error = ResolveTokenError_Other;
5898 /* Validate token */
5899 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5900 (table != MONO_TABLE_MEMBERREF)) {
5901 *resolve_error = ResolveTokenError_BadTable;
5905 if (image_is_dynamic (image)) {
5906 if (table == MONO_TABLE_METHOD) {
5907 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5908 mono_error_cleanup (&error);
5912 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5913 *resolve_error = ResolveTokenError_BadTable;
5917 init_generic_context_from_args (&context, type_args, method_args);
5918 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5919 mono_error_cleanup (&error);
5923 if ((index <= 0) || (index > image->tables [table].rows)) {
5924 *resolve_error = ResolveTokenError_OutOfRange;
5927 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5928 *resolve_error = ResolveTokenError_BadTable;
5932 init_generic_context_from_args (&context, type_args, method_args);
5933 method = mono_get_method_checked (image, token, NULL, &context, &error);
5934 mono_error_set_pending_exception (&error);
5939 ICALL_EXPORT MonoString*
5940 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5943 int index = mono_metadata_token_index (token);
5945 *resolve_error = ResolveTokenError_Other;
5947 /* Validate token */
5948 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5949 *resolve_error = ResolveTokenError_BadTable;
5953 if (image_is_dynamic (image)) {
5954 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5955 mono_error_cleanup (&error);
5959 if ((index <= 0) || (index >= image->heap_us.size)) {
5960 *resolve_error = ResolveTokenError_OutOfRange;
5964 /* FIXME: What to do if the index points into the middle of a string ? */
5966 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5967 mono_error_set_pending_exception (&error);
5971 ICALL_EXPORT MonoClassField*
5972 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5976 int table = mono_metadata_token_table (token);
5977 int index = mono_metadata_token_index (token);
5978 MonoGenericContext context;
5979 MonoClassField *field;
5981 *resolve_error = ResolveTokenError_Other;
5983 /* Validate token */
5984 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5985 *resolve_error = ResolveTokenError_BadTable;
5989 if (image_is_dynamic (image)) {
5990 if (table == MONO_TABLE_FIELD) {
5991 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5992 mono_error_cleanup (&error);
5996 if (mono_memberref_is_method (image, token)) {
5997 *resolve_error = ResolveTokenError_BadTable;
6001 init_generic_context_from_args (&context, type_args, method_args);
6002 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6003 mono_error_cleanup (&error);
6007 if ((index <= 0) || (index > image->tables [table].rows)) {
6008 *resolve_error = ResolveTokenError_OutOfRange;
6011 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6012 *resolve_error = ResolveTokenError_BadTable;
6016 init_generic_context_from_args (&context, type_args, method_args);
6017 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6018 mono_error_set_pending_exception (&error);
6024 ICALL_EXPORT MonoObject*
6025 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6029 int table = mono_metadata_token_table (token);
6031 *error = ResolveTokenError_Other;
6034 case MONO_TABLE_TYPEDEF:
6035 case MONO_TABLE_TYPEREF:
6036 case MONO_TABLE_TYPESPEC: {
6037 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6039 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6040 mono_error_set_pending_exception (&merror);
6047 case MONO_TABLE_METHOD:
6048 case MONO_TABLE_METHODSPEC: {
6049 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6051 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6052 mono_error_set_pending_exception (&merror);
6058 case MONO_TABLE_FIELD: {
6059 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6061 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6062 mono_error_set_pending_exception (&merror);
6068 case MONO_TABLE_MEMBERREF:
6069 if (mono_memberref_is_method (image, token)) {
6070 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6072 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6073 mono_error_set_pending_exception (&merror);
6080 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6082 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6083 mono_error_set_pending_exception (&merror);
6092 *error = ResolveTokenError_BadTable;
6098 ICALL_EXPORT MonoArray*
6099 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6102 int table = mono_metadata_token_table (token);
6103 int idx = mono_metadata_token_index (token);
6104 MonoTableInfo *tables = image->tables;
6109 *resolve_error = ResolveTokenError_OutOfRange;
6111 /* FIXME: Support other tables ? */
6112 if (table != MONO_TABLE_STANDALONESIG)
6115 if (image_is_dynamic (image))
6118 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6121 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6123 ptr = mono_metadata_blob_heap (image, sig);
6124 len = mono_metadata_decode_blob_size (ptr, &ptr);
6126 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6127 if (mono_error_set_pending_exception (&error))
6129 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6133 ICALL_EXPORT MonoBoolean
6134 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6140 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6146 check_for_invalid_type (MonoClass *klass, MonoError *error)
6150 mono_error_init (error);
6152 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6155 name = mono_type_get_full_name (klass);
6156 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6158 ICALL_EXPORT MonoReflectionType *
6159 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6162 MonoReflectionType *ret;
6163 MonoClass *klass, *aklass;
6165 klass = mono_class_from_mono_type (type->type);
6166 check_for_invalid_type (klass, &error);
6167 if (mono_error_set_pending_exception (&error))
6170 if (rank == 0) //single dimentional array
6171 aklass = mono_array_class_get (klass, 1);
6173 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6175 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6176 mono_error_set_pending_exception (&error);
6181 ICALL_EXPORT MonoReflectionType *
6182 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6185 MonoReflectionType *ret;
6188 klass = mono_class_from_mono_type (type->type);
6189 mono_class_init_checked (klass, &error);
6190 if (mono_error_set_pending_exception (&error))
6193 check_for_invalid_type (klass, &error);
6194 if (mono_error_set_pending_exception (&error))
6197 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6198 mono_error_set_pending_exception (&error);
6203 ICALL_EXPORT MonoReflectionType *
6204 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6207 MonoReflectionType *ret;
6208 MonoClass *klass, *pklass;
6210 klass = mono_class_from_mono_type (type->type);
6211 mono_class_init_checked (klass, &error);
6212 if (mono_error_set_pending_exception (&error))
6214 check_for_invalid_type (klass, &error);
6215 if (mono_error_set_pending_exception (&error))
6218 pklass = mono_ptr_class_get (type->type);
6220 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6221 mono_error_set_pending_exception (&error);
6226 ICALL_EXPORT MonoObject *
6227 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6228 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6231 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6232 MonoObject *delegate;
6234 MonoMethod *method = info->method;
6235 MonoMethodSignature *sig = mono_method_signature(method);
6237 mono_class_init_checked (delegate_class, &error);
6238 if (mono_error_set_pending_exception (&error))
6241 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6242 /* FIXME improve this exception message */
6243 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6245 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6246 mono_error_set_pending_exception (&error);
6250 if (mono_security_core_clr_enabled ()) {
6251 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6252 if (throwOnBindFailure)
6253 mono_error_set_pending_exception (&error);
6255 mono_error_cleanup (&error);
6260 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6261 if (!method->is_inflated) {
6262 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"));
6267 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6268 if (mono_error_set_pending_exception (&error))
6271 if (method_is_dynamic (method)) {
6272 /* Creating a trampoline would leak memory */
6273 func = mono_compile_method_checked (method, &error);
6274 if (mono_error_set_pending_exception (&error))
6277 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6278 method = mono_object_get_virtual_method (target, method);
6279 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6280 if (mono_error_set_pending_exception (&error))
6282 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6285 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6286 if (mono_error_set_pending_exception (&error))
6291 ICALL_EXPORT MonoMulticastDelegate *
6292 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6295 MonoMulticastDelegate *ret;
6297 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6299 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6300 if (mono_error_set_pending_exception (&error))
6303 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6308 ICALL_EXPORT MonoReflectionMethod*
6309 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6311 MonoReflectionMethod *ret = NULL;
6313 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6314 mono_error_set_pending_exception (&error);
6320 static inline gint32
6321 mono_array_get_byte_length (MonoArray *array)
6327 klass = array->obj.vtable->klass;
6329 if (array->bounds == NULL)
6330 length = array->max_length;
6333 for (i = 0; i < klass->rank; ++ i)
6334 length *= array->bounds [i].length;
6337 switch (klass->element_class->byval_arg.type) {
6340 case MONO_TYPE_BOOLEAN:
6344 case MONO_TYPE_CHAR:
6352 return length * sizeof (gpointer);
6363 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6365 return mono_array_get_byte_length (array);
6369 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6371 return mono_array_get (array, gint8, idx);
6375 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6377 mono_array_set (array, gint8, idx, value);
6380 ICALL_EXPORT MonoBoolean
6381 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6383 guint8 *src_buf, *dest_buf;
6386 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6390 g_assert (count >= 0);
6392 /* This is called directly from the class libraries without going through the managed wrapper */
6393 MONO_CHECK_ARG_NULL (src, FALSE);
6394 MONO_CHECK_ARG_NULL (dest, FALSE);
6396 /* watch out for integer overflow */
6397 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6400 src_buf = (guint8 *)src->vector + src_offset;
6401 dest_buf = (guint8 *)dest->vector + dest_offset;
6404 memcpy (dest_buf, src_buf, count);
6406 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6411 #ifndef DISABLE_REMOTING
6412 ICALL_EXPORT MonoObject *
6413 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6416 MonoDomain *domain = mono_object_domain (this_obj);
6418 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6419 MonoTransparentProxy *tp;
6423 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6424 if (mono_error_set_pending_exception (&error))
6427 tp = (MonoTransparentProxy*) res;
6429 MONO_OBJECT_SETREF (tp, rp, rp);
6430 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6431 klass = mono_class_from_mono_type (type);
6433 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6434 mono_class_setup_vtable (klass);
6435 if (mono_class_has_failure (klass)) {
6436 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6440 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6441 if (mono_error_set_pending_exception (&error))
6443 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6444 if (mono_error_set_pending_exception (&error))
6447 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6448 if (mono_error_set_pending_exception (&error))
6453 ICALL_EXPORT MonoReflectionType *
6454 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6457 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6458 mono_error_set_pending_exception (&error);
6464 /* System.Environment */
6467 ves_icall_System_Environment_get_UserName (void)
6469 /* using glib is more portable */
6470 return mono_string_new (mono_domain_get (), g_get_user_name ());
6475 mono_icall_get_machine_name (void)
6477 #if !defined(DISABLE_SOCKETS)
6481 #if defined _SC_HOST_NAME_MAX
6482 n = sysconf (_SC_HOST_NAME_MAX);
6486 buf = g_malloc (n+1);
6488 if (gethostname (buf, n) == 0){
6490 result = mono_string_new (mono_domain_get (), buf);
6497 return mono_string_new (mono_domain_get (), "mono");
6500 #endif /* !HOST_WIN32 */
6502 ICALL_EXPORT MonoString *
6503 ves_icall_System_Environment_get_MachineName (void)
6505 return mono_icall_get_machine_name ();
6510 mono_icall_get_platform (void)
6512 #if defined(__MACH__)
6515 // Notice that the value is hidden from user code, and only exposed
6516 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6517 // define and making assumptions based on Unix/128/4 values before there
6518 // was a MacOS define. Lots of code would assume that not-Unix meant
6519 // Windows, but in this case, it would be OSX.
6527 #endif /* !HOST_WIN32 */
6530 ves_icall_System_Environment_get_Platform (void)
6532 return mono_icall_get_platform ();
6536 static inline MonoString *
6537 mono_icall_get_new_line (void)
6539 return mono_string_new (mono_domain_get (), "\n");
6541 #endif /* !HOST_WIN32 */
6543 ICALL_EXPORT MonoString *
6544 ves_icall_System_Environment_get_NewLine (void)
6546 return mono_icall_get_new_line ();
6550 static inline MonoBoolean
6551 mono_icall_is_64bit_os (void)
6553 #if SIZEOF_VOID_P == 8
6556 #if defined(HAVE_SYS_UTSNAME_H)
6557 struct utsname name;
6559 if (uname (&name) >= 0) {
6560 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6566 #endif /* !HOST_WIN32 */
6568 ICALL_EXPORT MonoBoolean
6569 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6571 return mono_icall_is_64bit_os ();
6574 ICALL_EXPORT MonoStringHandle
6575 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6579 if (utf8_name == NULL)
6580 return NULL_HANDLE_STRING;
6582 value = g_getenv (utf8_name);
6585 return NULL_HANDLE_STRING;
6587 return mono_string_new_handle (mono_domain_get (), value, error);
6591 * There is no standard way to get at environ.
6594 #ifndef __MINGW32_VERSION
6595 #if defined(__APPLE__)
6596 #if defined (TARGET_OSX)
6597 /* Apple defines this in crt_externs.h but doesn't provide that header for
6598 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6599 * in fact exist on all implementations (so far)
6601 gchar ***_NSGetEnviron(void);
6602 #define environ (*_NSGetEnviron())
6604 static char *mono_environ[1] = { NULL };
6605 #define environ mono_environ
6606 #endif /* defined (TARGET_OSX) */
6614 ICALL_EXPORT MonoArray *
6615 ves_icall_System_Environment_GetCoomandLineArgs (void)
6618 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6619 mono_error_set_pending_exception (&error);
6625 mono_icall_get_environment_variable_names (void)
6635 for (e = environ; *e != 0; ++ e)
6638 domain = mono_domain_get ();
6639 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6640 if (mono_error_set_pending_exception (&error))
6644 for (e = environ; *e != 0; ++ e) {
6645 parts = g_strsplit (*e, "=", 2);
6647 str = mono_string_new (domain, *parts);
6648 mono_array_setref (names, n, str);
6658 #endif /* !HOST_WIN32 */
6660 ICALL_EXPORT MonoArray *
6661 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6663 return mono_icall_get_environment_variable_names ();
6668 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6670 gchar *utf8_name, *utf8_value;
6673 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6674 if (mono_error_set_pending_exception (&error))
6677 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6678 g_unsetenv (utf8_name);
6683 utf8_value = mono_string_to_utf8_checked (value, &error);
6684 if (!mono_error_ok (&error)) {
6686 mono_error_set_pending_exception (&error);
6689 g_setenv (utf8_name, utf8_value, TRUE);
6692 g_free (utf8_value);
6694 #endif /* !HOST_WIN32 */
6697 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6699 mono_icall_set_environment_variable (name, value);
6703 ves_icall_System_Environment_Exit (int result)
6705 mono_environment_exitcode_set (result);
6707 /* FIXME: There are some cleanup hangs that should be worked out, but
6708 * if the program is going to exit, everything will be cleaned up when
6709 * NaCl exits anyway.
6711 #ifndef __native_client__
6712 if (!mono_runtime_try_shutdown ())
6713 mono_thread_exit ();
6715 /* Suspend all managed threads since the runtime is going away */
6716 mono_thread_suspend_all_other_threads ();
6718 mono_runtime_quit ();
6721 /* we may need to do some cleanup here... */
6725 ICALL_EXPORT MonoStringHandle
6726 ves_icall_System_Environment_GetGacPath (MonoError *error)
6728 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6732 static inline MonoString *
6733 mono_icall_get_windows_folder_path (int folder)
6735 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6736 return mono_string_new (mono_domain_get (), "");
6738 #endif /* !HOST_WIN32 */
6740 ICALL_EXPORT MonoString*
6741 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6743 return mono_icall_get_windows_folder_path (folder);
6746 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6748 mono_icall_get_logical_drives (void)
6751 gunichar2 buf [256], *ptr, *dname;
6753 guint initial_size = 127, size = 128;
6756 MonoString *drivestr;
6757 MonoDomain *domain = mono_domain_get ();
6763 while (size > initial_size) {
6764 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6765 if (size > initial_size) {
6768 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6769 initial_size = size;
6783 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6784 if (mono_error_set_pending_exception (&error))
6791 while (*u16) { u16++; len ++; }
6792 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6793 if (mono_error_set_pending_exception (&error))
6796 mono_array_setref (result, ndrives++, drivestr);
6806 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6808 ICALL_EXPORT MonoArray *
6809 ves_icall_System_Environment_GetLogicalDrives (void)
6811 return mono_icall_get_logical_drives ();
6814 ICALL_EXPORT MonoString *
6815 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6818 gunichar2 volume_name [MAX_PATH + 1];
6820 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6822 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6823 mono_error_set_pending_exception (&error);
6827 ICALL_EXPORT MonoStringHandle
6828 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6830 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6833 static const char *encodings [] = {
6835 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6836 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6837 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6839 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6840 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6841 "x_unicode_2_0_utf_7",
6843 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6844 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6846 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6849 "unicodefffe", "utf_16be",
6856 * Returns the internal codepage, if the value of "int_code_page" is
6857 * 1 at entry, and we can not compute a suitable code page number,
6858 * returns the code page as a string
6860 ICALL_EXPORT MonoString*
6861 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6866 char *codepage = NULL;
6868 int want_name = *int_code_page;
6871 *int_code_page = -1;
6873 g_get_charset (&cset);
6874 c = codepage = g_strdup (cset);
6875 for (c = codepage; *c; c++){
6876 if (isascii (*c) && isalpha (*c))
6881 /* g_print ("charset: %s\n", cset); */
6883 /* handle some common aliases */
6886 for (i = 0; p != 0; ){
6889 p = encodings [++i];
6892 if (strcmp (p, codepage) == 0){
6893 *int_code_page = code;
6896 p = encodings [++i];
6899 if (strstr (codepage, "utf_8") != NULL)
6900 *int_code_page |= 0x10000000;
6903 if (want_name && *int_code_page == -1)
6904 return mono_string_new (mono_domain_get (), cset);
6909 ICALL_EXPORT MonoBoolean
6910 ves_icall_System_Environment_get_HasShutdownStarted (void)
6912 if (mono_runtime_is_shutting_down ())
6915 if (mono_domain_is_unloading (mono_domain_get ()))
6923 mono_icall_broadcast_setting_change (void)
6927 #endif /* !HOST_WIN32 */
6930 ves_icall_System_Environment_BroadcastSettingChange (void)
6932 mono_icall_broadcast_setting_change ();
6937 ves_icall_System_Environment_get_TickCount (void)
6939 /* this will overflow after ~24 days */
6940 return (gint32) (mono_msec_boottime () & 0xffffffff);
6944 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6949 #ifndef DISABLE_REMOTING
6950 ICALL_EXPORT MonoBoolean
6951 ves_icall_IsTransparentProxy (MonoObject *proxy)
6956 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6962 ICALL_EXPORT MonoReflectionMethod *
6963 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6964 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6966 MonoReflectionMethod *ret = NULL;
6971 MonoMethod **vtable;
6972 MonoMethod *res = NULL;
6974 MONO_CHECK_ARG_NULL (rtype, NULL);
6975 MONO_CHECK_ARG_NULL (rmethod, NULL);
6977 method = rmethod->method;
6978 klass = mono_class_from_mono_type (rtype->type);
6979 mono_class_init_checked (klass, &error);
6980 if (mono_error_set_pending_exception (&error))
6983 if (MONO_CLASS_IS_INTERFACE (klass))
6986 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6989 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6990 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6996 mono_class_setup_vtable (klass);
6997 vtable = klass->vtable;
6999 if (mono_class_is_interface (method->klass)) {
7000 gboolean variance_used = FALSE;
7001 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7002 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7004 res = vtable [offs + method->slot];
7006 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7009 if (method->slot != -1)
7010 res = vtable [method->slot];
7016 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7017 mono_error_set_pending_exception (&error);
7022 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7028 klass = mono_class_from_mono_type (type->type);
7029 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7030 if (!is_ok (&error)) {
7031 mono_error_set_pending_exception (&error);
7035 mono_vtable_set_is_remote (vtable, enable);
7038 #else /* DISABLE_REMOTING */
7041 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7043 g_assert_not_reached ();
7048 ICALL_EXPORT MonoObject *
7049 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7056 domain = mono_object_domain (type);
7057 klass = mono_class_from_mono_type (type->type);
7058 mono_class_init_checked (klass, &error);
7059 if (mono_error_set_pending_exception (&error))
7062 if (MONO_CLASS_IS_INTERFACE (klass) || mono_class_is_abstract (klass)) {
7063 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7067 if (klass->rank >= 1) {
7068 g_assert (klass->rank == 1);
7069 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7070 mono_error_set_pending_exception (&error);
7073 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7074 if (!is_ok (&error)) {
7075 mono_error_set_pending_exception (&error);
7078 /* Bypass remoting object creation check */
7079 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7080 mono_error_set_pending_exception (&error);
7086 ICALL_EXPORT MonoStringHandle
7087 ves_icall_System_IO_get_temp_path (MonoError *error)
7089 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7092 #ifndef PLATFORM_NO_DRIVEINFO
7093 ICALL_EXPORT MonoBoolean
7094 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7095 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7099 ULARGE_INTEGER wapi_free_bytes_avail;
7100 ULARGE_INTEGER wapi_total_number_of_bytes;
7101 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7103 *error = ERROR_SUCCESS;
7104 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7105 &wapi_total_number_of_free_bytes);
7108 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7109 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7110 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7112 *free_bytes_avail = 0;
7113 *total_number_of_bytes = 0;
7114 *total_number_of_free_bytes = 0;
7115 *error = GetLastError ();
7121 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7122 static inline guint32
7123 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7125 return GetDriveType (mono_string_chars (root_path_name));
7127 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7129 ICALL_EXPORT guint32
7130 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7132 return mono_icall_drive_info_get_drive_type (root_path_name);
7135 #endif /* PLATFORM_NO_DRIVEINFO */
7137 ICALL_EXPORT gpointer
7138 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7141 gpointer result = mono_compile_method_checked (method, &error);
7142 mono_error_set_pending_exception (&error);
7146 ICALL_EXPORT MonoString *
7147 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7152 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7154 mono_icall_make_platform_path (path);
7156 mcpath = mono_string_new (mono_domain_get (), path);
7162 /* this is an icall */
7164 get_bundled_app_config (void)
7167 const gchar *app_config;
7170 gchar *config_file_name, *config_file_path;
7171 gsize len, config_file_path_length, config_ext_length;
7174 domain = mono_domain_get ();
7175 file = domain->setup->configuration_file;
7176 if (!file || file->length == 0)
7179 // Retrieve config file and remove the extension
7180 config_file_name = mono_string_to_utf8_checked (file, &error);
7181 if (mono_error_set_pending_exception (&error))
7183 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7184 if (!config_file_path)
7185 config_file_path = config_file_name;
7187 config_file_path_length = strlen (config_file_path);
7188 config_ext_length = strlen (".config");
7189 if (config_file_path_length <= config_ext_length)
7192 len = config_file_path_length - config_ext_length;
7193 module = (gchar *)g_malloc0 (len + 1);
7194 memcpy (module, config_file_path, len);
7195 // Get the config file from the module name
7196 app_config = mono_config_string_for_assembly_file (module);
7199 if (config_file_name != config_file_path)
7200 g_free (config_file_name);
7201 g_free (config_file_path);
7206 return mono_string_new (mono_domain_get (), app_config);
7209 static MonoStringHandle
7210 get_bundled_machine_config (MonoError *error)
7212 const gchar *machine_config;
7214 machine_config = mono_get_machine_config ();
7216 if (!machine_config)
7217 return NULL_HANDLE_STRING;
7219 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7222 ICALL_EXPORT MonoStringHandle
7223 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7225 return get_bundled_machine_config (error);
7229 ICALL_EXPORT MonoStringHandle
7230 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7232 return get_bundled_machine_config (error);
7235 ICALL_EXPORT MonoStringHandle
7236 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7238 return get_bundled_machine_config (error);
7242 ICALL_EXPORT MonoString *
7243 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7248 path = g_path_get_dirname (mono_get_config_dir ());
7250 mono_icall_make_platform_path (path);
7252 ipath = mono_string_new (mono_domain_get (), path);
7258 ICALL_EXPORT gboolean
7259 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7261 MonoPEResourceDataEntry *entry;
7264 if (!assembly || !result || !size)
7269 image = assembly->assembly->image;
7270 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7274 *result = mono_image_rva_map (image, entry->rde_data_offset);
7279 *size = entry->rde_size;
7284 ICALL_EXPORT MonoBoolean
7285 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7287 return mono_is_debugger_attached ();
7290 ICALL_EXPORT MonoBoolean
7291 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7293 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7294 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7300 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7302 if (mono_get_runtime_callbacks ()->debug_log)
7303 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7308 mono_icall_write_windows_debug_string (MonoString *message)
7310 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7312 #endif /* !HOST_WIN32 */
7315 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7317 mono_icall_write_windows_debug_string (message);
7320 /* Only used for value types */
7321 ICALL_EXPORT MonoObject *
7322 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7329 domain = mono_object_domain (type);
7330 klass = mono_class_from_mono_type (type->type);
7331 mono_class_init_checked (klass, &error);
7332 if (mono_error_set_pending_exception (&error))
7335 if (mono_class_is_nullable (klass))
7336 /* No arguments -> null */
7339 result = mono_object_new_checked (domain, klass, &error);
7340 mono_error_set_pending_exception (&error);
7344 ICALL_EXPORT MonoReflectionMethod *
7345 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7347 MonoReflectionMethod *ret = NULL;
7350 MonoClass *klass, *parent;
7351 MonoGenericContext *generic_inst = NULL;
7352 MonoMethod *method = m->method;
7353 MonoMethod *result = NULL;
7356 if (method->klass == NULL)
7359 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7360 MONO_CLASS_IS_INTERFACE (method->klass) ||
7361 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7364 slot = mono_method_get_vtable_slot (method);
7368 klass = method->klass;
7369 if (mono_class_is_ginst (klass)) {
7370 generic_inst = mono_class_get_context (klass);
7371 klass = mono_class_get_generic_class (klass)->container_class;
7376 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7377 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7378 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7379 or klass is the generic container class and generic_inst is the instantiation.
7381 when we go to the parent, if the parent is an open constructed type, we need to
7382 replace the type parameters by the definitions from the generic_inst, and then take it
7383 apart again into the klass and the generic_inst.
7385 For cases like this:
7386 class C<T> : B<T, int> {
7387 public override void Foo () { ... }
7389 class B<U,V> : A<HashMap<U,V>> {
7390 public override void Foo () { ... }
7393 public virtual void Foo () { ... }
7396 if at each iteration the parent isn't open, we can skip inflating it. if at some
7397 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7400 MonoGenericContext *parent_inst = NULL;
7401 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7402 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7403 if (!mono_error_ok (&error)) {
7404 mono_error_set_pending_exception (&error);
7408 if (mono_class_is_ginst (parent)) {
7409 parent_inst = mono_class_get_context (parent);
7410 parent = mono_class_get_generic_class (parent)->container_class;
7413 mono_class_setup_vtable (parent);
7414 if (parent->vtable_size <= slot)
7417 generic_inst = parent_inst;
7420 klass = klass->parent;
7423 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7424 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7425 if (!mono_error_ok (&error)) {
7426 mono_error_set_pending_exception (&error);
7430 generic_inst = NULL;
7432 if (mono_class_is_ginst (klass)) {
7433 generic_inst = mono_class_get_context (klass);
7434 klass = mono_class_get_generic_class (klass)->container_class;
7440 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7441 if (!mono_error_ok (&error)) {
7442 mono_error_set_pending_exception (&error);
7447 if (klass == method->klass)
7450 /*This is possible if definition == FALSE.
7451 * Do it here to be really sure we don't read invalid memory.
7453 if (slot >= klass->vtable_size)
7456 mono_class_setup_vtable (klass);
7458 result = klass->vtable [slot];
7459 if (result == NULL) {
7460 /* It is an abstract method */
7461 gboolean found = FALSE;
7462 gpointer iter = NULL;
7463 while ((result = mono_class_get_methods (klass, &iter))) {
7464 if (result->slot == slot) {
7469 /* found might be FALSE if we looked in an abstract class
7470 * that doesn't override an abstract method of its
7472 * abstract class Base {
7473 * public abstract void Foo ();
7475 * abstract class Derived : Base { }
7476 * class Child : Derived {
7477 * public override void Foo () { }
7480 * if m was Child.Foo and we ask for the base method,
7481 * then we get here with klass == Derived and found == FALSE
7483 /* but it shouldn't be the case that if we're looking
7484 * for the definition and didn't find a result; the
7485 * loop above should've taken us as far as we could
7487 g_assert (!(definition && !found));
7492 g_assert (result != NULL);
7494 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7495 mono_error_set_pending_exception (&error);
7499 ICALL_EXPORT MonoString*
7500 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7502 MonoMethod *method = m->method;
7504 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7509 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7511 iter->sig = *(MonoMethodSignature**)argsp;
7513 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7514 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7517 /* FIXME: it's not documented what start is exactly... */
7521 iter->args = argsp + sizeof (gpointer);
7523 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7525 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7528 ICALL_EXPORT MonoTypedRef
7529 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7531 guint32 i, arg_size;
7535 i = iter->sig->sentinelpos + iter->next_arg;
7537 g_assert (i < iter->sig->param_count);
7539 res.type = iter->sig->params [i];
7540 res.klass = mono_class_from_mono_type (res.type);
7541 arg_size = mono_type_stack_size (res.type, &align);
7542 #if defined(__arm__) || defined(__mips__)
7543 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7545 res.value = iter->args;
7546 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7547 /* Values are stored as 8 byte register sized objects, but 'value'
7548 * is dereferenced as a pointer in other routines.
7550 res.value = (char*)res.value + 4;
7552 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7553 if (arg_size <= sizeof (gpointer)) {
7555 int padding = arg_size - mono_type_size (res.type, &dummy);
7556 res.value = (guint8*)res.value + padding;
7559 iter->args = (char*)iter->args + arg_size;
7562 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7567 ICALL_EXPORT MonoTypedRef
7568 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7570 guint32 i, arg_size;
7574 i = iter->sig->sentinelpos + iter->next_arg;
7576 g_assert (i < iter->sig->param_count);
7578 while (i < iter->sig->param_count) {
7579 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7581 res.type = iter->sig->params [i];
7582 res.klass = mono_class_from_mono_type (res.type);
7583 /* FIXME: endianess issue... */
7584 arg_size = mono_type_stack_size (res.type, &align);
7585 #if defined(__arm__) || defined(__mips__)
7586 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7588 res.value = iter->args;
7589 iter->args = (char*)iter->args + arg_size;
7591 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7594 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7602 ICALL_EXPORT MonoType*
7603 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7607 i = iter->sig->sentinelpos + iter->next_arg;
7609 g_assert (i < iter->sig->param_count);
7611 return iter->sig->params [i];
7614 ICALL_EXPORT MonoObject*
7615 mono_TypedReference_ToObject (MonoTypedRef* tref)
7618 MonoObject *result = NULL;
7619 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7620 MonoObject** objp = (MonoObject **)tref->value;
7624 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7625 mono_error_set_pending_exception (&error);
7629 ICALL_EXPORT MonoTypedRef
7630 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7633 MonoReflectionField *f;
7635 MonoType *ftype = NULL;
7639 memset (&res, 0, sizeof (res));
7642 g_assert (mono_array_length (fields) > 0);
7644 klass = target->vtable->klass;
7646 for (i = 0; i < mono_array_length (fields); ++i) {
7647 f = mono_array_get (fields, MonoReflectionField*, i);
7649 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7652 if (f->field->parent != klass) {
7653 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7657 p = (guint8*)target + f->field->offset;
7659 p += f->field->offset - sizeof (MonoObject);
7660 klass = mono_class_from_mono_type (f->field->type);
7661 ftype = f->field->type;
7665 res.klass = mono_class_from_mono_type (ftype);
7672 prelink_method (MonoMethod *method, MonoError *error)
7674 const char *exc_class, *exc_arg;
7676 mono_error_init (error);
7677 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7679 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7681 mono_error_set_exception_instance (error,
7682 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7685 /* create the wrapper, too? */
7689 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7693 prelink_method (method->method, &error);
7694 mono_error_set_pending_exception (&error);
7698 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7701 MonoClass *klass = mono_class_from_mono_type (type->type);
7703 gpointer iter = NULL;
7705 mono_class_init_checked (klass, &error);
7706 if (mono_error_set_pending_exception (&error))
7709 while ((m = mono_class_get_methods (klass, &iter))) {
7710 prelink_method (m, &error);
7711 if (mono_error_set_pending_exception (&error))
7716 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7718 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7719 gint32 const **exponents,
7720 gunichar2 const **digitLowerTable,
7721 gunichar2 const **digitUpperTable,
7722 gint64 const **tenPowersList,
7723 gint32 const **decHexDigits)
7725 *mantissas = Formatter_MantissaBitsTable;
7726 *exponents = Formatter_TensExponentTable;
7727 *digitLowerTable = Formatter_DigitLowerTable;
7728 *digitUpperTable = Formatter_DigitUpperTable;
7729 *tenPowersList = Formatter_TenPowersList;
7730 *decHexDigits = Formatter_DecHexDigits;
7734 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7735 * and avoid useless allocations.
7738 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7740 MonoReflectionType *rt;
7744 mono_error_init (error);
7745 for (i = 0; i < type->num_mods; ++i) {
7746 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7751 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7752 return_val_if_nok (error, NULL);
7754 for (i = 0; i < type->num_mods; ++i) {
7755 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7756 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7757 return_val_if_nok (error, NULL);
7759 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7760 return_val_if_nok (error, NULL);
7762 mono_array_setref (res, count, rt);
7769 ICALL_EXPORT MonoArray*
7770 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7773 MonoType *type = param->ClassImpl->type;
7774 MonoClass *member_class = mono_object_class (param->MemberImpl);
7775 MonoMethod *method = NULL;
7778 MonoMethodSignature *sig;
7781 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7782 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7783 method = rmethod->method;
7784 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7785 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7786 if (!(method = prop->property->get))
7787 method = prop->property->set;
7790 char *type_name = mono_type_get_full_name (member_class);
7791 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7792 MonoException *ex = mono_get_exception_not_supported (msg);
7795 mono_set_pending_exception (ex);
7799 image = method->klass->image;
7800 pos = param->PositionImpl;
7801 sig = mono_method_signature (method);
7805 type = sig->params [pos];
7807 res = type_array_from_modifiers (image, type, optional, &error);
7808 mono_error_set_pending_exception (&error);
7813 get_property_type (MonoProperty *prop)
7815 MonoMethodSignature *sig;
7817 sig = mono_method_signature (prop->get);
7819 } else if (prop->set) {
7820 sig = mono_method_signature (prop->set);
7821 return sig->params [sig->param_count - 1];
7826 ICALL_EXPORT MonoArray*
7827 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7830 MonoType *type = get_property_type (property->property);
7831 MonoImage *image = property->klass->image;
7836 res = type_array_from_modifiers (image, type, optional, &error);
7837 mono_error_set_pending_exception (&error);
7842 *Construct a MonoType suited to be used to decode a constant blob object.
7844 * @type is the target type which will be constructed
7845 * @blob_type is the blob type, for example, that comes from the constant table
7846 * @real_type is the expected constructed type.
7849 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7851 type->type = blob_type;
7852 type->data.klass = NULL;
7853 if (blob_type == MONO_TYPE_CLASS)
7854 type->data.klass = mono_defaults.object_class;
7855 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7856 /* For enums, we need to use the base type */
7857 type->type = MONO_TYPE_VALUETYPE;
7858 type->data.klass = mono_class_from_mono_type (real_type);
7860 type->data.klass = mono_class_from_mono_type (real_type);
7863 ICALL_EXPORT MonoObject*
7864 property_info_get_default_value (MonoReflectionProperty *property)
7868 MonoProperty *prop = property->property;
7869 MonoType *type = get_property_type (prop);
7870 MonoDomain *domain = mono_object_domain (property);
7871 MonoTypeEnum def_type;
7872 const char *def_value;
7875 mono_class_init (prop->parent);
7877 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7878 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7882 def_value = mono_class_get_property_default_value (prop, &def_type);
7884 mono_type_from_blob_type (&blob_type, def_type, type);
7885 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7887 mono_error_set_pending_exception (&error);
7891 ICALL_EXPORT MonoBoolean
7892 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7895 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7896 MonoCustomAttrInfo *cinfo;
7899 mono_class_init_checked (attr_class, &error);
7900 if (mono_error_set_pending_exception (&error))
7903 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7904 if (!is_ok (&error)) {
7905 mono_error_set_pending_exception (&error);
7910 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7912 mono_custom_attrs_free (cinfo);
7916 ICALL_EXPORT MonoArray*
7917 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7919 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7924 mono_class_init_checked (attr_class, &error);
7925 if (mono_error_set_pending_exception (&error))
7929 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7930 if (!mono_error_ok (&error)) {
7931 mono_error_set_pending_exception (&error);
7938 ICALL_EXPORT MonoArray*
7939 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7943 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7944 mono_error_set_pending_exception (&error);
7949 ICALL_EXPORT MonoStringHandle
7950 ves_icall_Mono_Runtime_GetDisplayName (MonoError *error)
7953 MonoStringHandle display_name;
7955 mono_error_init (error);
7956 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7957 display_name = mono_string_new_handle (mono_domain_get (), info, error);
7959 return display_name;
7962 ICALL_EXPORT MonoString*
7963 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7966 MonoString *message;
7970 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7971 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7974 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7976 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7977 if (mono_error_set_pending_exception (&error))
7985 static inline gint32
7986 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
7988 return WAIT_TIMEOUT;
7990 #endif /* !HOST_WIN32 */
7993 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7995 return mono_icall_wait_for_input_idle (handle, milliseconds);
7999 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8001 return mono_process_current_pid ();
8004 ICALL_EXPORT MonoBoolean
8005 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
8017 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
8019 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
8023 ICALL_EXPORT MonoObject*
8024 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
8026 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
8031 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
8033 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
8037 ICALL_EXPORT MonoObject*
8038 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
8040 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
8044 ICALL_EXPORT MonoBoolean
8045 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
8047 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
8052 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
8054 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
8058 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
8060 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
8065 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
8067 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
8071 ICALL_EXPORT mono_unichar2*
8072 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
8074 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
8081 #ifndef DISABLE_ICALL_TABLES
8083 #define ICALL_TYPE(id,name,first)
8084 #define ICALL(id,name,func) Icall_ ## id,
8085 #define HANDLES(inner) inner
8088 #include "metadata/icall-def.h"
8094 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8095 #define ICALL(id,name,func)
8097 #define HANDLES(inner) inner
8099 #include "metadata/icall-def.h"
8105 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8106 #define ICALL(id,name,func)
8108 #define HANDLES(inner) inner
8110 guint16 first_icall;
8113 static const IcallTypeDesc
8114 icall_type_descs [] = {
8115 #include "metadata/icall-def.h"
8119 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8122 #define HANDLES(inner) inner
8124 #define ICALL_TYPE(id,name,first)
8127 #ifdef HAVE_ARRAY_ELEM_INIT
8128 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8129 #define MSGSTRFIELD1(line) str##line
8131 static const struct msgstrtn_t {
8132 #define ICALL(id,name,func)
8134 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8135 #include "metadata/icall-def.h"
8137 } icall_type_names_str = {
8138 #define ICALL_TYPE(id,name,first) (name),
8139 #include "metadata/icall-def.h"
8142 static const guint16 icall_type_names_idx [] = {
8143 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8144 #include "metadata/icall-def.h"
8147 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8149 static const struct msgstr_t {
8151 #define ICALL_TYPE(id,name,first)
8152 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8153 #include "metadata/icall-def.h"
8155 } icall_names_str = {
8156 #define ICALL(id,name,func) (name),
8157 #include "metadata/icall-def.h"
8160 static const guint16 icall_names_idx [] = {
8161 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8162 #include "metadata/icall-def.h"
8165 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8171 #define ICALL_TYPE(id,name,first) name,
8172 #define ICALL(id,name,func)
8173 static const char* const
8174 icall_type_names [] = {
8175 #include "metadata/icall-def.h"
8179 #define icall_type_name_get(id) (icall_type_names [(id)])
8183 #define ICALL_TYPE(id,name,first)
8184 #define ICALL(id,name,func) name,
8185 static const char* const
8187 #include "metadata/icall-def.h"
8190 #define icall_name_get(id) icall_names [(id)]
8192 #endif /* !HAVE_ARRAY_ELEM_INIT */
8195 #define HANDLES(inner) inner
8198 #define ICALL_TYPE(id,name,first)
8199 #define ICALL(id,name,func) func,
8200 static const gconstpointer
8201 icall_functions [] = {
8202 #include "metadata/icall-def.h"
8206 #ifdef ENABLE_ICALL_SYMBOL_MAP
8208 #define HANDLES(inner) inner
8211 #define ICALL_TYPE(id,name,first)
8212 #define ICALL(id,name,func) #func,
8213 static const gconstpointer
8214 icall_symbols [] = {
8215 #include "metadata/icall-def.h"
8222 #define ICALL_TYPE(id,name,first)
8223 #define ICALL(id,name,func) 0,
8225 #define HANDLES(inner) 1,
8227 icall_uses_handles [] = {
8228 #include "metadata/icall-def.h"
8233 #endif /* DISABLE_ICALL_TABLES */
8235 static mono_mutex_t icall_mutex;
8236 static GHashTable *icall_hash = NULL;
8237 static GHashTable *jit_icall_hash_name = NULL;
8238 static GHashTable *jit_icall_hash_addr = NULL;
8241 mono_icall_init (void)
8243 #ifndef DISABLE_ICALL_TABLES
8246 /* check that tables are sorted: disable in release */
8249 const char *prev_class = NULL;
8250 const char *prev_method;
8252 for (i = 0; i < Icall_type_num; ++i) {
8253 const IcallTypeDesc *desc;
8256 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8257 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8258 prev_class = icall_type_name_get (i);
8259 desc = &icall_type_descs [i];
8260 num_icalls = icall_desc_num_icalls (desc);
8261 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8262 for (j = 0; j < num_icalls; ++j) {
8263 const char *methodn = icall_name_get (desc->first_icall + j);
8264 if (prev_method && strcmp (prev_method, methodn) >= 0)
8265 g_print ("method %s should come before method %s\n", methodn, prev_method);
8266 prev_method = methodn;
8272 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8273 mono_os_mutex_init (&icall_mutex);
8277 mono_icall_lock (void)
8279 mono_locks_os_acquire (&icall_mutex, IcallLock);
8283 mono_icall_unlock (void)
8285 mono_locks_os_release (&icall_mutex, IcallLock);
8289 mono_icall_cleanup (void)
8291 g_hash_table_destroy (icall_hash);
8292 g_hash_table_destroy (jit_icall_hash_name);
8293 g_hash_table_destroy (jit_icall_hash_addr);
8294 mono_os_mutex_destroy (&icall_mutex);
8298 * mono_add_internal_call:
8299 * @name: method specification to surface to the managed world
8300 * @method: pointer to a C method to invoke when the method is called
8302 * This method surfaces the C function pointed by @method as a method
8303 * that has been surfaced in managed code with the method specified in
8304 * @name as an internal call.
8306 * Internal calls are surfaced to all app domains loaded and they are
8307 * accessibly by a type with the specified name.
8309 * You must provide a fully qualified type name, that is namespaces
8310 * and type name, followed by a colon and the method name, with an
8311 * optional signature to bind.
8313 * For example, the following are all valid declarations:
8315 * "MyApp.Services.ScriptService:Accelerate"
8316 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8318 * You use method parameters in cases where there might be more than
8319 * one surface method to managed code. That way you can register different
8320 * internal calls for different method overloads.
8322 * The internal calls are invoked with no marshalling. This means that .NET
8323 * types like System.String are exposed as `MonoString *` parameters. This is
8324 * different than the way that strings are surfaced in P/Invoke.
8326 * For more information on how the parameters are marshalled, see the
8327 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8330 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8331 * reference for more information on the format of method descriptions.
8334 mono_add_internal_call (const char *name, gconstpointer method)
8338 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8340 mono_icall_unlock ();
8343 #ifndef DISABLE_ICALL_TABLES
8345 #ifdef HAVE_ARRAY_ELEM_INIT
8347 compare_method_imap (const void *key, const void *elem)
8349 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8350 return strcmp (key, method_name);
8354 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8356 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);
8359 return (nameslot - &icall_names_idx [0]);
8363 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8365 gsize slotnum = find_slot_icall (imap, name);
8368 return (gboolean)icall_uses_handles [slotnum];
8372 find_method_icall (const IcallTypeDesc *imap, const char *name)
8374 gsize slotnum = find_slot_icall (imap, name);
8377 return (gpointer)icall_functions [slotnum];
8381 compare_class_imap (const void *key, const void *elem)
8383 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8384 return strcmp (key, class_name);
8387 static const IcallTypeDesc*
8388 find_class_icalls (const char *name)
8390 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);
8393 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8396 #else /* HAVE_ARRAY_ELEM_INIT */
8399 compare_method_imap (const void *key, const void *elem)
8401 const char** method_name = (const char**)elem;
8402 return strcmp (key, *method_name);
8406 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8408 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8411 return nameslot - icall_names;
8415 find_method_icall (const IcallTypeDesc *imap, const char *name)
8417 gsize slotnum = find_slot_icall (imap, name);
8420 return (gpointer)icall_functions [slotnum];
8424 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8426 gsize slotnum = find_slot_icall (imap, name);
8429 return (gboolean)icall_uses_handles [slotnum];
8433 compare_class_imap (const void *key, const void *elem)
8435 const char** class_name = (const char**)elem;
8436 return strcmp (key, *class_name);
8439 static const IcallTypeDesc*
8440 find_class_icalls (const char *name)
8442 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8445 return &icall_type_descs [nameslot - icall_type_names];
8448 #endif /* HAVE_ARRAY_ELEM_INIT */
8450 #endif /* DISABLE_ICALL_TABLES */
8453 * we should probably export this as an helper (handle nested types).
8454 * Returns the number of chars written in buf.
8457 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8459 int nspacelen, cnamelen;
8460 nspacelen = strlen (klass->name_space);
8461 cnamelen = strlen (klass->name);
8462 if (nspacelen + cnamelen + 2 > bufsize)
8465 memcpy (buf, klass->name_space, nspacelen);
8466 buf [nspacelen ++] = '.';
8468 memcpy (buf + nspacelen, klass->name, cnamelen);
8469 buf [nspacelen + cnamelen] = 0;
8470 return nspacelen + cnamelen;
8473 #ifdef DISABLE_ICALL_TABLES
8475 no_icall_table (void)
8477 g_assert_not_reached ();
8482 * mono_lookup_internal_call_full:
8483 * @method: the method to look up
8484 * @uses_handles: out argument if method needs handles around managed objects.
8486 * Returns a pointer to the icall code for the given method. If
8487 * uses_handles is not NULL, it will be set to TRUE if the method
8488 * needs managed objects wrapped using the infrastructure in handle.h
8490 * If the method is not found, warns and returns NULL.
8493 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8498 int typelen = 0, mlen, siglen;
8500 #ifndef DISABLE_ICALL_TABLES
8501 const IcallTypeDesc *imap = NULL;
8504 g_assert (method != NULL);
8506 if (method->is_inflated)
8507 method = ((MonoMethodInflated *) method)->declaring;
8509 if (method->klass->nested_in) {
8510 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8514 mname [pos++] = '/';
8517 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8523 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8528 #ifndef DISABLE_ICALL_TABLES
8529 imap = find_class_icalls (mname);
8532 mname [typelen] = ':';
8533 mname [typelen + 1] = ':';
8535 mlen = strlen (method->name);
8536 memcpy (mname + typelen + 2, method->name, mlen);
8537 sigstart = mname + typelen + 2 + mlen;
8540 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8541 siglen = strlen (tmpsig);
8542 if (typelen + mlen + siglen + 6 > sizeof (mname))
8545 memcpy (sigstart + 1, tmpsig, siglen);
8546 sigstart [siglen + 1] = ')';
8547 sigstart [siglen + 2] = 0;
8552 res = g_hash_table_lookup (icall_hash, mname);
8555 *uses_handles = FALSE;
8556 mono_icall_unlock ();;
8559 /* try without signature */
8561 res = g_hash_table_lookup (icall_hash, mname);
8564 *uses_handles = FALSE;
8565 mono_icall_unlock ();
8569 #ifdef DISABLE_ICALL_TABLES
8570 mono_icall_unlock ();
8571 /* Fail only when the result is actually used */
8572 /* mono_marshal_get_native_wrapper () depends on this */
8573 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8574 return ves_icall_System_String_ctor_RedirectToCreateString;
8576 return no_icall_table;
8578 /* it wasn't found in the static call tables */
8581 *uses_handles = FALSE;
8582 mono_icall_unlock ();
8585 res = find_method_icall (imap, sigstart - mlen);
8588 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8589 mono_icall_unlock ();
8592 /* try _with_ signature */
8594 res = find_method_icall (imap, sigstart - mlen);
8597 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8598 mono_icall_unlock ();
8602 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8603 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8604 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8605 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8606 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");
8607 g_print ("If you see other errors or faults after this message they are probably related\n");
8608 g_print ("and you need to fix your mono install first.\n");
8610 mono_icall_unlock ();
8617 mono_lookup_internal_call (MonoMethod *method)
8619 return mono_lookup_internal_call_full (method, NULL);
8622 #ifdef ENABLE_ICALL_SYMBOL_MAP
8624 func_cmp (gconstpointer key, gconstpointer p)
8626 return (gsize)key - (gsize)*(gsize*)p;
8631 * mono_lookup_icall_symbol:
8633 * Given the icall METHOD, returns its C symbol.
8636 mono_lookup_icall_symbol (MonoMethod *m)
8638 #ifdef DISABLE_ICALL_TABLES
8639 g_assert_not_reached ();
8642 #ifdef ENABLE_ICALL_SYMBOL_MAP
8646 static gconstpointer *functions_sorted;
8647 static const char**symbols_sorted;
8648 static gboolean inited;
8653 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8654 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8655 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8656 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8657 /* Bubble sort the two arrays */
8661 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8662 if (functions_sorted [i] > functions_sorted [i + 1]) {
8665 tmp = functions_sorted [i];
8666 functions_sorted [i] = functions_sorted [i + 1];
8667 functions_sorted [i + 1] = tmp;
8668 tmp = symbols_sorted [i];
8669 symbols_sorted [i] = symbols_sorted [i + 1];
8670 symbols_sorted [i + 1] = tmp;
8677 func = mono_lookup_internal_call (m);
8680 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8684 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8686 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8687 g_assert_not_reached ();
8694 type_from_typename (char *type_name)
8696 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8698 if (!strcmp (type_name, "int"))
8699 klass = mono_defaults.int_class;
8700 else if (!strcmp (type_name, "ptr"))
8701 klass = mono_defaults.int_class;
8702 else if (!strcmp (type_name, "void"))
8703 klass = mono_defaults.void_class;
8704 else if (!strcmp (type_name, "int32"))
8705 klass = mono_defaults.int32_class;
8706 else if (!strcmp (type_name, "uint32"))
8707 klass = mono_defaults.uint32_class;
8708 else if (!strcmp (type_name, "int8"))
8709 klass = mono_defaults.sbyte_class;
8710 else if (!strcmp (type_name, "uint8"))
8711 klass = mono_defaults.byte_class;
8712 else if (!strcmp (type_name, "int16"))
8713 klass = mono_defaults.int16_class;
8714 else if (!strcmp (type_name, "uint16"))
8715 klass = mono_defaults.uint16_class;
8716 else if (!strcmp (type_name, "long"))
8717 klass = mono_defaults.int64_class;
8718 else if (!strcmp (type_name, "ulong"))
8719 klass = mono_defaults.uint64_class;
8720 else if (!strcmp (type_name, "float"))
8721 klass = mono_defaults.single_class;
8722 else if (!strcmp (type_name, "double"))
8723 klass = mono_defaults.double_class;
8724 else if (!strcmp (type_name, "object"))
8725 klass = mono_defaults.object_class;
8726 else if (!strcmp (type_name, "obj"))
8727 klass = mono_defaults.object_class;
8728 else if (!strcmp (type_name, "string"))
8729 klass = mono_defaults.string_class;
8730 else if (!strcmp (type_name, "bool"))
8731 klass = mono_defaults.boolean_class;
8732 else if (!strcmp (type_name, "boolean"))
8733 klass = mono_defaults.boolean_class;
8735 g_error ("%s", type_name);
8736 g_assert_not_reached ();
8738 return &klass->byval_arg;
8742 * LOCKING: Take the corlib image lock.
8744 MonoMethodSignature*
8745 mono_create_icall_signature (const char *sigstr)
8750 MonoMethodSignature *res, *res2;
8751 MonoImage *corlib = mono_defaults.corlib;
8753 mono_image_lock (corlib);
8754 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8755 mono_image_unlock (corlib);
8760 parts = g_strsplit (sigstr, " ", 256);
8769 res = mono_metadata_signature_alloc (corlib, len - 1);
8774 * Under windows, the default pinvoke calling convention is STDCALL but
8777 res->call_convention = MONO_CALL_C;
8780 res->ret = type_from_typename (parts [0]);
8781 for (i = 1; i < len; ++i) {
8782 res->params [i - 1] = type_from_typename (parts [i]);
8787 mono_image_lock (corlib);
8788 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8790 res = res2; /*Value is allocated in the image pool*/
8792 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8793 mono_image_unlock (corlib);
8799 mono_find_jit_icall_by_name (const char *name)
8801 MonoJitICallInfo *info;
8802 g_assert (jit_icall_hash_name);
8805 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8806 mono_icall_unlock ();
8811 mono_find_jit_icall_by_addr (gconstpointer addr)
8813 MonoJitICallInfo *info;
8814 g_assert (jit_icall_hash_addr);
8817 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8818 mono_icall_unlock ();
8824 * mono_get_jit_icall_info:
8826 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8827 * caller should access it while holding the icall lock.
8830 mono_get_jit_icall_info (void)
8832 return jit_icall_hash_name;
8836 * mono_lookup_jit_icall_symbol:
8838 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8841 mono_lookup_jit_icall_symbol (const char *name)
8843 MonoJitICallInfo *info;
8844 const char *res = NULL;
8847 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8849 res = info->c_symbol;
8850 mono_icall_unlock ();
8855 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8858 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8859 mono_icall_unlock ();
8863 * 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
8864 * icalls without wrappers in some cases.
8867 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8869 MonoJitICallInfo *info;
8876 if (!jit_icall_hash_name) {
8877 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8878 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8881 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8882 g_warning ("jit icall already defined \"%s\"\n", name);
8883 g_assert_not_reached ();
8886 info = g_new0 (MonoJitICallInfo, 1);
8891 info->c_symbol = c_symbol;
8892 info->no_raise = no_raise;
8895 info->wrapper = func;
8897 info->wrapper = NULL;
8900 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8901 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8903 mono_icall_unlock ();
8908 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8910 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);