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/process.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 #if defined(HAVE_BTLS) && !defined(HAVE_DYNAMIC_BTLS)
109 #include <btls/btls-ssl.h>
110 #include <btls/btls-bio.h>
111 #include <btls/btls-error.h>
112 #include <btls/btls-key.h>
113 #include <btls/btls-pkcs12.h>
114 #include <btls/btls-x509-crl.h>
115 #include <btls/btls-x509-chain.h>
116 #include <btls/btls-x509-lookup.h>
117 #include <btls/btls-x509-lookup-mono.h>
118 #include <btls/btls-x509-name.h>
119 #include <btls/btls-x509-revoked.h>
120 #include <btls/btls-x509-store-ctx.h>
121 #include <btls/btls-x509-verify-param.h>
124 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
126 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
128 /* Lazy class loading functions */
129 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
130 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
131 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
132 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
133 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
134 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
137 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
139 static inline MonoBoolean
140 is_generic_parameter (MonoType *type)
142 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
146 mono_class_init_checked (MonoClass *klass, MonoError *error)
148 mono_error_init (error);
150 if (!mono_class_init (klass))
151 mono_error_set_for_class_failure (error, klass);
156 mono_icall_make_platform_path (gchar *path)
161 static inline const gchar *
162 mono_icall_get_file_path_prefix (const gchar *path)
166 #endif /* HOST_WIN32 */
168 ICALL_EXPORT MonoObject *
169 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
175 MonoObject *result = NULL;
177 ac = (MonoClass *)arr->obj.vtable->klass;
179 esize = mono_array_element_size (ac);
180 ea = (gpointer*)((char*)arr->vector + (pos * esize));
182 if (ac->element_class->valuetype) {
183 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
184 mono_error_set_pending_exception (&error);
186 result = (MonoObject *)*ea;
190 ICALL_EXPORT MonoObject *
191 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
197 MONO_CHECK_ARG_NULL (idxs, NULL);
200 ic = (MonoClass *)io->obj.vtable->klass;
202 ac = (MonoClass *)arr->obj.vtable->klass;
204 g_assert (ic->rank == 1);
205 if (io->bounds != NULL || io->max_length != ac->rank) {
206 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
210 ind = (gint32 *)io->vector;
212 if (arr->bounds == NULL) {
213 if (*ind < 0 || *ind >= arr->max_length) {
214 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
218 return ves_icall_System_Array_GetValueImpl (arr, *ind);
221 for (i = 0; i < ac->rank; i++) {
222 if ((ind [i] < arr->bounds [i].lower_bound) ||
223 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
224 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
229 pos = ind [0] - arr->bounds [0].lower_bound;
230 for (i = 1; i < ac->rank; i++)
231 pos = pos * arr->bounds [i].length + ind [i] -
232 arr->bounds [i].lower_bound;
234 return ves_icall_System_Array_GetValueImpl (arr, pos);
238 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
241 MonoClass *ac, *vc, *ec;
250 mono_error_init (&error);
253 vc = value->vtable->klass;
257 ac = arr->obj.vtable->klass;
258 ec = ac->element_class;
260 esize = mono_array_element_size (ac);
261 ea = (gpointer*)((char*)arr->vector + (pos * esize));
262 va = (gpointer*)((char*)value + sizeof (MonoObject));
264 if (mono_class_is_nullable (ec)) {
265 mono_nullable_init ((guint8*)ea, value, ec);
270 mono_gc_bzero_atomic (ea, esize);
274 #define NO_WIDENING_CONVERSION G_STMT_START{\
275 mono_set_pending_exception (mono_get_exception_argument ( \
276 "value", "not a widening conversion")); \
280 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
281 if (esize < vsize + (extra)) { \
282 mono_set_pending_exception (mono_get_exception_argument ( \
283 "value", "not a widening conversion")); \
288 #define INVALID_CAST G_STMT_START{ \
289 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
290 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
294 /* Check element (destination) type. */
295 switch (ec->byval_arg.type) {
296 case MONO_TYPE_STRING:
297 switch (vc->byval_arg.type) {
298 case MONO_TYPE_STRING:
304 case MONO_TYPE_BOOLEAN:
305 switch (vc->byval_arg.type) {
306 case MONO_TYPE_BOOLEAN:
319 NO_WIDENING_CONVERSION;
328 if (!ec->valuetype) {
329 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
330 if (mono_error_set_pending_exception (&error))
334 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
338 if (mono_object_isinst_checked (value, ec, &error)) {
339 if (ec->has_references)
340 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
342 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
345 if (mono_error_set_pending_exception (&error))
351 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
353 et = ec->byval_arg.type;
354 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
355 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
357 vt = vc->byval_arg.type;
358 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
359 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
361 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
367 case MONO_TYPE_CHAR: \
368 CHECK_WIDENING_CONVERSION(0); \
369 *(etype *) ea = (etype) u64; \
371 /* You can't assign a signed value to an unsigned array. */ \
376 /* You can't assign a floating point number to an integer array. */ \
379 NO_WIDENING_CONVERSION; \
383 #define ASSIGN_SIGNED(etype) G_STMT_START{\
389 CHECK_WIDENING_CONVERSION(0); \
390 *(etype *) ea = (etype) i64; \
392 /* You can assign an unsigned value to a signed array if the array's */ \
393 /* element size is larger than the value size. */ \
398 case MONO_TYPE_CHAR: \
399 CHECK_WIDENING_CONVERSION(1); \
400 *(etype *) ea = (etype) u64; \
402 /* You can't assign a floating point number to an integer array. */ \
405 NO_WIDENING_CONVERSION; \
409 #define ASSIGN_REAL(etype) G_STMT_START{\
413 CHECK_WIDENING_CONVERSION(0); \
414 *(etype *) ea = (etype) r64; \
416 /* All integer values fit into a floating point array, so we don't */ \
417 /* need to CHECK_WIDENING_CONVERSION here. */ \
422 *(etype *) ea = (etype) i64; \
428 case MONO_TYPE_CHAR: \
429 *(etype *) ea = (etype) u64; \
436 u64 = *(guint8 *) va;
439 u64 = *(guint16 *) va;
442 u64 = *(guint32 *) va;
445 u64 = *(guint64 *) va;
451 i64 = *(gint16 *) va;
454 i64 = *(gint32 *) va;
457 i64 = *(gint64 *) va;
460 r64 = *(gfloat *) va;
463 r64 = *(gdouble *) va;
466 u64 = *(guint16 *) va;
468 case MONO_TYPE_BOOLEAN:
469 /* Boolean is only compatible with itself. */
482 NO_WIDENING_CONVERSION;
489 /* If we can't do a direct copy, let's try a widening conversion. */
492 ASSIGN_UNSIGNED (guint16);
494 ASSIGN_UNSIGNED (guint8);
496 ASSIGN_UNSIGNED (guint16);
498 ASSIGN_UNSIGNED (guint32);
500 ASSIGN_UNSIGNED (guint64);
502 ASSIGN_SIGNED (gint8);
504 ASSIGN_SIGNED (gint16);
506 ASSIGN_SIGNED (gint32);
508 ASSIGN_SIGNED (gint64);
510 ASSIGN_REAL (gfloat);
512 ASSIGN_REAL (gdouble);
516 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
520 #undef NO_WIDENING_CONVERSION
521 #undef CHECK_WIDENING_CONVERSION
522 #undef ASSIGN_UNSIGNED
528 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
534 MONO_CHECK_ARG_NULL (idxs,);
536 ic = idxs->obj.vtable->klass;
537 ac = arr->obj.vtable->klass;
539 g_assert (ic->rank == 1);
540 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
541 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
545 ind = (gint32 *)idxs->vector;
547 if (arr->bounds == NULL) {
548 if (*ind < 0 || *ind >= arr->max_length) {
549 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
553 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
557 for (i = 0; i < ac->rank; i++)
558 if ((ind [i] < arr->bounds [i].lower_bound) ||
559 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
560 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
564 pos = ind [0] - arr->bounds [0].lower_bound;
565 for (i = 1; i < ac->rank; i++)
566 pos = pos * arr->bounds [i].length + ind [i] -
567 arr->bounds [i].lower_bound;
569 ves_icall_System_Array_SetValueImpl (arr, value, pos);
572 ICALL_EXPORT MonoArray *
573 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
576 MonoClass *aklass, *klass;
579 gboolean bounded = FALSE;
581 MONO_CHECK_ARG_NULL (type, NULL);
582 MONO_CHECK_ARG_NULL (lengths, NULL);
584 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
586 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
588 for (i = 0; i < mono_array_length (lengths); i++) {
589 if (mono_array_get (lengths, gint32, i) < 0) {
590 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
595 klass = mono_class_from_mono_type (type->type);
596 mono_class_init_checked (klass, &error);
597 if (mono_error_set_pending_exception (&error))
600 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
601 /* vectors are not the same as one dimensional arrays with no-zero bounds */
606 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
608 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
609 for (i = 0; i < aklass->rank; ++i) {
610 sizes [i] = mono_array_get (lengths, guint32, i);
612 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
614 sizes [i + aklass->rank] = 0;
617 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
618 mono_error_set_pending_exception (&error);
623 ICALL_EXPORT MonoArray *
624 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
627 MonoClass *aklass, *klass;
630 gboolean bounded = FALSE;
632 MONO_CHECK_ARG_NULL (type, NULL);
633 MONO_CHECK_ARG_NULL (lengths, NULL);
635 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
637 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
639 for (i = 0; i < mono_array_length (lengths); i++) {
640 if ((mono_array_get (lengths, gint64, i) < 0) ||
641 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
642 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
647 klass = mono_class_from_mono_type (type->type);
648 mono_class_init_checked (klass, &error);
649 if (mono_error_set_pending_exception (&error))
652 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
653 /* vectors are not the same as one dimensional arrays with no-zero bounds */
658 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
660 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
661 for (i = 0; i < aklass->rank; ++i) {
662 sizes [i] = mono_array_get (lengths, guint64, i);
664 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
666 sizes [i + aklass->rank] = 0;
669 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
670 mono_error_set_pending_exception (&error);
676 ves_icall_System_Array_GetRank (MonoObject *arr)
678 return arr->vtable->klass->rank;
682 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
684 gint32 rank = arr->obj.vtable->klass->rank;
687 if ((dimension < 0) || (dimension >= rank)) {
688 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
692 if (arr->bounds == NULL)
693 length = arr->max_length;
695 length = arr->bounds [dimension].length;
697 #ifdef MONO_BIG_ARRAYS
698 if (length > G_MAXINT32) {
699 mono_set_pending_exception (mono_get_exception_overflow ());
707 ves_icall_System_Array_GetLongLength (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)
717 return arr->max_length;
719 return arr->bounds [dimension].length;
723 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
725 gint32 rank = arr->obj.vtable->klass->rank;
727 if ((dimension < 0) || (dimension >= rank)) {
728 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
732 if (arr->bounds == NULL)
735 return arr->bounds [dimension].lower_bound;
739 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
741 int sz = mono_array_element_size (mono_object_class (arr));
742 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
745 ICALL_EXPORT MonoArray*
746 ves_icall_System_Array_Clone (MonoArray *arr)
749 MonoArray *result = mono_array_clone_checked (arr, &error);
750 mono_error_set_pending_exception (&error);
754 ICALL_EXPORT gboolean
755 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
760 MonoVTable *src_vtable;
761 MonoVTable *dest_vtable;
762 MonoClass *src_class;
763 MonoClass *dest_class;
765 src_vtable = source->obj.vtable;
766 dest_vtable = dest->obj.vtable;
768 if (src_vtable->rank != dest_vtable->rank)
771 if (source->bounds || dest->bounds)
774 /* there's no integer overflow since mono_array_length returns an unsigned integer */
775 if ((dest_idx + length > mono_array_length_fast (dest)) ||
776 (source_idx + length > mono_array_length_fast (source)))
779 src_class = src_vtable->klass->element_class;
780 dest_class = dest_vtable->klass->element_class;
783 * Handle common cases.
786 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
787 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
789 if (src_class == mono_defaults.object_class && dest_class->valuetype)
792 /* Check if we're copying a char[] <==> (u)short[] */
793 if (src_class != dest_class) {
794 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
797 /* 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. */
798 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
802 if (dest_class->valuetype) {
803 element_size = mono_array_element_size (source->obj.vtable->klass);
804 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
805 if (dest_class->has_references) {
806 mono_value_copy_array (dest, dest_idx, source_addr, length);
808 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
809 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
812 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
819 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
825 ac = (MonoClass *)arr->obj.vtable->klass;
827 esize = mono_array_element_size (ac);
828 ea = (gpointer*)((char*)arr->vector + (pos * esize));
830 mono_gc_memmove_atomic (value, ea, esize);
834 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
840 ac = (MonoClass *)arr->obj.vtable->klass;
841 ec = ac->element_class;
843 esize = mono_array_element_size (ac);
844 ea = (gpointer*)((char*)arr->vector + (pos * esize));
846 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
847 g_assert (esize == sizeof (gpointer));
848 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
850 g_assert (ec->inited);
851 g_assert (esize == mono_class_value_size (ec, NULL));
852 if (ec->has_references)
853 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
855 mono_gc_memmove_atomic (ea, value, esize);
860 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
862 MonoClass *klass = array->obj.vtable->klass;
863 guint32 size = mono_array_element_size (klass);
864 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
866 const char *field_data;
868 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
869 MonoException *exc = mono_get_exception_argument("array",
870 "Cannot initialize array of non-primitive type.");
871 mono_set_pending_exception (exc);
875 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
876 MonoException *exc = mono_get_exception_argument("field_handle",
877 "Field doesn't have an RVA");
878 mono_set_pending_exception (exc);
882 size *= array->max_length;
883 field_data = mono_field_get_data (field_handle);
885 if (size > mono_type_size (field_handle->type, &align)) {
886 MonoException *exc = mono_get_exception_argument("field_handle",
887 "Field not large enough to fill array");
888 mono_set_pending_exception (exc);
892 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
894 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
895 guint ## n *src = (guint ## n *) field_data; \
897 nEnt = (size / sizeof(guint ## n)); \
899 for (i = 0; i < nEnt; i++) { \
900 data[i] = read ## n (&src[i]); \
904 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
906 switch (type->type) {
923 memcpy (mono_array_addr (array, char, 0), field_data, size);
927 memcpy (mono_array_addr (array, char, 0), field_data, size);
932 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
934 return offsetof (MonoString, chars);
937 ICALL_EXPORT MonoObject *
938 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
940 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
944 MonoObject *ret = mono_object_clone_checked (obj, &error);
945 mono_error_set_pending_exception (&error);
952 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
958 MONO_CHECK_ARG_NULL (handle,);
960 klass = mono_class_from_mono_type (handle);
961 MONO_CHECK_ARG (handle, klass,);
963 if (klass->generic_container)
966 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
967 if (!is_ok (&error)) {
968 mono_error_set_pending_exception (&error);
972 /* This will call the type constructor */
973 if (!mono_runtime_class_init_full (vtable, &error))
974 mono_error_set_pending_exception (&error);
978 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
982 mono_image_check_for_module_cctor (image);
983 if (image->has_module_cctor) {
984 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
985 if (!mono_error_ok (&error)) {
986 mono_error_set_pending_exception (&error);
989 /*It's fine to raise the exception here*/
990 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
991 if (!is_ok (&error)) {
992 mono_error_set_pending_exception (&error);
995 if (!mono_runtime_class_init_full (vtable, &error))
996 mono_error_set_pending_exception (&error);
1000 ICALL_EXPORT MonoBoolean
1001 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
1003 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
1004 // It does not work on win32
1010 MonoInternalThread *thread;
1012 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
1013 /* if we have no info we are optimistic and assume there is enough room */
1017 thread = mono_thread_internal_current ();
1018 // .net seems to check that at least 50% of stack is available
1019 min_size = thread->stack_size / 2;
1021 current = (guint8 *)&stack_addr;
1022 if (current > stack_addr) {
1023 if ((current - stack_addr) < min_size)
1026 if (current - (stack_addr - stack_size) < min_size)
1033 ICALL_EXPORT MonoObject *
1034 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1037 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1038 mono_error_set_pending_exception (&error);
1044 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1048 MonoObject **values = NULL;
1051 gint32 result = (int)(gsize)mono_defaults.int32_class;
1052 MonoClassField* field;
1055 klass = mono_object_class (this_obj);
1057 if (mono_class_num_fields (klass) == 0)
1061 * Compute the starting value of the hashcode for fields of primitive
1062 * types, and return the remaining fields in an array to the managed side.
1063 * This way, we can avoid costly reflection operations in managed code.
1066 while ((field = mono_class_get_fields (klass, &iter))) {
1067 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1069 if (mono_field_is_deleted (field))
1071 /* FIXME: Add more types */
1072 switch (field->type->type) {
1074 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1076 case MONO_TYPE_STRING: {
1078 s = *(MonoString**)((guint8*)this_obj + field->offset);
1080 result ^= mono_string_hash (s);
1085 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1086 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1087 if (!is_ok (&error)) {
1088 mono_error_set_pending_exception (&error);
1091 values [count++] = o;
1097 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1098 if (mono_error_set_pending_exception (&error))
1100 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1101 for (i = 0; i < count; ++i)
1102 mono_array_setref (*fields, i, values [i]);
1109 ICALL_EXPORT MonoBoolean
1110 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1114 MonoObject **values = NULL;
1116 MonoClassField* field;
1120 MONO_CHECK_ARG_NULL (that, FALSE);
1122 if (this_obj->vtable != that->vtable)
1125 klass = mono_object_class (this_obj);
1127 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1128 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1131 * Do the comparison for fields of primitive type and return a result if
1132 * possible. Otherwise, return the remaining fields in an array to the
1133 * managed side. This way, we can avoid costly reflection operations in
1138 while ((field = mono_class_get_fields (klass, &iter))) {
1139 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1141 if (mono_field_is_deleted (field))
1143 /* FIXME: Add more types */
1144 switch (field->type->type) {
1147 case MONO_TYPE_BOOLEAN:
1148 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1153 case MONO_TYPE_CHAR:
1154 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1159 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1164 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1168 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1172 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1177 case MONO_TYPE_STRING: {
1178 MonoString *s1, *s2;
1179 guint32 s1len, s2len;
1180 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1181 s2 = *(MonoString**)((guint8*)that + field->offset);
1184 if ((s1 == NULL) || (s2 == NULL))
1186 s1len = mono_string_length (s1);
1187 s2len = mono_string_length (s2);
1191 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1197 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1198 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1199 if (!is_ok (&error)) {
1200 mono_error_set_pending_exception (&error);
1203 values [count++] = o;
1204 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1205 if (!is_ok (&error)) {
1206 mono_error_set_pending_exception (&error);
1209 values [count++] = o;
1212 if (klass->enumtype)
1213 /* enums only have one non-static field */
1219 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1220 if (mono_error_set_pending_exception (&error))
1222 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1223 for (i = 0; i < count; ++i)
1224 mono_array_setref_fast (*fields, i, values [i]);
1231 ICALL_EXPORT MonoReflectionType *
1232 ves_icall_System_Object_GetType (MonoObject *obj)
1235 MonoReflectionType *ret;
1236 #ifndef DISABLE_REMOTING
1237 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1238 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1241 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1243 mono_error_set_pending_exception (&error);
1248 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1250 MonoMethod **dest = (MonoMethod **)data;
1252 /* skip unmanaged frames */
1257 if (!strcmp (m->klass->name_space, "System.Reflection"))
1266 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1268 MonoMethod **dest = (MonoMethod **)data;
1270 /* skip unmanaged frames */
1274 if (m->wrapper_type != MONO_WRAPPER_NONE)
1282 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1293 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1295 MonoMethod **dest = (MonoMethod **)data;
1297 /* skip unmanaged frames */
1301 if (m->wrapper_type != MONO_WRAPPER_NONE)
1309 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1310 || (!strcmp (m->klass->name_space, "System"))))
1320 static MonoReflectionType *
1321 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1323 MonoMethod *m, *dest;
1325 MonoType *type = NULL;
1326 MonoAssembly *assembly = NULL;
1327 gboolean type_resolve = FALSE;
1328 MonoImage *rootimage = NULL;
1330 mono_error_init (error);
1333 * We must compute the calling assembly as type loading must happen under a metadata context.
1334 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1335 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1337 m = mono_method_get_last_managed ();
1339 if (m && m->klass->image != mono_defaults.corlib) {
1340 /* Happens with inlining */
1342 /* Ugly hack: type_from_parsed_name is called from
1343 * System.Type.internal_from_name, which is called most
1344 * directly from System.Type.GetType(string,bool,bool) but
1345 * also indirectly from places such as
1346 * System.Type.GetType(string,func,func) (via
1347 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1348 * so we need to skip over all of those to find the true caller.
1350 * It would be nice if we had stack marks.
1352 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1358 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1359 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1360 * to crash. This only seems to happen in some strange remoting
1361 * scenarios and I was unable to figure out what's happening there.
1362 * Dec 10, 2005 - Martin.
1366 assembly = dest->klass->image->assembly;
1367 type_resolve = TRUE;
1368 rootimage = assembly->image;
1370 g_warning (G_STRLOC);
1373 if (info->assembly.name)
1374 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1377 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1378 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1379 return_val_if_nok (error, NULL);
1383 // Say we're looking for System.Generic.Dict<int, Local>
1384 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1385 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1386 // is messed up when we go to construct the Local as the type arg...
1388 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1389 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1390 if (!info->assembly.name && !type) {
1392 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1393 return_val_if_nok (error, NULL);
1395 if (assembly && !type && type_resolve) {
1396 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1397 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1398 return_val_if_nok (error, NULL);
1404 return mono_type_get_object_checked (mono_domain_get (), type, error);
1407 ICALL_EXPORT MonoReflectionType*
1408 ves_icall_System_Type_internal_from_name (MonoString *name,
1409 MonoBoolean throwOnError,
1410 MonoBoolean ignoreCase)
1413 MonoTypeNameParse info;
1414 MonoReflectionType *type = NULL;
1417 char *str = mono_string_to_utf8_checked (name, &error);
1418 if (!is_ok (&error))
1421 parsedOk = mono_reflection_parse_type (str, &info);
1423 /* mono_reflection_parse_type() mangles the string */
1425 mono_reflection_free_type_info (&info);
1427 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1431 type = type_from_parsed_name (&info, ignoreCase, &error);
1433 mono_reflection_free_type_info (&info);
1435 if (!is_ok (&error))
1440 mono_error_set_type_load_name (&error, g_strdup (str), g_strdup (""), "");
1447 if (!is_ok (&error)) {
1449 mono_error_set_pending_exception (&error);
1451 mono_error_cleanup (&error);
1459 ICALL_EXPORT MonoReflectionType*
1460 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1463 MonoReflectionType *ret;
1464 MonoDomain *domain = mono_domain_get ();
1466 ret = mono_type_get_object_checked (domain, handle, &error);
1467 mono_error_set_pending_exception (&error);
1472 ICALL_EXPORT MonoType*
1473 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1475 return mono_class_get_type (klass);
1479 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1481 g_ptr_array_free (ptr_array, TRUE);
1485 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1491 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1494 char *res = mono_string_to_utf8_checked (s, &error);
1495 mono_error_set_pending_exception (&error);
1499 /* System.TypeCode */
1518 TYPECODE_STRING = 18
1521 ICALL_EXPORT guint32
1522 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1524 int t = type->type->type;
1526 if (type->type->byref)
1527 return TYPECODE_OBJECT;
1531 case MONO_TYPE_VOID:
1532 return TYPECODE_OBJECT;
1533 case MONO_TYPE_BOOLEAN:
1534 return TYPECODE_BOOLEAN;
1536 return TYPECODE_BYTE;
1538 return TYPECODE_SBYTE;
1540 return TYPECODE_UINT16;
1542 return TYPECODE_INT16;
1543 case MONO_TYPE_CHAR:
1544 return TYPECODE_CHAR;
1548 return TYPECODE_OBJECT;
1550 return TYPECODE_UINT32;
1552 return TYPECODE_INT32;
1554 return TYPECODE_UINT64;
1556 return TYPECODE_INT64;
1558 return TYPECODE_SINGLE;
1560 return TYPECODE_DOUBLE;
1561 case MONO_TYPE_VALUETYPE: {
1562 MonoClass *klass = type->type->data.klass;
1564 if (klass->enumtype) {
1565 t = mono_class_enum_basetype (klass)->type;
1567 } else if (mono_is_corlib_image (klass->image)) {
1568 if (strcmp (klass->name_space, "System") == 0) {
1569 if (strcmp (klass->name, "Decimal") == 0)
1570 return TYPECODE_DECIMAL;
1571 else if (strcmp (klass->name, "DateTime") == 0)
1572 return TYPECODE_DATETIME;
1575 return TYPECODE_OBJECT;
1577 case MONO_TYPE_STRING:
1578 return TYPECODE_STRING;
1579 case MONO_TYPE_SZARRAY:
1580 case MONO_TYPE_ARRAY:
1581 case MONO_TYPE_OBJECT:
1583 case MONO_TYPE_MVAR:
1584 case MONO_TYPE_TYPEDBYREF:
1585 return TYPECODE_OBJECT;
1586 case MONO_TYPE_CLASS:
1588 MonoClass *klass = type->type->data.klass;
1589 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1590 if (strcmp (klass->name, "DBNull") == 0)
1591 return TYPECODE_DBNULL;
1594 return TYPECODE_OBJECT;
1595 case MONO_TYPE_GENERICINST:
1596 return TYPECODE_OBJECT;
1598 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1604 mono_type_is_primitive (MonoType *type)
1606 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1607 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1611 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1613 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1614 return mono_class_enum_basetype (type->data.klass);
1615 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1616 return mono_class_enum_basetype (type->data.generic_class->container_class);
1620 ICALL_EXPORT guint32
1621 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1626 g_assert (type != NULL);
1628 klass = mono_class_from_mono_type (type->type);
1629 klassc = mono_class_from_mono_type (c->type);
1631 if (type->type->byref ^ c->type->byref)
1634 if (type->type->byref) {
1635 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1636 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1638 klass = mono_class_from_mono_type (t);
1639 klassc = mono_class_from_mono_type (ot);
1641 if (mono_type_is_primitive (t)) {
1642 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1643 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1644 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1645 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1646 return t->type == ot->type;
1648 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1651 if (klass->valuetype)
1652 return klass == klassc;
1653 return klass->valuetype == klassc->valuetype;
1656 return mono_class_is_assignable_from (klass, klassc);
1659 ICALL_EXPORT guint32
1660 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1663 MonoClass *klass = mono_class_from_mono_type (type->type);
1664 mono_class_init_checked (klass, &error);
1665 if (!is_ok (&error)) {
1666 mono_error_set_pending_exception (&error);
1669 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1670 mono_error_set_pending_exception (&error);
1674 ICALL_EXPORT guint32
1675 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1677 MonoClass *klass = mono_class_from_mono_type (type->type);
1678 return klass->flags;
1681 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1682 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1685 MonoClass *klass = field->field->parent;
1686 MonoMarshalType *info;
1690 if (klass->generic_container ||
1691 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1694 ftype = mono_field_get_type (field->field);
1695 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1698 info = mono_marshal_load_type_info (klass);
1700 for (i = 0; i < info->num_fields; ++i) {
1701 if (info->fields [i].field == field->field) {
1702 if (!info->fields [i].mspec)
1705 MonoReflectionMarshalAsAttribute* obj;
1706 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1707 if (!mono_error_ok (&error))
1708 mono_error_set_pending_exception (&error);
1717 ICALL_EXPORT MonoReflectionField*
1718 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1721 gboolean found = FALSE;
1727 klass = handle->parent;
1729 klass = mono_class_from_mono_type (type);
1731 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1734 /* The managed code will throw the exception */
1738 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1739 mono_error_set_pending_exception (&error);
1743 ICALL_EXPORT MonoReflectionEvent*
1744 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1752 klass = handle->parent;
1754 klass = mono_class_from_mono_type (type);
1756 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1758 /* Managed code will throw an exception */
1762 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1763 mono_error_set_pending_exception (&error);
1768 ICALL_EXPORT MonoReflectionProperty*
1769 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1777 klass = handle->parent;
1779 klass = mono_class_from_mono_type (type);
1781 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1783 /* Managed code will throw an exception */
1787 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1788 mono_error_set_pending_exception (&error);
1792 ICALL_EXPORT MonoArray*
1793 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1796 MonoType *type = mono_field_get_type_checked (field->field, &error);
1799 if (!mono_error_ok (&error)) {
1800 mono_error_set_pending_exception (&error);
1804 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1805 mono_error_set_pending_exception (&error);
1810 vell_icall_get_method_attributes (MonoMethod *method)
1812 return method->flags;
1816 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1819 MonoReflectionType *rt;
1820 MonoDomain *domain = mono_domain_get ();
1821 MonoMethodSignature* sig;
1823 sig = mono_method_signature_checked (method, &error);
1824 if (!mono_error_ok (&error)) {
1825 mono_error_set_pending_exception (&error);
1829 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1830 if (!mono_error_ok (&error)) {
1831 mono_error_set_pending_exception (&error);
1835 MONO_STRUCT_SETREF (info, parent, rt);
1837 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1838 if (!mono_error_ok (&error)) {
1839 mono_error_set_pending_exception (&error);
1843 MONO_STRUCT_SETREF (info, ret, rt);
1845 info->attrs = method->flags;
1846 info->implattrs = method->iflags;
1847 if (sig->call_convention == MONO_CALL_DEFAULT)
1848 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1850 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1855 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1858 ICALL_EXPORT MonoArray*
1859 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1862 MonoDomain *domain = mono_domain_get ();
1864 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1865 mono_error_set_pending_exception (&error);
1869 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1870 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1873 MonoDomain *domain = mono_domain_get ();
1874 MonoReflectionMarshalAsAttribute* res = NULL;
1875 MonoMarshalSpec **mspecs;
1878 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1879 mono_method_get_marshal_info (method, mspecs);
1882 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1883 if (!mono_error_ok (&error)) {
1884 mono_error_set_pending_exception (&error);
1889 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1891 mono_metadata_free_marshal_spec (mspecs [i]);
1898 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1900 MonoClass *parent = field->field->parent;
1901 if (!parent->size_inited)
1902 mono_class_init (parent);
1903 mono_class_setup_fields (parent);
1905 return field->field->offset - sizeof (MonoObject);
1908 ICALL_EXPORT MonoReflectionType*
1909 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1912 MonoReflectionType *ret;
1915 parent = declaring? field->field->parent: field->klass;
1917 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1918 mono_error_set_pending_exception (&error);
1924 ICALL_EXPORT MonoObject *
1925 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1928 MonoClass *fklass = field->klass;
1929 MonoClassField *cf = field->field;
1930 MonoDomain *domain = mono_object_domain (field);
1932 if (fklass->image->assembly->ref_only) {
1933 mono_set_pending_exception (mono_get_exception_invalid_operation (
1934 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1938 if (mono_security_core_clr_enabled () &&
1939 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1940 mono_error_set_pending_exception (&error);
1944 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1945 mono_error_set_pending_exception (&error);
1950 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1953 MonoClassField *cf = field->field;
1957 if (field->klass->image->assembly->ref_only) {
1958 mono_set_pending_exception (mono_get_exception_invalid_operation (
1959 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1963 if (mono_security_core_clr_enabled () &&
1964 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1965 mono_error_set_pending_exception (&error);
1969 type = mono_field_get_type_checked (cf, &error);
1970 if (!mono_error_ok (&error)) {
1971 mono_error_set_pending_exception (&error);
1975 v = (gchar *) value;
1977 switch (type->type) {
1980 case MONO_TYPE_BOOLEAN:
1983 case MONO_TYPE_CHAR:
1992 case MONO_TYPE_VALUETYPE:
1995 v += sizeof (MonoObject);
1997 case MONO_TYPE_STRING:
1998 case MONO_TYPE_OBJECT:
1999 case MONO_TYPE_CLASS:
2000 case MONO_TYPE_ARRAY:
2001 case MONO_TYPE_SZARRAY:
2004 case MONO_TYPE_GENERICINST: {
2005 MonoGenericClass *gclass = type->data.generic_class;
2006 g_assert (!gclass->context.class_inst->is_open);
2008 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2009 MonoClass *nklass = mono_class_from_mono_type (type);
2010 MonoObject *nullable;
2013 * Convert the boxed vtype into a Nullable structure.
2014 * This is complicated by the fact that Nullables have
2015 * a variable structure.
2017 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2018 if (!mono_error_ok (&error)) {
2019 mono_error_set_pending_exception (&error);
2023 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2025 v = (gchar *)mono_object_unbox (nullable);
2028 if (gclass->container_class->valuetype && (v != NULL))
2029 v += sizeof (MonoObject);
2033 g_error ("type 0x%x not handled in "
2034 "ves_icall_FieldInfo_SetValueInternal", type->type);
2039 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2040 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2041 if (!is_ok (&error)) {
2042 mono_error_set_pending_exception (&error);
2045 if (!vtable->initialized) {
2046 if (!mono_runtime_class_init_full (vtable, &error)) {
2047 mono_error_set_pending_exception (&error);
2051 mono_field_static_set_value (vtable, cf, v);
2053 mono_field_set_value (obj, cf, v);
2058 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2067 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2068 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2072 if (MONO_TYPE_IS_REFERENCE (f->type))
2073 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2075 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2078 ICALL_EXPORT MonoObject *
2079 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2081 MonoObject *o = NULL;
2082 MonoClassField *field = rfield->field;
2084 MonoDomain *domain = mono_object_domain (rfield);
2086 MonoTypeEnum def_type;
2087 const char *def_value;
2091 mono_class_init (field->parent);
2093 t = mono_field_get_type_checked (field, &error);
2094 if (!mono_error_ok (&error)) {
2095 mono_error_set_pending_exception (&error);
2099 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2100 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2104 if (image_is_dynamic (field->parent->image)) {
2105 MonoClass *klass = field->parent;
2106 int fidx = field - klass->fields;
2108 g_assert (fidx >= 0 && fidx < klass->field.count);
2109 g_assert (klass->ext);
2110 g_assert (klass->ext->field_def_values);
2111 def_type = klass->ext->field_def_values [fidx].def_type;
2112 def_value = klass->ext->field_def_values [fidx].data;
2113 if (def_type == MONO_TYPE_END) {
2114 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2118 def_value = mono_class_get_field_default_value (field, &def_type);
2119 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2121 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2126 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2130 case MONO_TYPE_BOOLEAN:
2133 case MONO_TYPE_CHAR:
2141 case MONO_TYPE_R8: {
2144 /* boxed value type */
2145 t = g_new0 (MonoType, 1);
2147 klass = mono_class_from_mono_type (t);
2149 o = mono_object_new_checked (domain, klass, &error);
2150 if (!mono_error_ok (&error)) {
2151 mono_error_set_pending_exception (&error);
2154 v = ((gchar *) o) + sizeof (MonoObject);
2155 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2156 if (mono_error_set_pending_exception (&error))
2160 case MONO_TYPE_STRING:
2161 case MONO_TYPE_CLASS:
2162 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2163 if (mono_error_set_pending_exception (&error))
2167 g_assert_not_reached ();
2173 ICALL_EXPORT MonoReflectionType*
2174 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2177 MonoReflectionType *ret;
2180 type = mono_field_get_type_checked (ref_field->field, &error);
2181 if (!mono_error_ok (&error)) {
2182 mono_error_set_pending_exception (&error);
2186 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2187 if (!mono_error_ok (&error)) {
2188 mono_error_set_pending_exception (&error);
2195 /* From MonoProperty.cs */
2197 PInfo_Attributes = 1,
2198 PInfo_GetMethod = 1 << 1,
2199 PInfo_SetMethod = 1 << 2,
2200 PInfo_ReflectedType = 1 << 3,
2201 PInfo_DeclaringType = 1 << 4,
2206 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2209 MonoReflectionType *rt;
2210 MonoReflectionMethod *rm;
2211 MonoDomain *domain = mono_object_domain (property);
2212 const MonoProperty *pproperty = property->property;
2214 if ((req_info & PInfo_ReflectedType) != 0) {
2215 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2216 if (mono_error_set_pending_exception (&error))
2219 MONO_STRUCT_SETREF (info, parent, rt);
2221 if ((req_info & PInfo_DeclaringType) != 0) {
2222 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2223 if (mono_error_set_pending_exception (&error))
2226 MONO_STRUCT_SETREF (info, declaring_type, rt);
2229 if ((req_info & PInfo_Name) != 0)
2230 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2232 if ((req_info & PInfo_Attributes) != 0)
2233 info->attrs = pproperty->attrs;
2235 if ((req_info & PInfo_GetMethod) != 0) {
2236 if (pproperty->get &&
2237 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2238 pproperty->get->klass == property->klass)) {
2239 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2240 if (mono_error_set_pending_exception (&error))
2246 MONO_STRUCT_SETREF (info, get, rm);
2248 if ((req_info & PInfo_SetMethod) != 0) {
2249 if (pproperty->set &&
2250 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2251 pproperty->set->klass == property->klass)) {
2252 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2253 if (mono_error_set_pending_exception (&error))
2259 MONO_STRUCT_SETREF (info, set, rm);
2262 * There may be other methods defined for properties, though, it seems they are not exposed
2263 * in the reflection API
2268 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2271 MonoReflectionType *rt;
2272 MonoReflectionMethod *rm;
2273 MonoDomain *domain = mono_object_domain (event);
2275 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2276 if (mono_error_set_pending_exception (&error))
2279 MONO_STRUCT_SETREF (info, reflected_type, rt);
2281 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2282 if (mono_error_set_pending_exception (&error))
2285 MONO_STRUCT_SETREF (info, declaring_type, rt);
2287 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2288 info->attrs = event->event->attrs;
2290 if (event->event->add) {
2291 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2292 if (mono_error_set_pending_exception (&error))
2298 MONO_STRUCT_SETREF (info, add_method, rm);
2300 if (event->event->remove) {
2301 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2302 if (mono_error_set_pending_exception (&error))
2308 MONO_STRUCT_SETREF (info, remove_method, rm);
2310 if (event->event->raise) {
2311 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2312 if (mono_error_set_pending_exception (&error))
2318 MONO_STRUCT_SETREF (info, raise_method, rm);
2320 #ifndef MONO_SMALL_CONFIG
2321 if (event->event->other) {
2323 while (event->event->other [n])
2325 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2326 if (mono_error_set_pending_exception (&error))
2328 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2330 for (i = 0; i < n; i++) {
2331 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2332 if (mono_error_set_pending_exception (&error))
2334 mono_array_setref (info->other_methods, i, rm);
2341 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2346 mono_class_setup_interfaces (klass, error);
2347 if (!mono_error_ok (error))
2350 for (i = 0; i < klass->interface_count; i++) {
2351 ic = klass->interfaces [i];
2352 g_hash_table_insert (ifaces, ic, ic);
2354 collect_interfaces (ic, ifaces, error);
2355 if (!mono_error_ok (error))
2361 MonoArray *iface_array;
2362 MonoGenericContext *context;
2366 } FillIfaceArrayData;
2369 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2371 MonoReflectionType *rt;
2372 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2373 MonoClass *ic = (MonoClass *)key;
2374 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2376 if (!mono_error_ok (data->error))
2379 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2380 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2381 if (!mono_error_ok (data->error))
2385 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2386 if (!mono_error_ok (data->error))
2389 mono_array_setref (data->iface_array, data->next_idx++, rt);
2392 mono_metadata_free_type (inflated);
2396 get_interfaces_hash (gconstpointer v1)
2398 MonoClass *k = (MonoClass*)v1;
2400 return k->type_token;
2403 ICALL_EXPORT MonoArray*
2404 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2407 MonoClass *klass = mono_class_from_mono_type (type->type);
2409 FillIfaceArrayData data = { 0 };
2412 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2414 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2415 data.context = mono_class_get_context (klass);
2416 klass = klass->generic_class->container_class;
2419 for (parent = klass; parent; parent = parent->parent) {
2420 mono_class_setup_interfaces (parent, &error);
2421 if (!mono_error_ok (&error))
2423 collect_interfaces (parent, iface_hash, &error);
2424 if (!mono_error_ok (&error))
2428 data.error = &error;
2429 data.domain = mono_object_domain (type);
2431 len = g_hash_table_size (iface_hash);
2433 g_hash_table_destroy (iface_hash);
2434 if (!data.domain->empty_types) {
2435 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2436 if (!is_ok (&error))
2439 return data.domain->empty_types;
2442 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2443 if (!is_ok (&error))
2445 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2446 if (!mono_error_ok (&error))
2449 g_hash_table_destroy (iface_hash);
2450 return data.iface_array;
2453 g_hash_table_destroy (iface_hash);
2454 mono_error_set_pending_exception (&error);
2459 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2461 gboolean variance_used;
2462 MonoClass *klass = mono_class_from_mono_type (type->type);
2463 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2464 MonoReflectionMethod *member;
2467 int i = 0, len, ioffset;
2471 mono_class_init_checked (klass, &error);
2472 if (mono_error_set_pending_exception (&error))
2474 mono_class_init_checked (iclass, &error);
2475 if (mono_error_set_pending_exception (&error))
2478 mono_class_setup_vtable (klass);
2480 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2484 len = mono_class_num_methods (iclass);
2485 domain = mono_object_domain (type);
2486 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2487 if (mono_error_set_pending_exception (&error))
2489 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2490 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2491 if (mono_error_set_pending_exception (&error))
2493 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2495 while ((method = mono_class_get_methods (iclass, &iter))) {
2496 member = mono_method_get_object_checked (domain, method, iclass, &error);
2497 if (mono_error_set_pending_exception (&error))
2499 mono_array_setref (*methods, i, member);
2500 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2501 if (mono_error_set_pending_exception (&error))
2503 mono_array_setref (*targets, i, member);
2510 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2513 MonoClass *klass = mono_class_from_mono_type (type->type);
2515 mono_class_init_checked (klass, &error);
2516 if (mono_error_set_pending_exception (&error))
2519 if (image_is_dynamic (klass->image)) {
2520 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2521 *packing = tb->packing_size;
2522 *size = tb->class_size;
2524 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2528 ICALL_EXPORT MonoReflectionType*
2529 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2532 MonoReflectionType *ret;
2535 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2536 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2537 mono_error_set_pending_exception (&error);
2541 klass = mono_class_from_mono_type (type->type);
2542 mono_class_init_checked (klass, &error);
2543 if (mono_error_set_pending_exception (&error))
2547 // GetElementType should only return a type for:
2548 // Array Pointer PassedByRef
2549 if (type->type->byref)
2550 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2551 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2552 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2553 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2554 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2558 mono_error_set_pending_exception (&error);
2563 ICALL_EXPORT MonoReflectionType*
2564 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2567 MonoReflectionType *ret;
2569 if (type->type->byref)
2572 MonoClass *klass = mono_class_from_mono_type (type->type);
2576 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2577 mono_error_set_pending_exception (&error);
2582 ICALL_EXPORT MonoBoolean
2583 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2585 return type->type->type == MONO_TYPE_PTR;
2588 ICALL_EXPORT MonoBoolean
2589 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2591 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)));
2594 ICALL_EXPORT MonoBoolean
2595 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2597 return type->type->byref;
2600 ICALL_EXPORT MonoBoolean
2601 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2604 MonoClass *klass = mono_class_from_mono_type (type->type);
2605 mono_class_init_checked (klass, &error);
2606 if (mono_error_set_pending_exception (&error))
2609 return mono_class_is_com_object (klass);
2612 ICALL_EXPORT guint32
2613 ves_icall_reflection_get_token (MonoObject* obj)
2616 guint32 result = mono_reflection_get_token_checked (obj, &error);
2617 mono_error_set_pending_exception (&error);
2621 ICALL_EXPORT MonoReflectionModule*
2622 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2625 MonoReflectionModule *result = NULL;
2626 MonoClass *klass = mono_class_from_mono_type (type->type);
2627 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2628 mono_error_set_pending_exception (&error);
2632 ICALL_EXPORT MonoReflectionAssembly*
2633 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2636 MonoDomain *domain = mono_domain_get ();
2637 MonoClass *klass = mono_class_from_mono_type (type->type);
2638 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2639 mono_error_set_pending_exception (&error);
2643 ICALL_EXPORT MonoReflectionType*
2644 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2647 MonoReflectionType *ret;
2648 MonoDomain *domain = mono_domain_get ();
2651 if (type->type->byref)
2653 if (type->type->type == MONO_TYPE_VAR) {
2654 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2655 klass = param ? param->owner.klass : NULL;
2656 } else if (type->type->type == MONO_TYPE_MVAR) {
2657 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2658 klass = param ? param->owner.method->klass : NULL;
2660 klass = mono_class_from_mono_type (type->type)->nested_in;
2666 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2667 mono_error_set_pending_exception (&error);
2672 ICALL_EXPORT MonoStringHandle
2673 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2675 MonoDomain *domain = mono_domain_get ();
2676 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2677 MonoClass *klass = mono_class_from_mono_type (type);
2680 char *n = g_strdup_printf ("%s&", klass->name);
2681 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2687 return mono_string_new_handle (domain, klass->name, error);
2691 ICALL_EXPORT MonoStringHandle
2692 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2694 MonoDomain *domain = mono_domain_get ();
2695 MonoClass *klass = mono_class_from_mono_type_handle (type);
2697 while (klass->nested_in)
2698 klass = klass->nested_in;
2700 if (klass->name_space [0] == '\0')
2701 return NULL_HANDLE_STRING;
2703 return mono_string_new_handle (domain, klass->name_space, error);
2707 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2711 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2712 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2716 klass = mono_class_from_mono_type (type->type);
2722 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2724 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2727 ICALL_EXPORT MonoArray*
2728 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2731 MonoReflectionType *rt;
2733 MonoClass *klass, *pklass;
2734 MonoDomain *domain = mono_object_domain (type);
2737 klass = mono_class_from_mono_type (type->type);
2739 if (klass->generic_container) {
2740 MonoGenericContainer *container = klass->generic_container;
2741 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2742 if (mono_error_set_pending_exception (&error))
2744 for (i = 0; i < container->type_argc; ++i) {
2745 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2747 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2748 if (mono_error_set_pending_exception (&error))
2751 mono_array_setref (res, i, rt);
2753 } else if (klass->generic_class) {
2754 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2755 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2756 if (mono_error_set_pending_exception (&error))
2758 for (i = 0; i < inst->type_argc; ++i) {
2759 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2760 if (mono_error_set_pending_exception (&error))
2763 mono_array_setref (res, i, rt);
2771 ICALL_EXPORT gboolean
2772 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2776 if (!IS_MONOTYPE (type))
2779 if (type->type->byref)
2782 klass = mono_class_from_mono_type (type->type);
2783 return klass->generic_container != NULL;
2786 ICALL_EXPORT MonoReflectionType*
2787 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2790 MonoReflectionType *ret;
2793 if (type->type->byref)
2796 klass = mono_class_from_mono_type (type->type);
2798 if (klass->generic_container) {
2799 return type; /* check this one */
2801 if (klass->generic_class) {
2802 MonoClass *generic_class = klass->generic_class->container_class;
2805 tb = mono_class_get_ref_info (generic_class);
2807 if (generic_class->wastypebuilder && tb)
2808 return (MonoReflectionType *)tb;
2810 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2811 mono_error_set_pending_exception (&error);
2819 ICALL_EXPORT MonoReflectionType*
2820 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2823 MonoReflectionType *ret;
2825 MonoType *geninst, **types;
2828 g_assert (IS_MONOTYPE (type));
2829 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2830 if (mono_error_set_pending_exception (&error))
2833 count = mono_array_length (type_array);
2834 types = g_new0 (MonoType *, count);
2836 for (i = 0; i < count; i++) {
2837 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2838 types [i] = t->type;
2841 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2844 mono_error_set_pending_exception (&error);
2848 klass = mono_class_from_mono_type (geninst);
2850 /*we might inflate to the GTD*/
2851 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2852 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2856 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2857 mono_error_set_pending_exception (&error);
2862 ICALL_EXPORT gboolean
2863 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2867 if (!IS_MONOTYPE (type))
2870 if (type->type->byref)
2873 klass = mono_class_from_mono_type (type->type);
2874 return klass->generic_class != NULL || klass->generic_container != NULL;
2878 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2880 if (!IS_MONOTYPE (type))
2883 if (is_generic_parameter (type->type))
2884 return mono_type_get_generic_param_num (type->type);
2888 ICALL_EXPORT MonoGenericParamInfo *
2889 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2891 return mono_generic_param_info (type->type->data.generic_param);
2894 ICALL_EXPORT MonoBoolean
2895 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2897 return is_generic_parameter (type->type);
2900 ICALL_EXPORT MonoReflectionMethod*
2901 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2902 MonoReflectionMethod* generic)
2909 MonoReflectionMethod *ret = NULL;
2911 domain = ((MonoObject *)type)->vtable->domain;
2913 klass = mono_class_from_mono_type (type->type);
2914 mono_class_init_checked (klass, &error);
2915 if (mono_error_set_pending_exception (&error))
2919 while ((method = mono_class_get_methods (klass, &iter))) {
2920 if (method->token == generic->method->token) {
2921 ret = mono_method_get_object_checked (domain, method, klass, &error);
2922 if (mono_error_set_pending_exception (&error))
2930 ICALL_EXPORT MonoReflectionMethod *
2931 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2934 MonoType *type = ref_type->type;
2936 MonoReflectionMethod *ret = NULL;
2938 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2939 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2942 if (type->type == MONO_TYPE_VAR)
2945 method = mono_type_get_generic_param_owner (type)->owner.method;
2948 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2949 if (!mono_error_ok (&error))
2950 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2954 ICALL_EXPORT MonoBoolean
2955 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2957 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2961 ICALL_EXPORT MonoBoolean
2962 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2964 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2969 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2971 MonoDomain *domain = mono_domain_get ();
2972 MonoImage *image = method->method->klass->image;
2973 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2974 MonoTableInfo *tables = image->tables;
2975 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2976 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2977 guint32 im_cols [MONO_IMPLMAP_SIZE];
2978 guint32 scope_token;
2979 const char *import = NULL;
2980 const char *scope = NULL;
2982 if (image_is_dynamic (image)) {
2983 MonoReflectionMethodAux *method_aux =
2984 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2986 import = method_aux->dllentry;
2987 scope = method_aux->dll;
2990 if (!import || !scope) {
2991 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2996 if (piinfo->implmap_idx) {
2997 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2999 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3000 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3001 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3002 scope = mono_metadata_string_heap (image, scope_token);
3006 *flags = piinfo->piflags;
3007 *entry_point = mono_string_new (domain, import);
3008 *dll_name = mono_string_new (domain, scope);
3011 ICALL_EXPORT MonoReflectionMethod *
3012 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3014 MonoMethodInflated *imethod;
3016 MonoReflectionMethod *ret = NULL;
3019 if (method->method->is_generic)
3022 if (!method->method->is_inflated)
3025 imethod = (MonoMethodInflated *) method->method;
3027 result = imethod->declaring;
3028 /* Not a generic method. */
3029 if (!result->is_generic)
3032 if (image_is_dynamic (method->method->klass->image)) {
3033 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3034 MonoReflectionMethod *res;
3037 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3038 * the dynamic case as well ?
3040 mono_image_lock ((MonoImage*)image);
3041 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3042 mono_image_unlock ((MonoImage*)image);
3048 if (imethod->context.class_inst) {
3049 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3050 /*Generic methods gets the context of the GTD.*/
3051 if (mono_class_get_context (klass)) {
3052 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3053 if (!mono_error_ok (&error))
3058 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3060 if (!mono_error_ok (&error))
3061 mono_error_set_pending_exception (&error);
3065 ICALL_EXPORT gboolean
3066 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3068 return mono_method_signature (method->method)->generic_param_count != 0;
3071 ICALL_EXPORT gboolean
3072 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3074 return method->method->is_generic;
3077 ICALL_EXPORT MonoArray*
3078 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3081 MonoReflectionType *rt;
3086 domain = mono_object_domain (method);
3088 if (method->method->is_inflated) {
3089 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3092 count = inst->type_argc;
3093 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3094 if (mono_error_set_pending_exception (&error))
3097 for (i = 0; i < count; i++) {
3098 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3099 if (mono_error_set_pending_exception (&error))
3102 mono_array_setref (res, i, rt);
3109 count = mono_method_signature (method->method)->generic_param_count;
3110 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3111 if (mono_error_set_pending_exception (&error))
3114 for (i = 0; i < count; i++) {
3115 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3116 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3117 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3119 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3120 if (mono_error_set_pending_exception (&error))
3123 mono_array_setref (res, i, rt);
3129 ICALL_EXPORT MonoObject *
3130 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3134 * Invoke from reflection is supposed to always be a virtual call (the API
3135 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3136 * greater flexibility.
3138 MonoMethod *m = method->method;
3139 MonoMethodSignature *sig = mono_method_signature (m);
3142 void *obj = this_arg;
3146 if (mono_security_core_clr_enabled () &&
3147 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3148 mono_error_set_pending_exception (&error);
3152 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3153 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3154 mono_error_cleanup (&error); /* FIXME does this make sense? */
3155 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3160 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3161 if (!is_ok (&error)) {
3162 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3165 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3166 char *target_name = mono_type_get_full_name (m->klass);
3167 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3168 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3170 g_free (target_name);
3174 m = mono_object_get_virtual_method (this_arg, m);
3175 /* must pass the pointer to the value for valuetype methods */
3176 if (m->klass->valuetype)
3177 obj = mono_object_unbox (this_arg);
3178 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3179 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3184 if (sig->ret->byref) {
3185 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"));
3189 pcount = params? mono_array_length (params): 0;
3190 if (pcount != sig->param_count) {
3191 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3195 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3196 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."));
3200 image = m->klass->image;
3201 if (image->assembly->ref_only) {
3202 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."));
3206 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3207 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3211 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3215 intptr_t *lower_bounds;
3216 pcount = mono_array_length (params);
3217 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3218 /* Note: the synthetized array .ctors have int32 as argument type */
3219 for (i = 0; i < pcount; ++i)
3220 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3222 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3223 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3224 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3225 if (!mono_error_ok (&error)) {
3226 mono_error_set_pending_exception (&error);
3230 for (i = 0; i < mono_array_length (arr); ++i) {
3231 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3232 if (!mono_error_ok (&error)) {
3233 mono_error_set_pending_exception (&error);
3236 mono_array_setref_fast (arr, i, subarray);
3238 return (MonoObject*)arr;
3241 if (m->klass->rank == pcount) {
3242 /* Only lengths provided. */
3243 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3244 if (!mono_error_ok (&error)) {
3245 mono_error_set_pending_exception (&error);
3249 return (MonoObject*)arr;
3251 g_assert (pcount == (m->klass->rank * 2));
3252 /* The arguments are lower-bound-length pairs */
3253 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3255 for (i = 0; i < pcount / 2; ++i) {
3256 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3257 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3260 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3261 if (!mono_error_ok (&error)) {
3262 mono_error_set_pending_exception (&error);
3266 return (MonoObject*)arr;
3269 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3270 mono_error_set_pending_exception (&error);
3274 #ifndef DISABLE_REMOTING
3275 ICALL_EXPORT MonoObject *
3276 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3279 MonoDomain *domain = mono_object_domain (method);
3280 MonoMethod *m = method->method;
3281 MonoMethodSignature *sig = mono_method_signature (m);
3282 MonoArray *out_args;
3284 int i, j, outarg_count = 0;
3286 if (m->klass == mono_defaults.object_class) {
3287 if (!strcmp (m->name, "FieldGetter")) {
3288 MonoClass *k = this_arg->vtable->klass;
3292 /* If this is a proxy, then it must be a CBO */
3293 if (k == mono_defaults.transparent_proxy_class) {
3294 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3295 this_arg = tp->rp->unwrapped_server;
3296 g_assert (this_arg);
3297 k = this_arg->vtable->klass;
3300 name = mono_array_get (params, MonoString *, 1);
3301 str = mono_string_to_utf8_checked (name, &error);
3302 if (mono_error_set_pending_exception (&error))
3306 MonoClassField* field = mono_class_get_field_from_name (k, str);
3309 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3310 if (field_klass->valuetype) {
3311 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3312 if (mono_error_set_pending_exception (&error))
3315 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3317 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3318 if (mono_error_set_pending_exception (&error))
3320 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3321 mono_array_setref (out_args, 0, result);
3328 g_assert_not_reached ();
3330 } else if (!strcmp (m->name, "FieldSetter")) {
3331 MonoClass *k = this_arg->vtable->klass;
3337 /* If this is a proxy, then it must be a CBO */
3338 if (k == mono_defaults.transparent_proxy_class) {
3339 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3340 this_arg = tp->rp->unwrapped_server;
3341 g_assert (this_arg);
3342 k = this_arg->vtable->klass;
3345 name = mono_array_get (params, MonoString *, 1);
3346 str = mono_string_to_utf8_checked (name, &error);
3347 if (mono_error_set_pending_exception (&error))
3351 MonoClassField* field = mono_class_get_field_from_name (k, str);
3354 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3355 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3357 if (field_klass->valuetype) {
3358 size = mono_type_size (field->type, &align);
3359 g_assert (size == mono_class_value_size (field_klass, NULL));
3360 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3362 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3365 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3366 if (mono_error_set_pending_exception (&error))
3368 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3377 g_assert_not_reached ();
3382 for (i = 0; i < mono_array_length (params); i++) {
3383 if (sig->params [i]->byref)
3387 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3388 if (mono_error_set_pending_exception (&error))
3391 /* handle constructors only for objects already allocated */
3392 if (!strcmp (method->method->name, ".ctor"))
3393 g_assert (this_arg);
3395 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3396 g_assert (!method->method->klass->valuetype);
3397 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3398 if (mono_error_set_pending_exception (&error))
3401 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3402 if (sig->params [i]->byref) {
3404 arg = mono_array_get (params, gpointer, i);
3405 mono_array_setref (out_args, j, arg);
3410 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3417 read_enum_value (const char *mem, int type)
3420 case MONO_TYPE_BOOLEAN:
3422 return *(guint8*)mem;
3424 return *(gint8*)mem;
3425 case MONO_TYPE_CHAR:
3427 return read16 (mem);
3429 return (gint16) read16 (mem);
3431 return read32 (mem);
3433 return (gint32) read32 (mem);
3436 return read64 (mem);
3438 g_assert_not_reached ();
3444 write_enum_value (char *mem, int type, guint64 value)
3448 case MONO_TYPE_I1: {
3449 guint8 *p = (guint8*)mem;
3455 case MONO_TYPE_CHAR: {
3456 guint16 *p = (guint16 *)mem;
3461 case MONO_TYPE_I4: {
3462 guint32 *p = (guint32 *)mem;
3467 case MONO_TYPE_I8: {
3468 guint64 *p = (guint64 *)mem;
3473 g_assert_not_reached ();
3478 ICALL_EXPORT MonoObject *
3479 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3487 domain = mono_object_domain (enumType);
3488 enumc = mono_class_from_mono_type (enumType->type);
3490 mono_class_init_checked (enumc, &error);
3491 if (mono_error_set_pending_exception (&error))
3494 etype = mono_class_enum_basetype (enumc);
3496 res = mono_object_new_checked (domain, enumc, &error);
3497 if (mono_error_set_pending_exception (&error))
3499 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3504 ICALL_EXPORT MonoBoolean
3505 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3507 int size = mono_class_value_size (a->vtable->klass, NULL);
3508 guint64 a_val = 0, b_val = 0;
3510 memcpy (&a_val, mono_object_unbox (a), size);
3511 memcpy (&b_val, mono_object_unbox (b), size);
3513 return (a_val & b_val) == b_val;
3516 ICALL_EXPORT MonoObject *
3517 ves_icall_System_Enum_get_value (MonoObject *eobj)
3529 g_assert (eobj->vtable->klass->enumtype);
3531 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3532 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3533 if (mono_error_set_pending_exception (&error))
3535 dst = (char *)res + sizeof (MonoObject);
3536 src = (char *)eobj + sizeof (MonoObject);
3537 size = mono_class_value_size (enumc, NULL);
3539 memcpy (dst, src, size);
3544 ICALL_EXPORT MonoReflectionType *
3545 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3548 MonoReflectionType *ret;
3552 klass = mono_class_from_mono_type (type->type);
3553 mono_class_init_checked (klass, &error);
3554 if (mono_error_set_pending_exception (&error))
3557 etype = mono_class_enum_basetype (klass);
3559 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3563 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3564 mono_error_set_pending_exception (&error);
3570 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3572 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3573 gpointer odata = (char *)other + sizeof (MonoObject);
3574 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3575 g_assert (basetype);
3580 if (eobj->vtable->klass != other->vtable->klass)
3583 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3584 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3585 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3588 return me > other ? 1 : -1; \
3591 switch (basetype->type) {
3593 COMPARE_ENUM_VALUES (guint8);
3595 COMPARE_ENUM_VALUES (gint8);
3596 case MONO_TYPE_CHAR:
3598 COMPARE_ENUM_VALUES (guint16);
3600 COMPARE_ENUM_VALUES (gint16);
3602 COMPARE_ENUM_VALUES (guint32);
3604 COMPARE_ENUM_VALUES (gint32);
3606 COMPARE_ENUM_VALUES (guint64);
3608 COMPARE_ENUM_VALUES (gint64);
3612 #undef COMPARE_ENUM_VALUES
3613 /* indicates that the enum was of an unsupported unerlying type */
3618 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3620 gpointer data = (char *)eobj + sizeof (MonoObject);
3621 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3622 g_assert (basetype);
3624 switch (basetype->type) {
3625 case MONO_TYPE_I1: {
3626 gint8 value = *((gint8*)data);
3627 return ((int)value ^ (int)value << 8);
3630 return *((guint8*)data);
3631 case MONO_TYPE_CHAR:
3633 return *((guint16*)data);
3635 case MONO_TYPE_I2: {
3636 gint16 value = *((gint16*)data);
3637 return ((int)(guint16)value | (((int)value) << 16));
3640 return *((guint32*)data);
3642 return *((gint32*)data);
3644 case MONO_TYPE_I8: {
3645 gint64 value = *((gint64*)data);
3646 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3649 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3654 ICALL_EXPORT MonoBoolean
3655 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3658 MonoDomain *domain = mono_object_domain (type);
3659 MonoClass *enumc = mono_class_from_mono_type (type->type);
3660 guint j = 0, nvalues;
3662 MonoClassField *field;
3664 guint64 field_value, previous_value = 0;
3665 gboolean sorted = TRUE;
3667 mono_class_init_checked (enumc, &error);
3668 if (mono_error_set_pending_exception (&error))
3672 if (!enumc->enumtype) {
3673 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3677 base_type = mono_class_enum_basetype (enumc)->type;
3679 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3680 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3681 if (mono_error_set_pending_exception (&error))
3683 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3684 if (mono_error_set_pending_exception (&error))
3688 while ((field = mono_class_get_fields (enumc, &iter))) {
3690 MonoTypeEnum def_type;
3692 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3694 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3696 if (mono_field_is_deleted (field))
3698 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3700 p = mono_class_get_field_default_value (field, &def_type);
3701 /* len = */ mono_metadata_decode_blob_size (p, &p);
3703 field_value = read_enum_value (p, base_type);
3704 mono_array_set (*values, guint64, j, field_value);
3706 if (previous_value > field_value)
3709 previous_value = field_value;
3717 BFLAGS_IgnoreCase = 1,
3718 BFLAGS_DeclaredOnly = 2,
3719 BFLAGS_Instance = 4,
3721 BFLAGS_Public = 0x10,
3722 BFLAGS_NonPublic = 0x20,
3723 BFLAGS_FlattenHierarchy = 0x40,
3724 BFLAGS_InvokeMethod = 0x100,
3725 BFLAGS_CreateInstance = 0x200,
3726 BFLAGS_GetField = 0x400,
3727 BFLAGS_SetField = 0x800,
3728 BFLAGS_GetProperty = 0x1000,
3729 BFLAGS_SetProperty = 0x2000,
3730 BFLAGS_ExactBinding = 0x10000,
3731 BFLAGS_SuppressChangeType = 0x20000,
3732 BFLAGS_OptionalParamBinding = 0x40000
3735 ICALL_EXPORT GPtrArray*
3736 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3739 MonoClass *startklass, *klass;
3742 int (*compare_func) (const char *s1, const char *s2) = NULL;
3743 MonoClassField *field;
3745 if (type->type->byref) {
3746 return g_ptr_array_new ();
3749 mono_error_init (&error);
3751 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3753 klass = startklass = mono_class_from_mono_type (type->type);
3755 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3758 if (mono_class_has_failure (klass)) {
3759 mono_error_set_for_class_failure (&error, klass);
3764 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3765 guint32 flags = mono_field_get_flags (field);
3767 if (mono_field_is_deleted_with_flags (field, flags))
3769 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3770 if (bflags & BFLAGS_Public)
3772 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3773 if (bflags & BFLAGS_NonPublic) {
3780 if (flags & FIELD_ATTRIBUTE_STATIC) {
3781 if (bflags & BFLAGS_Static)
3782 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3785 if (bflags & BFLAGS_Instance)
3792 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3795 g_ptr_array_add (ptr_array, field);
3797 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3803 g_ptr_array_free (ptr_array, TRUE);
3804 mono_error_set_pending_exception (&error);
3809 method_nonpublic (MonoMethod* method, gboolean start_klass)
3811 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3812 case METHOD_ATTRIBUTE_ASSEM:
3813 return (start_klass || mono_defaults.generic_ilist_class);
3814 case METHOD_ATTRIBUTE_PRIVATE:
3816 case METHOD_ATTRIBUTE_PUBLIC:
3824 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3827 MonoClass *startklass;
3831 /*FIXME, use MonoBitSet*/
3832 guint32 method_slots_default [8];
3833 guint32 *method_slots = NULL;
3834 int (*compare_func) (const char *s1, const char *s2) = NULL;
3836 array = g_ptr_array_new ();
3838 mono_error_init (error);
3841 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3843 /* An optimization for calls made from Delegate:CreateDelegate () */
3844 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3845 method = mono_get_delegate_invoke (klass);
3848 g_ptr_array_add (array, method);
3852 mono_class_setup_methods (klass);
3853 mono_class_setup_vtable (klass);
3854 if (mono_class_has_failure (klass))
3857 if (is_generic_parameter (&klass->byval_arg))
3858 nslots = mono_class_get_vtable_size (klass->parent);
3860 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3861 if (nslots >= sizeof (method_slots_default) * 8) {
3862 method_slots = g_new0 (guint32, nslots / 32 + 1);
3864 method_slots = method_slots_default;
3865 memset (method_slots, 0, sizeof (method_slots_default));
3868 mono_class_setup_methods (klass);
3869 mono_class_setup_vtable (klass);
3870 if (mono_class_has_failure (klass))
3874 while ((method = mono_class_get_methods (klass, &iter))) {
3876 if (method->slot != -1) {
3877 g_assert (method->slot < nslots);
3878 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3880 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3881 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3884 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3886 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3887 if (bflags & BFLAGS_Public)
3889 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3895 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3896 if (bflags & BFLAGS_Static)
3897 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3900 if (bflags & BFLAGS_Instance)
3908 if (compare_func (name, method->name))
3913 g_ptr_array_add (array, method);
3915 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3917 if (method_slots != method_slots_default)
3918 g_free (method_slots);
3923 if (method_slots != method_slots_default)
3924 g_free (method_slots);
3925 g_ptr_array_free (array, TRUE);
3927 g_assert (mono_class_has_failure (klass));
3928 mono_error_set_for_class_failure (error, klass);
3932 ICALL_EXPORT GPtrArray*
3933 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3936 GPtrArray *method_array;
3939 klass = mono_class_from_mono_type (type->type);
3940 if (type->type->byref) {
3941 return g_ptr_array_new ();
3944 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3945 mono_error_set_pending_exception (&error);
3946 return method_array;
3949 ICALL_EXPORT GPtrArray*
3950 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3952 MonoClass *startklass, *klass;
3955 gpointer iter = NULL;
3956 GPtrArray *res_array;
3959 if (type->type->byref) {
3960 return g_ptr_array_new ();
3963 klass = startklass = mono_class_from_mono_type (type->type);
3965 mono_class_setup_methods (klass);
3966 if (mono_class_has_failure (klass)) {
3967 mono_error_init (&error);
3968 mono_error_set_for_class_failure (&error, klass);
3969 mono_error_set_pending_exception (&error);
3973 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3976 while ((method = mono_class_get_methods (klass, &iter))) {
3978 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3980 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3981 if (bflags & BFLAGS_Public)
3984 if (bflags & BFLAGS_NonPublic)
3990 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3991 if (bflags & BFLAGS_Static)
3992 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3995 if (bflags & BFLAGS_Instance)
4001 g_ptr_array_add (res_array, method);
4008 property_hash (gconstpointer data)
4010 MonoProperty *prop = (MonoProperty*)data;
4012 return g_str_hash (prop->name);
4016 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4018 if (method1->slot != -1 && method1->slot == method2->slot)
4021 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4022 if (method1->is_inflated)
4023 method1 = ((MonoMethodInflated*) method1)->declaring;
4024 if (method2->is_inflated)
4025 method2 = ((MonoMethodInflated*) method2)->declaring;
4028 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4032 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4034 // Properties are hide-by-name-and-signature
4035 if (!g_str_equal (prop1->name, prop2->name))
4038 /* If we see a property in a generic method, we want to
4039 compare the generic signatures, not the inflated signatures
4040 because we might conflate two properties that were
4044 public T this[T t] { getter { return t; } } // method 1
4045 public U this[U u] { getter { return u; } } // method 2
4048 If we see int Foo<int,int>::Item[int] we need to know if
4049 the indexer came from method 1 or from method 2, and we
4050 shouldn't conflate them. (Bugzilla 36283)
4052 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4055 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4062 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4067 return method_nonpublic (accessor, start_klass);
4070 ICALL_EXPORT GPtrArray*
4071 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4074 MonoClass *startklass, *klass;
4079 int (*compare_func) (const char *s1, const char *s2) = NULL;
4081 GHashTable *properties = NULL;
4082 GPtrArray *res_array;
4084 if (type->type->byref) {
4085 return g_ptr_array_new ();
4088 mono_error_init (&error);
4090 klass = startklass = mono_class_from_mono_type (type->type);
4092 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4094 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4096 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4098 mono_class_setup_methods (klass);
4099 mono_class_setup_vtable (klass);
4100 if (mono_class_has_failure (klass)) {
4101 mono_error_set_for_class_failure (&error, klass);
4106 while ((prop = mono_class_get_properties (klass, &iter))) {
4112 flags = method->flags;
4115 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4116 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4117 if (bflags & BFLAGS_Public)
4119 } else if (bflags & BFLAGS_NonPublic) {
4120 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4121 property_accessor_nonpublic(prop->set, startklass == klass)) {
4128 if (flags & METHOD_ATTRIBUTE_STATIC) {
4129 if (bflags & BFLAGS_Static)
4130 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4133 if (bflags & BFLAGS_Instance)
4141 if (propname != NULL && compare_func (propname, prop->name))
4144 if (g_hash_table_lookup (properties, prop))
4147 g_ptr_array_add (res_array, prop);
4149 g_hash_table_insert (properties, prop, prop);
4151 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4154 g_hash_table_destroy (properties);
4161 g_hash_table_destroy (properties);
4162 g_ptr_array_free (res_array, TRUE);
4164 mono_error_set_pending_exception (&error);
4170 event_hash (gconstpointer data)
4172 MonoEvent *event = (MonoEvent*)data;
4174 return g_str_hash (event->name);
4178 event_equal (MonoEvent *event1, MonoEvent *event2)
4180 // Events are hide-by-name
4181 return g_str_equal (event1->name, event2->name);
4184 ICALL_EXPORT GPtrArray*
4185 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4188 MonoClass *startklass, *klass;
4193 int (*compare_func) (const char *s1, const char *s2) = NULL;
4194 GHashTable *events = NULL;
4195 GPtrArray *res_array;
4197 if (type->type->byref) {
4198 return g_ptr_array_new ();
4201 mono_error_init (&error);
4203 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4205 res_array = g_ptr_array_sized_new (4);
4207 klass = startklass = mono_class_from_mono_type (type->type);
4209 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4211 mono_class_setup_methods (klass);
4212 mono_class_setup_vtable (klass);
4213 if (mono_class_has_failure (klass)) {
4214 mono_error_set_for_class_failure (&error, klass);
4219 while ((event = mono_class_get_events (klass, &iter))) {
4221 method = event->add;
4223 method = event->remove;
4225 method = event->raise;
4227 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4228 if (bflags & BFLAGS_Public)
4230 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4231 if (bflags & BFLAGS_NonPublic)
4236 if (bflags & BFLAGS_NonPublic)
4242 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4243 if (bflags & BFLAGS_Static)
4244 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4247 if (bflags & BFLAGS_Instance)
4252 if (bflags & BFLAGS_Instance)
4257 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4260 if (g_hash_table_lookup (events, event))
4263 g_ptr_array_add (res_array, event);
4265 g_hash_table_insert (events, event, event);
4267 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4270 g_hash_table_destroy (events);
4276 g_hash_table_destroy (events);
4278 g_ptr_array_free (res_array, TRUE);
4280 mono_error_set_pending_exception (&error);
4284 ICALL_EXPORT GPtrArray *
4285 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4291 GPtrArray *res_array;
4293 if (type->type->byref) {
4294 return g_ptr_array_new ();
4297 klass = mono_class_from_mono_type (type->type);
4300 * If a nested type is generic, return its generic type definition.
4301 * Note that this means that the return value is essentially the set
4302 * of nested types of the generic type definition of @klass.
4304 * A note in MSDN claims that a generic type definition can have
4305 * nested types that aren't generic. In any case, the container of that
4306 * nested type would be the generic type definition.
4308 if (klass->generic_class)
4309 klass = klass->generic_class->container_class;
4311 res_array = g_ptr_array_new ();
4314 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4316 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4317 if (bflags & BFLAGS_Public)
4320 if (bflags & BFLAGS_NonPublic)
4326 if (str != NULL && strcmp (nested->name, str))
4329 g_ptr_array_add (res_array, &nested->byval_arg);
4335 ICALL_EXPORT MonoReflectionType*
4336 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4339 MonoReflectionType *ret;
4341 MonoType *type = NULL;
4342 MonoTypeNameParse info;
4343 gboolean type_resolve;
4345 /* On MS.NET, this does not fire a TypeResolve event */
4346 type_resolve = TRUE;
4347 str = mono_string_to_utf8_checked (name, &error);
4348 if (mono_error_set_pending_exception (&error))
4350 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4351 if (!mono_reflection_parse_type (str, &info)) {
4353 mono_reflection_free_type_info (&info);
4355 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4358 /*g_print ("failed parse\n");*/
4362 if (info.assembly.name) {
4364 mono_reflection_free_type_info (&info);
4366 /* 1.0 and 2.0 throw different exceptions */
4367 if (mono_defaults.generic_ilist_class)
4368 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4370 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4376 if (module != NULL) {
4377 if (module->image) {
4378 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4379 if (!is_ok (&error)) {
4381 mono_reflection_free_type_info (&info);
4382 mono_error_set_pending_exception (&error);
4389 if (assembly_is_dynamic (assembly->assembly)) {
4390 /* Enumerate all modules */
4391 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4395 if (abuilder->modules) {
4396 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4397 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4398 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4399 if (!is_ok (&error)) {
4401 mono_reflection_free_type_info (&info);
4402 mono_error_set_pending_exception (&error);
4410 if (!type && abuilder->loaded_modules) {
4411 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4412 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4413 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4414 if (!is_ok (&error)) {
4416 mono_reflection_free_type_info (&info);
4417 mono_error_set_pending_exception (&error);
4426 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4427 if (!is_ok (&error)) {
4429 mono_reflection_free_type_info (&info);
4430 mono_error_set_pending_exception (&error);
4435 mono_reflection_free_type_info (&info);
4437 MonoException *e = NULL;
4440 e = mono_get_exception_type_load (name, NULL);
4443 mono_set_pending_exception (e);
4447 if (type->type == MONO_TYPE_CLASS) {
4448 MonoClass *klass = mono_type_get_class (type);
4450 /* need to report exceptions ? */
4451 if (throwOnError && mono_class_has_failure (klass)) {
4452 /* report SecurityException (or others) that occured when loading the assembly */
4453 mono_error_set_for_class_failure (&error, klass);
4454 mono_error_set_pending_exception (&error);
4459 /* g_print ("got it\n"); */
4460 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4461 mono_error_set_pending_exception (&error);
4467 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4470 gchar *shadow_ini_file;
4473 /* Check for shadow-copied assembly */
4474 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4475 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4477 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4478 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4484 g_free (shadow_ini_file);
4485 if (content != NULL) {
4488 *filename = content;
4495 ICALL_EXPORT MonoString *
4496 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4498 MonoDomain *domain = mono_object_domain (assembly);
4499 MonoAssembly *mass = assembly->assembly;
4500 MonoString *res = NULL;
4505 if (g_path_is_absolute (mass->image->name)) {
4506 absolute = g_strdup (mass->image->name);
4507 dirname = g_path_get_dirname (absolute);
4509 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4510 dirname = g_strdup (mass->basedir);
4513 replace_shadow_path (domain, dirname, &absolute);
4516 mono_icall_make_platform_path (absolute);
4519 uri = g_filename_to_uri (absolute, NULL, NULL);
4521 const gchar *prepend = mono_icall_get_file_path_prefix (absolute);
4522 uri = g_strconcat (prepend, absolute, NULL);
4526 res = mono_string_new (domain, uri);
4533 ICALL_EXPORT MonoBoolean
4534 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4536 MonoAssembly *mass = assembly->assembly;
4538 return mass->in_gac;
4541 ICALL_EXPORT MonoReflectionAssembly*
4542 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4547 MonoImageOpenStatus status;
4548 MonoReflectionAssembly* result = NULL;
4550 name = mono_string_to_utf8_checked (mname, &error);
4551 if (mono_error_set_pending_exception (&error))
4553 res = mono_assembly_load_with_partial_name (name, &status);
4559 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4561 mono_error_set_pending_exception (&error);
4565 ICALL_EXPORT MonoStringHandle
4566 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4568 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4569 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4570 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4573 ICALL_EXPORT MonoBoolean
4574 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4576 return assembly->assembly->ref_only;
4579 ICALL_EXPORT MonoStringHandle
4580 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4582 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4583 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4585 return mono_string_new_handle (domain, assembly->image->version, error);
4588 ICALL_EXPORT MonoReflectionMethod*
4589 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4592 MonoReflectionMethod *res = NULL;
4595 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4599 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4600 if (!mono_error_ok (&error))
4603 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4606 if (!mono_error_ok (&error))
4607 mono_error_set_pending_exception (&error);
4611 ICALL_EXPORT MonoReflectionModule*
4612 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4615 MonoReflectionModule *result = NULL;
4616 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4617 if (!mono_error_ok (&error))
4618 mono_error_set_pending_exception (&error);
4622 ICALL_EXPORT MonoArray*
4623 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4626 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4627 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4628 if (mono_error_set_pending_exception (&error))
4633 for (i = 0; i < table->rows; ++i) {
4634 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4635 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4640 ICALL_EXPORT MonoStringHandle
4641 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4644 guint8 aotid_sum = 0;
4645 MonoDomain* domain = mono_domain_get ();
4647 if (!domain->entry_assembly || !domain->entry_assembly->image)
4650 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4652 for (i = 0; i < 16; ++i)
4653 aotid_sum |= (*aotid)[i];
4658 gchar *guid = mono_guid_to_string((guint8*) aotid);
4659 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4665 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4667 static MonoMethod *create_version = NULL;
4671 mono_error_init (error);
4674 if (!create_version) {
4675 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4676 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4677 g_assert (create_version);
4678 mono_method_desc_free (desc);
4684 args [3] = &revision;
4685 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4686 return_val_if_nok (error, NULL);
4688 mono_runtime_invoke_checked (create_version, result, args, error);
4689 return_val_if_nok (error, NULL);
4694 ICALL_EXPORT MonoArray*
4695 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4699 MonoDomain *domain = mono_object_domain (assembly);
4701 static MonoMethod *create_culture = NULL;
4702 MonoImage *image = assembly->assembly->image;
4706 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4709 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4710 if (mono_error_set_pending_exception (&error))
4714 if (count > 0 && !create_culture) {
4715 MonoMethodDesc *desc = mono_method_desc_new (
4716 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4717 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4718 g_assert (create_culture);
4719 mono_method_desc_free (desc);
4722 for (i = 0; i < count; i++) {
4723 MonoObject *version;
4724 MonoReflectionAssemblyName *aname;
4725 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4727 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4729 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4730 domain, mono_class_get_assembly_name_class (), &error);
4731 if (mono_error_set_pending_exception (&error))
4734 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4736 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4737 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4738 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4739 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4740 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4741 aname->versioncompat = 1; /* SameMachine (default) */
4742 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4744 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4745 if (mono_error_set_pending_exception (&error))
4748 MONO_OBJECT_SETREF (aname, version, version);
4750 if (create_culture) {
4752 MonoBoolean assembly_ref = 1;
4753 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4754 args [1] = &assembly_ref;
4756 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4757 if (mono_error_set_pending_exception (&error))
4760 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4763 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4764 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4765 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4767 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4768 /* public key token isn't copied - the class library will
4769 automatically generate it from the public key if required */
4770 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4771 if (mono_error_set_pending_exception (&error))
4774 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4775 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4777 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4778 if (mono_error_set_pending_exception (&error))
4781 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4782 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4785 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4786 if (mono_error_set_pending_exception (&error))
4789 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4792 /* note: this function doesn't return the codebase on purpose (i.e. it can
4793 be used under partial trust as path information isn't present). */
4795 mono_array_setref (result, i, aname);
4800 /* move this in some file in mono/util/ */
4802 g_concat_dir_and_file (const char *dir, const char *file)
4804 g_return_val_if_fail (dir != NULL, NULL);
4805 g_return_val_if_fail (file != NULL, NULL);
4808 * If the directory name doesn't have a / on the end, we need
4809 * to add one so we get a proper path to the file
4811 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4812 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4814 return g_strconcat (dir, file, NULL);
4818 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4821 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4823 guint32 cols [MONO_MANIFEST_SIZE];
4824 guint32 impl, file_idx;
4828 char *n = mono_string_to_utf8_checked (name, &error);
4829 if (mono_error_set_pending_exception (&error))
4832 for (i = 0; i < table->rows; ++i) {
4833 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4834 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4835 if (strcmp (val, n) == 0)
4839 if (i == table->rows)
4842 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4845 * this code should only be called after obtaining the
4846 * ResourceInfo and handling the other cases.
4848 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4849 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4851 module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
4852 if (mono_error_set_pending_exception (&error) || !module)
4856 module = assembly->assembly->image;
4859 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4860 if (mono_error_set_pending_exception (&error))
4862 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4864 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4867 ICALL_EXPORT gboolean
4868 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4871 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4873 guint32 cols [MONO_MANIFEST_SIZE];
4874 guint32 file_cols [MONO_FILE_SIZE];
4878 n = mono_string_to_utf8_checked (name, &error);
4879 if (mono_error_set_pending_exception (&error))
4881 for (i = 0; i < table->rows; ++i) {
4882 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4883 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4884 if (strcmp (val, n) == 0)
4888 if (i == table->rows)
4891 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4892 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4895 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4896 case MONO_IMPLEMENTATION_FILE:
4897 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4898 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4899 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4900 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4901 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4902 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4905 info->location = RESOURCE_LOCATION_EMBEDDED;
4908 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4909 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4910 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4911 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4912 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4913 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4915 mono_set_pending_exception (ex);
4918 MonoReflectionAssembly *assm_obj;
4919 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4921 mono_error_set_pending_exception (&error);
4924 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4926 /* Obtain info recursively */
4927 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4928 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4931 case MONO_IMPLEMENTATION_EXP_TYPE:
4932 g_assert_not_reached ();
4940 ICALL_EXPORT MonoObject*
4941 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4944 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4945 MonoArray *result = NULL;
4950 /* check hash if needed */
4952 n = mono_string_to_utf8_checked (name, &error);
4953 if (mono_error_set_pending_exception (&error))
4956 for (i = 0; i < table->rows; ++i) {
4957 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4958 if (strcmp (val, n) == 0) {
4961 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4962 fn = mono_string_new (mono_object_domain (assembly), n);
4964 return (MonoObject*)fn;
4972 for (i = 0; i < table->rows; ++i) {
4973 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4977 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4978 if (mono_error_set_pending_exception (&error))
4983 for (i = 0; i < table->rows; ++i) {
4984 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4985 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4986 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4987 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4992 return (MonoObject*)result;
4995 ICALL_EXPORT MonoArray*
4996 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4999 MonoDomain *domain = mono_domain_get();
5002 int i, j, file_count = 0;
5003 MonoImage **modules;
5004 guint32 module_count, real_module_count;
5005 MonoTableInfo *table;
5006 guint32 cols [MONO_FILE_SIZE];
5007 MonoImage *image = assembly->assembly->image;
5009 g_assert (image != NULL);
5010 g_assert (!assembly_is_dynamic (assembly->assembly));
5012 table = &image->tables [MONO_TABLE_FILE];
5013 file_count = table->rows;
5015 modules = image->modules;
5016 module_count = image->module_count;
5018 real_module_count = 0;
5019 for (i = 0; i < module_count; ++i)
5021 real_module_count ++;
5023 klass = mono_class_get_module_class ();
5024 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5025 if (mono_error_set_pending_exception (&error))
5028 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5029 if (mono_error_set_pending_exception (&error))
5032 mono_array_setref (res, 0, image_obj);
5034 for (i = 0; i < module_count; ++i)
5036 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5037 if (mono_error_set_pending_exception (&error))
5039 mono_array_setref (res, j, rm);
5043 for (i = 0; i < file_count; ++i, ++j) {
5044 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5045 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5046 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5047 if (mono_error_set_pending_exception (&error))
5049 mono_array_setref (res, j, rm);
5052 MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
5053 if (mono_error_set_pending_exception (&error))
5056 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5057 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5060 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5061 if (mono_error_set_pending_exception (&error))
5063 mono_array_setref (res, j, rm);
5070 ICALL_EXPORT MonoReflectionMethod*
5071 ves_icall_GetCurrentMethod (void)
5073 MonoReflectionMethod *res = NULL;
5076 MonoMethod *m = mono_method_get_last_managed ();
5079 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5083 while (m->is_inflated)
5084 m = ((MonoMethodInflated*)m)->declaring;
5086 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5087 mono_error_set_pending_exception (&error);
5093 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5096 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5099 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5100 //method is inflated, we should inflate it on the other class
5101 MonoGenericContext ctx;
5102 ctx.method_inst = inflated->context.method_inst;
5103 ctx.class_inst = inflated->context.class_inst;
5104 if (klass->generic_class)
5105 ctx.class_inst = klass->generic_class->context.class_inst;
5106 else if (klass->generic_container)
5107 ctx.class_inst = klass->generic_container->context.class_inst;
5108 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5109 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5113 mono_class_setup_methods (method->klass);
5114 if (mono_class_has_failure (method->klass))
5116 for (i = 0; i < method->klass->method.count; ++i) {
5117 if (method->klass->methods [i] == method) {
5122 mono_class_setup_methods (klass);
5123 if (mono_class_has_failure (klass))
5125 g_assert (offset >= 0 && offset < klass->method.count);
5126 return klass->methods [offset];
5129 ICALL_EXPORT MonoReflectionMethod*
5130 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5132 MonoReflectionMethod *res = NULL;
5135 if (type && generic_check) {
5136 klass = mono_class_from_mono_type (type);
5137 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5140 if (method->klass != klass) {
5141 method = mono_method_get_equivalent_method (method, klass);
5146 klass = mono_class_from_mono_type (type);
5148 klass = method->klass;
5149 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5150 mono_error_set_pending_exception (&error);
5154 ICALL_EXPORT MonoReflectionMethodBody*
5155 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5158 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5159 mono_error_set_pending_exception (&error);
5163 ICALL_EXPORT MonoReflectionAssembly*
5164 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5167 MonoReflectionAssembly *result;
5168 MonoMethod *dest = NULL;
5170 mono_stack_walk_no_il (get_executing, &dest);
5172 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5174 mono_error_set_pending_exception (&error);
5179 ICALL_EXPORT MonoReflectionAssembly*
5180 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5183 MonoReflectionAssembly *result;
5184 MonoDomain* domain = mono_domain_get ();
5186 if (!domain->entry_assembly)
5189 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5191 mono_error_set_pending_exception (&error);
5195 ICALL_EXPORT MonoReflectionAssembly*
5196 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5201 MonoReflectionAssembly *result;
5204 mono_stack_walk_no_il (get_executing, &dest);
5206 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5210 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5213 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5215 mono_error_set_pending_exception (&error);
5219 ICALL_EXPORT MonoStringHandle
5220 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5221 gboolean assembly_qualified, MonoError *error)
5223 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5224 MonoType *type = MONO_HANDLE_RAW (object)->type;
5225 MonoTypeNameFormat format;
5226 MonoStringHandle res;
5230 format = assembly_qualified ?
5231 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5232 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5234 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5236 name = mono_type_get_name_full (type, format);
5238 return NULL_HANDLE_STRING;
5240 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5242 return NULL_HANDLE_STRING;
5245 res = mono_string_new_handle (domain, name, error);
5252 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5255 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5257 mono_class_init_checked (klass, &error);
5258 mono_error_set_pending_exception (&error);
5259 return mono_security_core_clr_class_level (klass);
5263 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5265 MonoClassField *field = rfield->field;
5266 return mono_security_core_clr_field_level (field, TRUE);
5270 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5272 MonoMethod *method = rfield->method;
5273 return mono_security_core_clr_method_level (method, TRUE);
5277 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)
5279 static MonoMethod *create_culture = NULL;
5283 const char *pkey_ptr;
5285 MonoBoolean assembly_ref = 0;
5287 mono_error_init (error);
5289 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5290 aname->major = name->major;
5291 aname->minor = name->minor;
5292 aname->build = name->build;
5293 aname->flags = name->flags;
5294 aname->revision = name->revision;
5295 aname->hashalg = name->hash_alg;
5296 aname->versioncompat = 1; /* SameMachine (default) */
5297 aname->processor_architecture = name->arch;
5299 if (by_default_version) {
5300 MonoObject *version;
5302 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5303 return_if_nok (error);
5305 MONO_OBJECT_SETREF (aname, version, version);
5309 if (absolute != NULL && *absolute != '\0') {
5312 codebase = g_strdup (absolute);
5314 mono_icall_make_platform_path (codebase);
5316 const gchar *prepend = mono_icall_get_file_path_prefix (codebase);
5318 result = g_strconcat (prepend, codebase, NULL);
5324 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5328 if (!create_culture) {
5329 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5330 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5331 g_assert (create_culture);
5332 mono_method_desc_free (desc);
5335 if (name->culture) {
5336 args [0] = mono_string_new (domain, name->culture);
5337 args [1] = &assembly_ref;
5339 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5340 return_if_nok (error);
5342 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5345 if (name->public_key) {
5346 pkey_ptr = (char*)name->public_key;
5347 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5349 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5350 return_if_nok (error);
5351 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5352 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5353 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5354 } else if (default_publickey) {
5355 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5356 return_if_nok (error);
5357 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5358 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5361 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5362 if (name->public_key_token [0]) {
5366 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5367 return_if_nok (error);
5369 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5370 p = mono_array_addr (keyToken, char, 0);
5372 for (i = 0, j = 0; i < 8; i++) {
5373 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5374 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5377 } else if (default_token) {
5378 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5379 return_if_nok (error);
5380 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5384 ICALL_EXPORT MonoString *
5385 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5387 MonoDomain *domain = mono_object_domain (assembly);
5388 MonoAssembly *mass = assembly->assembly;
5392 name = mono_stringify_assembly_name (&mass->aname);
5393 res = mono_string_new (domain, name);
5399 ICALL_EXPORT MonoAssemblyName *
5400 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5402 return &mass->aname;
5406 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5410 MonoImageOpenStatus status = MONO_IMAGE_OK;
5413 MonoAssemblyName name;
5416 filename = mono_string_to_utf8_checked (fname, &error);
5417 if (mono_error_set_pending_exception (&error))
5420 dirname = g_path_get_dirname (filename);
5421 replace_shadow_path (mono_domain_get (), dirname, &filename);
5424 image = mono_image_open (filename, &status);
5430 if (status == MONO_IMAGE_IMAGE_INVALID)
5431 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5433 exc = mono_get_exception_file_not_found2 (NULL, fname);
5434 mono_set_pending_exception (exc);
5438 res = mono_assembly_fill_assembly_name (image, &name);
5440 mono_image_close (image);
5442 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5446 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5447 mono_error_set_pending_exception (&error);
5449 mono_image_close (image);
5453 ICALL_EXPORT MonoBoolean
5454 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5455 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5457 MonoBoolean result = FALSE;
5458 MonoDeclSecurityEntry entry;
5460 /* SecurityAction.RequestMinimum */
5461 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5462 *minimum = entry.blob;
5463 *minLength = entry.size;
5466 /* SecurityAction.RequestOptional */
5467 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5468 *optional = entry.blob;
5469 *optLength = entry.size;
5472 /* SecurityAction.RequestRefuse */
5473 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5474 *refused = entry.blob;
5475 *refLength = entry.size;
5483 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5485 guint32 attrs, visibility;
5487 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5488 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5489 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5492 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5498 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5500 MonoReflectionType *rt;
5503 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5506 mono_error_init (error);
5508 /* we start the count from 1 because we skip the special type <Module> */
5511 for (i = 1; i < tdef->rows; ++i) {
5512 if (mono_module_type_is_visible (tdef, image, i + 1))
5516 count = tdef->rows - 1;
5518 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5519 return_val_if_nok (error, NULL);
5520 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5521 return_val_if_nok (error, NULL);
5523 for (i = 1; i < tdef->rows; ++i) {
5524 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5525 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5528 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5529 return_val_if_nok (error, NULL);
5531 mono_array_setref (res, count, rt);
5533 MonoException *ex = mono_error_convert_to_exception (error);
5534 mono_array_setref (*exceptions, count, ex);
5543 ICALL_EXPORT MonoArray*
5544 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5547 MonoArray *res = NULL;
5548 MonoArray *exceptions = NULL;
5549 MonoImage *image = NULL;
5550 MonoTableInfo *table = NULL;
5553 int i, len, ex_count;
5555 domain = mono_object_domain (assembly);
5557 g_assert (!assembly_is_dynamic (assembly->assembly));
5558 image = assembly->assembly->image;
5559 table = &image->tables [MONO_TABLE_FILE];
5560 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5561 if (mono_error_set_pending_exception (&error))
5564 /* Append data from all modules in the assembly */
5565 for (i = 0; i < table->rows; ++i) {
5566 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5567 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5568 if (mono_error_set_pending_exception (&error))
5574 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5575 if (mono_error_set_pending_exception (&error))
5579 /* Append the new types to the end of the array */
5580 if (mono_array_length (res2) > 0) {
5582 MonoArray *res3, *ex3;
5584 len1 = mono_array_length (res);
5585 len2 = mono_array_length (res2);
5587 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5588 if (mono_error_set_pending_exception (&error))
5590 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5591 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5594 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5595 if (mono_error_set_pending_exception (&error))
5597 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5598 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5605 /* the ReflectionTypeLoadException must have all the types (Types property),
5606 * NULL replacing types which throws an exception. The LoaderException must
5607 * contain all exceptions for NULL items.
5610 len = mono_array_length (res);
5613 for (i = 0; i < len; i++) {
5614 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5618 klass = mono_type_get_class (t->type);
5619 if ((klass != NULL) && mono_class_has_failure (klass)) {
5620 /* keep the class in the list */
5621 list = g_list_append (list, klass);
5622 /* and replace Type with NULL */
5623 mono_array_setref (res, i, NULL);
5630 if (list || ex_count) {
5632 MonoException *exc = NULL;
5633 MonoArray *exl = NULL;
5634 int j, length = g_list_length (list) + ex_count;
5636 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5637 if (mono_error_set_pending_exception (&error)) {
5641 /* Types for which mono_class_get_checked () succeeded */
5642 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5643 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5644 mono_array_setref (exl, i, exc);
5646 /* Types for which it don't */
5647 for (j = 0; j < mono_array_length (exceptions); ++j) {
5648 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5650 g_assert (i < length);
5651 mono_array_setref (exl, i, exc);
5658 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5659 if (!is_ok (&error)) {
5660 mono_error_set_pending_exception (&error);
5663 mono_set_pending_exception (exc);
5671 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5673 mono_assembly_name_free (aname);
5676 ICALL_EXPORT gboolean
5677 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5679 *is_version_definited = *is_token_defined = FALSE;
5681 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5684 ICALL_EXPORT MonoReflectionType*
5685 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5688 MonoReflectionType *ret;
5689 MonoDomain *domain = mono_object_domain (module);
5692 g_assert (module->image);
5694 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5695 /* These images do not have a global type */
5698 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5699 if (!mono_error_ok (&error)) {
5700 mono_error_set_pending_exception (&error);
5704 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5705 if (!mono_error_ok (&error)) {
5706 mono_error_set_pending_exception (&error);
5714 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5716 /*if (module->image)
5717 mono_image_close (module->image);*/
5720 ICALL_EXPORT MonoStringHandle
5721 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5723 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5724 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5727 return mono_string_new_handle (domain, image->guid, error);
5731 static inline gpointer
5732 mono_icall_module_get_hinstance (MonoReflectionModule *module)
5734 return (gpointer) (-1);
5736 #endif /* HOST_WIN32 */
5738 ICALL_EXPORT gpointer
5739 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5741 return mono_icall_module_get_hinstance (module);
5745 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5747 if (image_is_dynamic (image)) {
5748 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5749 *pe_kind = dyn->pe_kind;
5750 *machine = dyn->machine;
5753 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5754 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5759 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5761 return (image->md_version_major << 16) | (image->md_version_minor);
5764 ICALL_EXPORT MonoArray*
5765 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5768 MonoArray *exceptions;
5771 if (!module->image) {
5772 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5773 mono_error_set_pending_exception (&error);
5778 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5779 if (mono_error_set_pending_exception (&error))
5782 for (i = 0; i < mono_array_length (exceptions); ++i) {
5783 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5785 mono_set_pending_exception (ex);
5794 mono_memberref_is_method (MonoImage *image, guint32 token)
5796 if (!image_is_dynamic (image)) {
5797 guint32 cols [MONO_MEMBERREF_SIZE];
5799 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5800 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5801 mono_metadata_decode_blob_size (sig, &sig);
5802 return (*sig != 0x6);
5805 MonoClass *handle_class;
5807 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5808 mono_error_cleanup (&error); /* just probing, ignore error */
5812 return mono_defaults.methodhandle_class == handle_class;
5817 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5820 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5821 mono_array_addr (type_args, MonoType*, 0));
5823 context->class_inst = NULL;
5825 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5826 mono_array_addr (method_args, MonoType*, 0));
5828 context->method_inst = NULL;
5831 ICALL_EXPORT MonoType*
5832 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5835 int table = mono_metadata_token_table (token);
5836 int index = mono_metadata_token_index (token);
5837 MonoGenericContext context;
5840 *resolve_error = ResolveTokenError_Other;
5842 /* Validate token */
5843 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5844 (table != MONO_TABLE_TYPESPEC)) {
5845 *resolve_error = ResolveTokenError_BadTable;
5849 if (image_is_dynamic (image)) {
5850 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5851 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5852 mono_error_cleanup (&error);
5853 return klass ? &klass->byval_arg : NULL;
5856 init_generic_context_from_args (&context, type_args, method_args);
5857 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5858 mono_error_cleanup (&error);
5859 return klass ? &klass->byval_arg : NULL;
5862 if ((index <= 0) || (index > image->tables [table].rows)) {
5863 *resolve_error = ResolveTokenError_OutOfRange;
5867 init_generic_context_from_args (&context, type_args, method_args);
5868 klass = mono_class_get_checked (image, token, &error);
5870 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5871 if (!mono_error_ok (&error)) {
5872 mono_error_set_pending_exception (&error);
5877 return &klass->byval_arg;
5882 ICALL_EXPORT MonoMethod*
5883 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5886 int table = mono_metadata_token_table (token);
5887 int index = mono_metadata_token_index (token);
5888 MonoGenericContext context;
5891 *resolve_error = ResolveTokenError_Other;
5893 /* Validate token */
5894 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5895 (table != MONO_TABLE_MEMBERREF)) {
5896 *resolve_error = ResolveTokenError_BadTable;
5900 if (image_is_dynamic (image)) {
5901 if (table == MONO_TABLE_METHOD) {
5902 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5903 mono_error_cleanup (&error);
5907 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5908 *resolve_error = ResolveTokenError_BadTable;
5912 init_generic_context_from_args (&context, type_args, method_args);
5913 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5914 mono_error_cleanup (&error);
5918 if ((index <= 0) || (index > image->tables [table].rows)) {
5919 *resolve_error = ResolveTokenError_OutOfRange;
5922 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5923 *resolve_error = ResolveTokenError_BadTable;
5927 init_generic_context_from_args (&context, type_args, method_args);
5928 method = mono_get_method_checked (image, token, NULL, &context, &error);
5929 mono_error_set_pending_exception (&error);
5934 ICALL_EXPORT MonoString*
5935 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5938 int index = mono_metadata_token_index (token);
5940 *resolve_error = ResolveTokenError_Other;
5942 /* Validate token */
5943 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5944 *resolve_error = ResolveTokenError_BadTable;
5948 if (image_is_dynamic (image)) {
5949 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5950 mono_error_cleanup (&error);
5954 if ((index <= 0) || (index >= image->heap_us.size)) {
5955 *resolve_error = ResolveTokenError_OutOfRange;
5959 /* FIXME: What to do if the index points into the middle of a string ? */
5961 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5962 mono_error_set_pending_exception (&error);
5966 ICALL_EXPORT MonoClassField*
5967 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5971 int table = mono_metadata_token_table (token);
5972 int index = mono_metadata_token_index (token);
5973 MonoGenericContext context;
5974 MonoClassField *field;
5976 *resolve_error = ResolveTokenError_Other;
5978 /* Validate token */
5979 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5980 *resolve_error = ResolveTokenError_BadTable;
5984 if (image_is_dynamic (image)) {
5985 if (table == MONO_TABLE_FIELD) {
5986 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5987 mono_error_cleanup (&error);
5991 if (mono_memberref_is_method (image, token)) {
5992 *resolve_error = ResolveTokenError_BadTable;
5996 init_generic_context_from_args (&context, type_args, method_args);
5997 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5998 mono_error_cleanup (&error);
6002 if ((index <= 0) || (index > image->tables [table].rows)) {
6003 *resolve_error = ResolveTokenError_OutOfRange;
6006 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6007 *resolve_error = ResolveTokenError_BadTable;
6011 init_generic_context_from_args (&context, type_args, method_args);
6012 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6013 mono_error_set_pending_exception (&error);
6019 ICALL_EXPORT MonoObject*
6020 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6024 int table = mono_metadata_token_table (token);
6026 *error = ResolveTokenError_Other;
6029 case MONO_TABLE_TYPEDEF:
6030 case MONO_TABLE_TYPEREF:
6031 case MONO_TABLE_TYPESPEC: {
6032 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6034 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6035 mono_error_set_pending_exception (&merror);
6042 case MONO_TABLE_METHOD:
6043 case MONO_TABLE_METHODSPEC: {
6044 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6046 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6047 mono_error_set_pending_exception (&merror);
6053 case MONO_TABLE_FIELD: {
6054 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6056 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6057 mono_error_set_pending_exception (&merror);
6063 case MONO_TABLE_MEMBERREF:
6064 if (mono_memberref_is_method (image, token)) {
6065 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6067 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6068 mono_error_set_pending_exception (&merror);
6075 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6077 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6078 mono_error_set_pending_exception (&merror);
6087 *error = ResolveTokenError_BadTable;
6093 ICALL_EXPORT MonoArray*
6094 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6097 int table = mono_metadata_token_table (token);
6098 int idx = mono_metadata_token_index (token);
6099 MonoTableInfo *tables = image->tables;
6104 *resolve_error = ResolveTokenError_OutOfRange;
6106 /* FIXME: Support other tables ? */
6107 if (table != MONO_TABLE_STANDALONESIG)
6110 if (image_is_dynamic (image))
6113 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6116 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6118 ptr = mono_metadata_blob_heap (image, sig);
6119 len = mono_metadata_decode_blob_size (ptr, &ptr);
6121 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6122 if (mono_error_set_pending_exception (&error))
6124 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6128 ICALL_EXPORT MonoBoolean
6129 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6135 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6141 check_for_invalid_type (MonoClass *klass, MonoError *error)
6145 mono_error_init (error);
6147 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6150 name = mono_type_get_full_name (klass);
6151 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6153 ICALL_EXPORT MonoReflectionType *
6154 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6157 MonoReflectionType *ret;
6158 MonoClass *klass, *aklass;
6160 klass = mono_class_from_mono_type (type->type);
6161 check_for_invalid_type (klass, &error);
6162 if (mono_error_set_pending_exception (&error))
6165 if (rank == 0) //single dimentional array
6166 aklass = mono_array_class_get (klass, 1);
6168 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6170 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6171 mono_error_set_pending_exception (&error);
6176 ICALL_EXPORT MonoReflectionType *
6177 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6180 MonoReflectionType *ret;
6183 klass = mono_class_from_mono_type (type->type);
6184 mono_class_init_checked (klass, &error);
6185 if (mono_error_set_pending_exception (&error))
6188 check_for_invalid_type (klass, &error);
6189 if (mono_error_set_pending_exception (&error))
6192 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6193 mono_error_set_pending_exception (&error);
6198 ICALL_EXPORT MonoReflectionType *
6199 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6202 MonoReflectionType *ret;
6203 MonoClass *klass, *pklass;
6205 klass = mono_class_from_mono_type (type->type);
6206 mono_class_init_checked (klass, &error);
6207 if (mono_error_set_pending_exception (&error))
6209 check_for_invalid_type (klass, &error);
6210 if (mono_error_set_pending_exception (&error))
6213 pklass = mono_ptr_class_get (type->type);
6215 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6216 mono_error_set_pending_exception (&error);
6221 ICALL_EXPORT MonoObject *
6222 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6223 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6226 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6227 MonoObject *delegate;
6229 MonoMethod *method = info->method;
6230 MonoMethodSignature *sig = mono_method_signature(method);
6232 mono_class_init_checked (delegate_class, &error);
6233 if (mono_error_set_pending_exception (&error))
6236 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6237 /* FIXME improve this exception message */
6238 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6240 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6241 mono_error_set_pending_exception (&error);
6245 if (mono_security_core_clr_enabled ()) {
6246 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6247 if (throwOnBindFailure)
6248 mono_error_set_pending_exception (&error);
6250 mono_error_cleanup (&error);
6255 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6256 if (!method->is_inflated) {
6257 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"));
6262 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6263 if (mono_error_set_pending_exception (&error))
6266 if (method_is_dynamic (method)) {
6267 /* Creating a trampoline would leak memory */
6268 func = mono_compile_method_checked (method, &error);
6269 if (mono_error_set_pending_exception (&error))
6272 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6273 method = mono_object_get_virtual_method (target, method);
6274 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6275 if (mono_error_set_pending_exception (&error))
6277 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6280 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6281 if (mono_error_set_pending_exception (&error))
6286 ICALL_EXPORT MonoMulticastDelegate *
6287 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6290 MonoMulticastDelegate *ret;
6292 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6294 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6295 if (mono_error_set_pending_exception (&error))
6298 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6303 ICALL_EXPORT MonoReflectionMethod*
6304 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6306 MonoReflectionMethod *ret = NULL;
6308 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6309 mono_error_set_pending_exception (&error);
6315 static inline gint32
6316 mono_array_get_byte_length (MonoArray *array)
6322 klass = array->obj.vtable->klass;
6324 if (array->bounds == NULL)
6325 length = array->max_length;
6328 for (i = 0; i < klass->rank; ++ i)
6329 length *= array->bounds [i].length;
6332 switch (klass->element_class->byval_arg.type) {
6335 case MONO_TYPE_BOOLEAN:
6339 case MONO_TYPE_CHAR:
6347 return length * sizeof (gpointer);
6358 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6360 return mono_array_get_byte_length (array);
6364 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6366 return mono_array_get (array, gint8, idx);
6370 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6372 mono_array_set (array, gint8, idx, value);
6375 ICALL_EXPORT MonoBoolean
6376 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6378 guint8 *src_buf, *dest_buf;
6381 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6385 g_assert (count >= 0);
6387 /* This is called directly from the class libraries without going through the managed wrapper */
6388 MONO_CHECK_ARG_NULL (src, FALSE);
6389 MONO_CHECK_ARG_NULL (dest, FALSE);
6391 /* watch out for integer overflow */
6392 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6395 src_buf = (guint8 *)src->vector + src_offset;
6396 dest_buf = (guint8 *)dest->vector + dest_offset;
6399 memcpy (dest_buf, src_buf, count);
6401 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6406 #ifndef DISABLE_REMOTING
6407 ICALL_EXPORT MonoObject *
6408 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6411 MonoDomain *domain = mono_object_domain (this_obj);
6413 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6414 MonoTransparentProxy *tp;
6418 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6419 if (mono_error_set_pending_exception (&error))
6422 tp = (MonoTransparentProxy*) res;
6424 MONO_OBJECT_SETREF (tp, rp, rp);
6425 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6426 klass = mono_class_from_mono_type (type);
6428 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6429 mono_class_setup_vtable (klass);
6430 if (mono_class_has_failure (klass)) {
6431 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6435 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6436 if (mono_error_set_pending_exception (&error))
6438 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6439 if (mono_error_set_pending_exception (&error))
6442 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6443 if (mono_error_set_pending_exception (&error))
6448 ICALL_EXPORT MonoReflectionType *
6449 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6452 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6453 mono_error_set_pending_exception (&error);
6459 /* System.Environment */
6462 ves_icall_System_Environment_get_UserName (void)
6464 /* using glib is more portable */
6465 return mono_string_new (mono_domain_get (), g_get_user_name ());
6470 mono_icall_get_machine_name (void)
6472 #if !defined(DISABLE_SOCKETS)
6476 #if defined _SC_HOST_NAME_MAX
6477 n = sysconf (_SC_HOST_NAME_MAX);
6481 buf = g_malloc (n+1);
6483 if (gethostname (buf, n) == 0){
6485 result = mono_string_new (mono_domain_get (), buf);
6492 return mono_string_new (mono_domain_get (), "mono");
6495 #endif /* !HOST_WIN32 */
6497 ICALL_EXPORT MonoString *
6498 ves_icall_System_Environment_get_MachineName (void)
6500 return mono_icall_get_machine_name ();
6505 mono_icall_get_platform (void)
6507 #if defined(__MACH__)
6510 // Notice that the value is hidden from user code, and only exposed
6511 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6512 // define and making assumptions based on Unix/128/4 values before there
6513 // was a MacOS define. Lots of code would assume that not-Unix meant
6514 // Windows, but in this case, it would be OSX.
6522 #endif /* !HOST_WIN32 */
6525 ves_icall_System_Environment_get_Platform (void)
6527 return mono_icall_get_platform ();
6531 static inline MonoString *
6532 mono_icall_get_new_line (void)
6534 return mono_string_new (mono_domain_get (), "\n");
6536 #endif /* !HOST_WIN32 */
6538 ICALL_EXPORT MonoString *
6539 ves_icall_System_Environment_get_NewLine (void)
6541 return mono_icall_get_new_line ();
6545 static inline MonoBoolean
6546 mono_icall_is_64bit_os (void)
6548 #if SIZEOF_VOID_P == 8
6551 #if defined(HAVE_SYS_UTSNAME_H)
6552 struct utsname name;
6554 if (uname (&name) >= 0) {
6555 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6561 #endif /* !HOST_WIN32 */
6563 ICALL_EXPORT MonoBoolean
6564 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6566 return mono_icall_is_64bit_os ();
6569 ICALL_EXPORT MonoStringHandle
6570 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6574 if (utf8_name == NULL)
6575 return NULL_HANDLE_STRING;
6577 value = g_getenv (utf8_name);
6580 return NULL_HANDLE_STRING;
6582 return mono_string_new_handle (mono_domain_get (), value, error);
6586 * There is no standard way to get at environ.
6589 #ifndef __MINGW32_VERSION
6590 #if defined(__APPLE__)
6591 #if defined (TARGET_OSX)
6592 /* Apple defines this in crt_externs.h but doesn't provide that header for
6593 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6594 * in fact exist on all implementations (so far)
6596 gchar ***_NSGetEnviron(void);
6597 #define environ (*_NSGetEnviron())
6599 static char *mono_environ[1] = { NULL };
6600 #define environ mono_environ
6601 #endif /* defined (TARGET_OSX) */
6609 ICALL_EXPORT MonoArray *
6610 ves_icall_System_Environment_GetCoomandLineArgs (void)
6613 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6614 mono_error_set_pending_exception (&error);
6620 mono_icall_get_environment_variable_names (void)
6630 for (e = environ; *e != 0; ++ e)
6633 domain = mono_domain_get ();
6634 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6635 if (mono_error_set_pending_exception (&error))
6639 for (e = environ; *e != 0; ++ e) {
6640 parts = g_strsplit (*e, "=", 2);
6642 str = mono_string_new (domain, *parts);
6643 mono_array_setref (names, n, str);
6653 #endif /* !HOST_WIN32 */
6655 ICALL_EXPORT MonoArray *
6656 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6658 return mono_icall_get_environment_variable_names ();
6663 mono_icall_set_environment_variable (MonoString *name, MonoString *value)
6665 gchar *utf8_name, *utf8_value;
6668 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6669 if (mono_error_set_pending_exception (&error))
6672 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6673 g_unsetenv (utf8_name);
6678 utf8_value = mono_string_to_utf8_checked (value, &error);
6679 if (!mono_error_ok (&error)) {
6681 mono_error_set_pending_exception (&error);
6684 g_setenv (utf8_name, utf8_value, TRUE);
6687 g_free (utf8_value);
6689 #endif /* !HOST_WIN32 */
6692 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6694 mono_icall_set_environment_variable (name, value);
6698 ves_icall_System_Environment_Exit (int result)
6700 mono_environment_exitcode_set (result);
6702 /* FIXME: There are some cleanup hangs that should be worked out, but
6703 * if the program is going to exit, everything will be cleaned up when
6704 * NaCl exits anyway.
6706 #ifndef __native_client__
6707 if (!mono_runtime_try_shutdown ())
6708 mono_thread_exit ();
6710 /* Suspend all managed threads since the runtime is going away */
6711 mono_thread_suspend_all_other_threads ();
6713 mono_runtime_quit ();
6716 /* we may need to do some cleanup here... */
6720 ICALL_EXPORT MonoStringHandle
6721 ves_icall_System_Environment_GetGacPath (MonoError *error)
6723 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6727 static inline MonoString *
6728 mono_icall_get_windows_folder_path (int folder)
6730 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6731 return mono_string_new (mono_domain_get (), "");
6733 #endif /* !HOST_WIN32 */
6735 ICALL_EXPORT MonoString*
6736 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6738 return mono_icall_get_windows_folder_path (folder);
6741 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
6743 mono_icall_get_logical_drives (void)
6746 gunichar2 buf [256], *ptr, *dname;
6748 guint initial_size = 127, size = 128;
6751 MonoString *drivestr;
6752 MonoDomain *domain = mono_domain_get ();
6758 while (size > initial_size) {
6759 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6760 if (size > initial_size) {
6763 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6764 initial_size = size;
6778 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6779 if (mono_error_set_pending_exception (&error))
6786 while (*u16) { u16++; len ++; }
6787 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6788 if (mono_error_set_pending_exception (&error))
6791 mono_array_setref (result, ndrives++, drivestr);
6801 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
6803 ICALL_EXPORT MonoArray *
6804 ves_icall_System_Environment_GetLogicalDrives (void)
6806 return mono_icall_get_logical_drives ();
6809 ICALL_EXPORT MonoString *
6810 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6813 gunichar2 volume_name [MAX_PATH + 1];
6815 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6817 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6818 mono_error_set_pending_exception (&error);
6822 ICALL_EXPORT MonoStringHandle
6823 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6825 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6828 static const char *encodings [] = {
6830 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6831 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6832 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6834 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6835 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6836 "x_unicode_2_0_utf_7",
6838 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6839 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6841 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6844 "unicodefffe", "utf_16be",
6851 * Returns the internal codepage, if the value of "int_code_page" is
6852 * 1 at entry, and we can not compute a suitable code page number,
6853 * returns the code page as a string
6855 ICALL_EXPORT MonoString*
6856 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6861 char *codepage = NULL;
6863 int want_name = *int_code_page;
6866 *int_code_page = -1;
6868 g_get_charset (&cset);
6869 c = codepage = g_strdup (cset);
6870 for (c = codepage; *c; c++){
6871 if (isascii (*c) && isalpha (*c))
6876 /* g_print ("charset: %s\n", cset); */
6878 /* handle some common aliases */
6881 for (i = 0; p != 0; ){
6884 p = encodings [++i];
6887 if (strcmp (p, codepage) == 0){
6888 *int_code_page = code;
6891 p = encodings [++i];
6894 if (strstr (codepage, "utf_8") != NULL)
6895 *int_code_page |= 0x10000000;
6898 if (want_name && *int_code_page == -1)
6899 return mono_string_new (mono_domain_get (), cset);
6904 ICALL_EXPORT MonoBoolean
6905 ves_icall_System_Environment_get_HasShutdownStarted (void)
6907 if (mono_runtime_is_shutting_down ())
6910 if (mono_domain_is_unloading (mono_domain_get ()))
6918 mono_icall_broadcast_setting_change (void)
6922 #endif /* !HOST_WIN32 */
6925 ves_icall_System_Environment_BroadcastSettingChange (void)
6927 mono_icall_broadcast_setting_change ();
6932 ves_icall_System_Environment_get_TickCount (void)
6934 /* this will overflow after ~24 days */
6935 return (gint32) (mono_msec_boottime () & 0xffffffff);
6939 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6944 #ifndef DISABLE_REMOTING
6945 ICALL_EXPORT MonoBoolean
6946 ves_icall_IsTransparentProxy (MonoObject *proxy)
6951 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6957 ICALL_EXPORT MonoReflectionMethod *
6958 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6959 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6961 MonoReflectionMethod *ret = NULL;
6966 MonoMethod **vtable;
6967 MonoMethod *res = NULL;
6969 MONO_CHECK_ARG_NULL (rtype, NULL);
6970 MONO_CHECK_ARG_NULL (rmethod, NULL);
6972 method = rmethod->method;
6973 klass = mono_class_from_mono_type (rtype->type);
6974 mono_class_init_checked (klass, &error);
6975 if (mono_error_set_pending_exception (&error))
6978 if (MONO_CLASS_IS_INTERFACE (klass))
6981 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6984 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6985 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6991 mono_class_setup_vtable (klass);
6992 vtable = klass->vtable;
6994 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6995 gboolean variance_used = FALSE;
6996 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6997 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6999 res = vtable [offs + method->slot];
7001 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7004 if (method->slot != -1)
7005 res = vtable [method->slot];
7011 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7012 mono_error_set_pending_exception (&error);
7017 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7023 klass = mono_class_from_mono_type (type->type);
7024 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7025 if (!is_ok (&error)) {
7026 mono_error_set_pending_exception (&error);
7030 mono_vtable_set_is_remote (vtable, enable);
7033 #else /* DISABLE_REMOTING */
7036 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7038 g_assert_not_reached ();
7043 ICALL_EXPORT MonoObject *
7044 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7051 domain = mono_object_domain (type);
7052 klass = mono_class_from_mono_type (type->type);
7053 mono_class_init_checked (klass, &error);
7054 if (mono_error_set_pending_exception (&error))
7057 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7058 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7062 if (klass->rank >= 1) {
7063 g_assert (klass->rank == 1);
7064 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7065 mono_error_set_pending_exception (&error);
7068 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7069 if (!is_ok (&error)) {
7070 mono_error_set_pending_exception (&error);
7073 /* Bypass remoting object creation check */
7074 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7075 mono_error_set_pending_exception (&error);
7081 ICALL_EXPORT MonoStringHandle
7082 ves_icall_System_IO_get_temp_path (MonoError *error)
7084 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7087 #ifndef PLATFORM_NO_DRIVEINFO
7088 ICALL_EXPORT MonoBoolean
7089 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7090 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7094 ULARGE_INTEGER wapi_free_bytes_avail;
7095 ULARGE_INTEGER wapi_total_number_of_bytes;
7096 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7098 *error = ERROR_SUCCESS;
7099 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7100 &wapi_total_number_of_free_bytes);
7103 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7104 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7105 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7107 *free_bytes_avail = 0;
7108 *total_number_of_bytes = 0;
7109 *total_number_of_free_bytes = 0;
7110 *error = GetLastError ();
7116 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
7117 static inline guint32
7118 mono_icall_drive_info_get_drive_type (MonoString *root_path_name)
7120 return GetDriveType (mono_string_chars (root_path_name));
7122 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
7124 ICALL_EXPORT guint32
7125 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7127 return mono_icall_drive_info_get_drive_type (root_path_name);
7130 #endif /* PLATFORM_NO_DRIVEINFO */
7132 ICALL_EXPORT gpointer
7133 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7136 gpointer result = mono_compile_method_checked (method, &error);
7137 mono_error_set_pending_exception (&error);
7141 ICALL_EXPORT MonoString *
7142 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7147 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7149 mono_icall_make_platform_path (path);
7151 mcpath = mono_string_new (mono_domain_get (), path);
7157 /* this is an icall */
7159 get_bundled_app_config (void)
7162 const gchar *app_config;
7165 gchar *config_file_name, *config_file_path;
7166 gsize len, config_file_path_length, config_ext_length;
7169 domain = mono_domain_get ();
7170 file = domain->setup->configuration_file;
7171 if (!file || file->length == 0)
7174 // Retrieve config file and remove the extension
7175 config_file_name = mono_string_to_utf8_checked (file, &error);
7176 if (mono_error_set_pending_exception (&error))
7178 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7179 if (!config_file_path)
7180 config_file_path = config_file_name;
7182 config_file_path_length = strlen (config_file_path);
7183 config_ext_length = strlen (".config");
7184 if (config_file_path_length <= config_ext_length)
7187 len = config_file_path_length - config_ext_length;
7188 module = (gchar *)g_malloc0 (len + 1);
7189 memcpy (module, config_file_path, len);
7190 // Get the config file from the module name
7191 app_config = mono_config_string_for_assembly_file (module);
7194 if (config_file_name != config_file_path)
7195 g_free (config_file_name);
7196 g_free (config_file_path);
7201 return mono_string_new (mono_domain_get (), app_config);
7204 static MonoStringHandle
7205 get_bundled_machine_config (MonoError *error)
7207 const gchar *machine_config;
7209 machine_config = mono_get_machine_config ();
7211 if (!machine_config)
7212 return NULL_HANDLE_STRING;
7214 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7217 ICALL_EXPORT MonoStringHandle
7218 ves_icall_System_Environment_get_bundled_machine_config (MonoError *error)
7220 return get_bundled_machine_config (error);
7224 ICALL_EXPORT MonoStringHandle
7225 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7227 return get_bundled_machine_config (error);
7230 ICALL_EXPORT MonoStringHandle
7231 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7233 return get_bundled_machine_config (error);
7237 ICALL_EXPORT MonoString *
7238 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7243 path = g_path_get_dirname (mono_get_config_dir ());
7245 mono_icall_make_platform_path (path);
7247 ipath = mono_string_new (mono_domain_get (), path);
7253 ICALL_EXPORT gboolean
7254 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7256 MonoPEResourceDataEntry *entry;
7259 if (!assembly || !result || !size)
7264 image = assembly->assembly->image;
7265 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7269 *result = mono_image_rva_map (image, entry->rde_data_offset);
7274 *size = entry->rde_size;
7279 ICALL_EXPORT MonoBoolean
7280 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7282 return mono_is_debugger_attached ();
7285 ICALL_EXPORT MonoBoolean
7286 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7288 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7289 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7295 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7297 if (mono_get_runtime_callbacks ()->debug_log)
7298 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7303 mono_icall_write_windows_debug_string (MonoString *message)
7305 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7307 #endif /* !HOST_WIN32 */
7310 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7312 mono_icall_write_windows_debug_string (message);
7315 /* Only used for value types */
7316 ICALL_EXPORT MonoObject *
7317 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7324 domain = mono_object_domain (type);
7325 klass = mono_class_from_mono_type (type->type);
7326 mono_class_init_checked (klass, &error);
7327 if (mono_error_set_pending_exception (&error))
7330 if (mono_class_is_nullable (klass))
7331 /* No arguments -> null */
7334 result = mono_object_new_checked (domain, klass, &error);
7335 mono_error_set_pending_exception (&error);
7339 ICALL_EXPORT MonoReflectionMethod *
7340 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7342 MonoReflectionMethod *ret = NULL;
7345 MonoClass *klass, *parent;
7346 MonoGenericContext *generic_inst = NULL;
7347 MonoMethod *method = m->method;
7348 MonoMethod *result = NULL;
7351 if (method->klass == NULL)
7354 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7355 MONO_CLASS_IS_INTERFACE (method->klass) ||
7356 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7359 slot = mono_method_get_vtable_slot (method);
7363 klass = method->klass;
7364 if (klass->generic_class) {
7365 generic_inst = mono_class_get_context (klass);
7366 klass = klass->generic_class->container_class;
7371 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7372 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7373 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7374 or klass is the generic container class and generic_inst is the instantiation.
7376 when we go to the parent, if the parent is an open constructed type, we need to
7377 replace the type parameters by the definitions from the generic_inst, and then take it
7378 apart again into the klass and the generic_inst.
7380 For cases like this:
7381 class C<T> : B<T, int> {
7382 public override void Foo () { ... }
7384 class B<U,V> : A<HashMap<U,V>> {
7385 public override void Foo () { ... }
7388 public virtual void Foo () { ... }
7391 if at each iteration the parent isn't open, we can skip inflating it. if at some
7392 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7395 MonoGenericContext *parent_inst = NULL;
7396 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7397 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7398 if (!mono_error_ok (&error)) {
7399 mono_error_set_pending_exception (&error);
7403 if (parent->generic_class) {
7404 parent_inst = mono_class_get_context (parent);
7405 parent = parent->generic_class->container_class;
7408 mono_class_setup_vtable (parent);
7409 if (parent->vtable_size <= slot)
7412 generic_inst = parent_inst;
7415 klass = klass->parent;
7418 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7419 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7420 if (!mono_error_ok (&error)) {
7421 mono_error_set_pending_exception (&error);
7425 generic_inst = NULL;
7427 if (klass->generic_class) {
7428 generic_inst = mono_class_get_context (klass);
7429 klass = klass->generic_class->container_class;
7435 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7436 if (!mono_error_ok (&error)) {
7437 mono_error_set_pending_exception (&error);
7442 if (klass == method->klass)
7445 /*This is possible if definition == FALSE.
7446 * Do it here to be really sure we don't read invalid memory.
7448 if (slot >= klass->vtable_size)
7451 mono_class_setup_vtable (klass);
7453 result = klass->vtable [slot];
7454 if (result == NULL) {
7455 /* It is an abstract method */
7456 gboolean found = FALSE;
7457 gpointer iter = NULL;
7458 while ((result = mono_class_get_methods (klass, &iter))) {
7459 if (result->slot == slot) {
7464 /* found might be FALSE if we looked in an abstract class
7465 * that doesn't override an abstract method of its
7467 * abstract class Base {
7468 * public abstract void Foo ();
7470 * abstract class Derived : Base { }
7471 * class Child : Derived {
7472 * public override void Foo () { }
7475 * if m was Child.Foo and we ask for the base method,
7476 * then we get here with klass == Derived and found == FALSE
7478 /* but it shouldn't be the case that if we're looking
7479 * for the definition and didn't find a result; the
7480 * loop above should've taken us as far as we could
7482 g_assert (!(definition && !found));
7487 g_assert (result != NULL);
7489 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7490 mono_error_set_pending_exception (&error);
7494 ICALL_EXPORT MonoString*
7495 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7497 MonoMethod *method = m->method;
7499 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7504 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7506 iter->sig = *(MonoMethodSignature**)argsp;
7508 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7509 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7512 /* FIXME: it's not documented what start is exactly... */
7516 iter->args = argsp + sizeof (gpointer);
7518 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7520 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7523 ICALL_EXPORT MonoTypedRef
7524 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7526 guint32 i, arg_size;
7530 i = iter->sig->sentinelpos + iter->next_arg;
7532 g_assert (i < iter->sig->param_count);
7534 res.type = iter->sig->params [i];
7535 res.klass = mono_class_from_mono_type (res.type);
7536 arg_size = mono_type_stack_size (res.type, &align);
7537 #if defined(__arm__) || defined(__mips__)
7538 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7540 res.value = iter->args;
7541 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7542 /* Values are stored as 8 byte register sized objects, but 'value'
7543 * is dereferenced as a pointer in other routines.
7545 res.value = (char*)res.value + 4;
7547 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7548 if (arg_size <= sizeof (gpointer)) {
7550 int padding = arg_size - mono_type_size (res.type, &dummy);
7551 res.value = (guint8*)res.value + padding;
7554 iter->args = (char*)iter->args + arg_size;
7557 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7562 ICALL_EXPORT MonoTypedRef
7563 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7565 guint32 i, arg_size;
7569 i = iter->sig->sentinelpos + iter->next_arg;
7571 g_assert (i < iter->sig->param_count);
7573 while (i < iter->sig->param_count) {
7574 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7576 res.type = iter->sig->params [i];
7577 res.klass = mono_class_from_mono_type (res.type);
7578 /* FIXME: endianess issue... */
7579 arg_size = mono_type_stack_size (res.type, &align);
7580 #if defined(__arm__) || defined(__mips__)
7581 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7583 res.value = iter->args;
7584 iter->args = (char*)iter->args + arg_size;
7586 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7589 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7597 ICALL_EXPORT MonoType*
7598 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7602 i = iter->sig->sentinelpos + iter->next_arg;
7604 g_assert (i < iter->sig->param_count);
7606 return iter->sig->params [i];
7609 ICALL_EXPORT MonoObject*
7610 mono_TypedReference_ToObject (MonoTypedRef* tref)
7613 MonoObject *result = NULL;
7614 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7615 MonoObject** objp = (MonoObject **)tref->value;
7619 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7620 mono_error_set_pending_exception (&error);
7624 ICALL_EXPORT MonoTypedRef
7625 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7628 MonoReflectionField *f;
7630 MonoType *ftype = NULL;
7634 memset (&res, 0, sizeof (res));
7637 g_assert (mono_array_length (fields) > 0);
7639 klass = target->vtable->klass;
7641 for (i = 0; i < mono_array_length (fields); ++i) {
7642 f = mono_array_get (fields, MonoReflectionField*, i);
7644 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7647 if (f->field->parent != klass) {
7648 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7652 p = (guint8*)target + f->field->offset;
7654 p += f->field->offset - sizeof (MonoObject);
7655 klass = mono_class_from_mono_type (f->field->type);
7656 ftype = f->field->type;
7660 res.klass = mono_class_from_mono_type (ftype);
7667 prelink_method (MonoMethod *method, MonoError *error)
7669 const char *exc_class, *exc_arg;
7671 mono_error_init (error);
7672 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7674 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7676 mono_error_set_exception_instance (error,
7677 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7680 /* create the wrapper, too? */
7684 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7688 prelink_method (method->method, &error);
7689 mono_error_set_pending_exception (&error);
7693 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7696 MonoClass *klass = mono_class_from_mono_type (type->type);
7698 gpointer iter = NULL;
7700 mono_class_init_checked (klass, &error);
7701 if (mono_error_set_pending_exception (&error))
7704 while ((m = mono_class_get_methods (klass, &iter))) {
7705 prelink_method (m, &error);
7706 if (mono_error_set_pending_exception (&error))
7711 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7713 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7714 gint32 const **exponents,
7715 gunichar2 const **digitLowerTable,
7716 gunichar2 const **digitUpperTable,
7717 gint64 const **tenPowersList,
7718 gint32 const **decHexDigits)
7720 *mantissas = Formatter_MantissaBitsTable;
7721 *exponents = Formatter_TensExponentTable;
7722 *digitLowerTable = Formatter_DigitLowerTable;
7723 *digitUpperTable = Formatter_DigitUpperTable;
7724 *tenPowersList = Formatter_TenPowersList;
7725 *decHexDigits = Formatter_DecHexDigits;
7729 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7730 * and avoid useless allocations.
7733 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7735 MonoReflectionType *rt;
7739 mono_error_init (error);
7740 for (i = 0; i < type->num_mods; ++i) {
7741 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7746 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7747 return_val_if_nok (error, NULL);
7749 for (i = 0; i < type->num_mods; ++i) {
7750 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7751 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7752 return_val_if_nok (error, NULL);
7754 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7755 return_val_if_nok (error, NULL);
7757 mono_array_setref (res, count, rt);
7764 ICALL_EXPORT MonoArray*
7765 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7768 MonoType *type = param->ClassImpl->type;
7769 MonoClass *member_class = mono_object_class (param->MemberImpl);
7770 MonoMethod *method = NULL;
7773 MonoMethodSignature *sig;
7776 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7777 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7778 method = rmethod->method;
7779 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7780 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7781 if (!(method = prop->property->get))
7782 method = prop->property->set;
7785 char *type_name = mono_type_get_full_name (member_class);
7786 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7787 MonoException *ex = mono_get_exception_not_supported (msg);
7790 mono_set_pending_exception (ex);
7794 image = method->klass->image;
7795 pos = param->PositionImpl;
7796 sig = mono_method_signature (method);
7800 type = sig->params [pos];
7802 res = type_array_from_modifiers (image, type, optional, &error);
7803 mono_error_set_pending_exception (&error);
7808 get_property_type (MonoProperty *prop)
7810 MonoMethodSignature *sig;
7812 sig = mono_method_signature (prop->get);
7814 } else if (prop->set) {
7815 sig = mono_method_signature (prop->set);
7816 return sig->params [sig->param_count - 1];
7821 ICALL_EXPORT MonoArray*
7822 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7825 MonoType *type = get_property_type (property->property);
7826 MonoImage *image = property->klass->image;
7831 res = type_array_from_modifiers (image, type, optional, &error);
7832 mono_error_set_pending_exception (&error);
7837 *Construct a MonoType suited to be used to decode a constant blob object.
7839 * @type is the target type which will be constructed
7840 * @blob_type is the blob type, for example, that comes from the constant table
7841 * @real_type is the expected constructed type.
7844 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7846 type->type = blob_type;
7847 type->data.klass = NULL;
7848 if (blob_type == MONO_TYPE_CLASS)
7849 type->data.klass = mono_defaults.object_class;
7850 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7851 /* For enums, we need to use the base type */
7852 type->type = MONO_TYPE_VALUETYPE;
7853 type->data.klass = mono_class_from_mono_type (real_type);
7855 type->data.klass = mono_class_from_mono_type (real_type);
7858 ICALL_EXPORT MonoObject*
7859 property_info_get_default_value (MonoReflectionProperty *property)
7863 MonoProperty *prop = property->property;
7864 MonoType *type = get_property_type (prop);
7865 MonoDomain *domain = mono_object_domain (property);
7866 MonoTypeEnum def_type;
7867 const char *def_value;
7870 mono_class_init (prop->parent);
7872 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7873 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7877 def_value = mono_class_get_property_default_value (prop, &def_type);
7879 mono_type_from_blob_type (&blob_type, def_type, type);
7880 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7882 mono_error_set_pending_exception (&error);
7886 ICALL_EXPORT MonoBoolean
7887 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7890 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7891 MonoCustomAttrInfo *cinfo;
7894 mono_class_init_checked (attr_class, &error);
7895 if (mono_error_set_pending_exception (&error))
7898 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7899 if (!is_ok (&error)) {
7900 mono_error_set_pending_exception (&error);
7905 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7907 mono_custom_attrs_free (cinfo);
7911 ICALL_EXPORT MonoArray*
7912 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7914 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7919 mono_class_init_checked (attr_class, &error);
7920 if (mono_error_set_pending_exception (&error))
7924 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7925 if (!mono_error_ok (&error)) {
7926 mono_error_set_pending_exception (&error);
7933 ICALL_EXPORT MonoArray*
7934 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7938 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7939 mono_error_set_pending_exception (&error);
7944 ICALL_EXPORT MonoString*
7945 ves_icall_Mono_Runtime_GetDisplayName (void)
7948 MonoString *display_name;
7950 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7951 display_name = mono_string_new (mono_domain_get (), info);
7953 return display_name;
7956 ICALL_EXPORT MonoString*
7957 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7960 MonoString *message;
7964 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7965 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7968 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7970 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7971 if (mono_error_set_pending_exception (&error))
7978 ICALL_EXPORT gpointer
7979 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7981 return GetCurrentProcess ();
7984 ICALL_EXPORT MonoBoolean
7985 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7987 return GetExitCodeProcess (handle, (guint32*) exitcode);
7991 static inline MonoBoolean
7992 mono_icall_close_process (gpointer handle)
7994 return CloseProcess (handle);
7996 #endif /* !HOST_WIN32 */
7998 ICALL_EXPORT MonoBoolean
7999 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8001 return mono_icall_close_process (handle);
8004 ICALL_EXPORT MonoBoolean
8005 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8007 return TerminateProcess (handle, exitcode);
8011 static inline gint32
8012 mono_icall_wait_for_input_idle (gpointer handle, gint32 milliseconds)
8014 return WAIT_TIMEOUT;
8016 #endif /* !HOST_WIN32 */
8019 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8021 return mono_icall_wait_for_input_idle (handle, milliseconds);
8024 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
8025 static inline MonoBoolean
8026 mono_icall_get_process_working_set_size (gpointer handle, gsize *min, gsize *max)
8028 return GetProcessWorkingSetSize (handle, min, max);
8030 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
8032 ICALL_EXPORT MonoBoolean
8033 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8035 return mono_icall_get_process_working_set_size (handle, min, max);
8038 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
8039 static inline MonoBoolean
8040 mono_icall_set_process_working_set_size (gpointer handle, gsize min, gsize max)
8042 return SetProcessWorkingSetSize (handle, min, max);
8044 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
8046 ICALL_EXPORT MonoBoolean
8047 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8049 return mono_icall_set_process_working_set_size (handle, min, max);
8052 ICALL_EXPORT MonoBoolean
8053 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8055 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8059 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8061 return mono_process_current_pid ();
8064 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
8065 static inline gint32
8066 mono_icall_get_priority_class (gpointer handle)
8068 return GetPriorityClass (handle);
8070 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
8073 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8075 return mono_icall_get_priority_class (handle);
8078 #if G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT)
8079 static inline MonoBoolean
8080 mono_icall_set_priority_class (gpointer handle, gint32 priorityClass)
8082 return SetPriorityClass (handle, priorityClass);
8084 #endif /* G_HAVE_API_SUPPORT(HAVE_CLASSIC_WINAPI_SUPPORT) */
8086 ICALL_EXPORT MonoBoolean
8087 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8089 return mono_icall_set_priority_class (handle, priorityClass);
8092 ICALL_EXPORT MonoBoolean
8093 ves_icall_Mono_TlsProviderFactory_IsBtlsSupported (void)
8105 ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT(MonoException* ex)
8107 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetHRForException_WinRT internal call is not implemented."));
8111 ICALL_EXPORT MonoObject*
8112 ves_icall_System_Runtime_InteropServices_Marshal_GetNativeActivationFactory(MonoObject* type)
8114 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetNativeActivationFactory internal call is not implemented."));
8119 ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef(MonoObject* obj)
8121 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.Marshal.GetRawIUnknownForComObjectNoAddRef internal call is not implemented."));
8125 ICALL_EXPORT MonoObject*
8126 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_GetRestrictedErrorInfo()
8128 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.GetRestrictedErrorInfo internal call is not implemented."));
8132 ICALL_EXPORT MonoBoolean
8133 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoOriginateLanguageException(int error, MonoString* message, void* languageException)
8135 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoOriginateLanguageException internal call is not implemented."));
8140 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_RoReportUnhandledError(MonoObject* error)
8142 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.RoReportUnhandledError internal call is not implemented."));
8146 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsCreateString(MonoString* sourceString, int length, void** hstring)
8148 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString internal call is not implemented."));
8153 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsDeleteString(void* hstring)
8155 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString internal call is not implemented."));
8159 ICALL_EXPORT mono_unichar2*
8160 ves_icall_System_Runtime_InteropServices_WindowsRuntime_UnsafeNativeMethods_WindowsGetStringRawBuffer(void* hstring, unsigned* length)
8162 mono_set_pending_exception(mono_get_exception_not_implemented("System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsGetStringRawBuffer internal call is not implemented."));
8169 #ifndef DISABLE_ICALL_TABLES
8171 #define ICALL_TYPE(id,name,first)
8172 #define ICALL(id,name,func) Icall_ ## id,
8173 #define HANDLES(inner) inner
8176 #include "metadata/icall-def.h"
8182 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8183 #define ICALL(id,name,func)
8185 #define HANDLES(inner) inner
8187 #include "metadata/icall-def.h"
8193 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8194 #define ICALL(id,name,func)
8196 #define HANDLES(inner) inner
8198 guint16 first_icall;
8201 static const IcallTypeDesc
8202 icall_type_descs [] = {
8203 #include "metadata/icall-def.h"
8207 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8210 #define HANDLES(inner) inner
8212 #define ICALL_TYPE(id,name,first)
8215 #ifdef HAVE_ARRAY_ELEM_INIT
8216 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8217 #define MSGSTRFIELD1(line) str##line
8219 static const struct msgstrtn_t {
8220 #define ICALL(id,name,func)
8222 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8223 #include "metadata/icall-def.h"
8225 } icall_type_names_str = {
8226 #define ICALL_TYPE(id,name,first) (name),
8227 #include "metadata/icall-def.h"
8230 static const guint16 icall_type_names_idx [] = {
8231 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8232 #include "metadata/icall-def.h"
8235 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8237 static const struct msgstr_t {
8239 #define ICALL_TYPE(id,name,first)
8240 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8241 #include "metadata/icall-def.h"
8243 } icall_names_str = {
8244 #define ICALL(id,name,func) (name),
8245 #include "metadata/icall-def.h"
8248 static const guint16 icall_names_idx [] = {
8249 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8250 #include "metadata/icall-def.h"
8253 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8259 #define ICALL_TYPE(id,name,first) name,
8260 #define ICALL(id,name,func)
8261 static const char* const
8262 icall_type_names [] = {
8263 #include "metadata/icall-def.h"
8267 #define icall_type_name_get(id) (icall_type_names [(id)])
8271 #define ICALL_TYPE(id,name,first)
8272 #define ICALL(id,name,func) name,
8273 static const char* const
8275 #include "metadata/icall-def.h"
8278 #define icall_name_get(id) icall_names [(id)]
8280 #endif /* !HAVE_ARRAY_ELEM_INIT */
8283 #define HANDLES(inner) inner
8286 #define ICALL_TYPE(id,name,first)
8287 #define ICALL(id,name,func) func,
8288 static const gconstpointer
8289 icall_functions [] = {
8290 #include "metadata/icall-def.h"
8294 #ifdef ENABLE_ICALL_SYMBOL_MAP
8296 #define HANDLES(inner) inner
8299 #define ICALL_TYPE(id,name,first)
8300 #define ICALL(id,name,func) #func,
8301 static const gconstpointer
8302 icall_symbols [] = {
8303 #include "metadata/icall-def.h"
8310 #define ICALL_TYPE(id,name,first)
8311 #define ICALL(id,name,func) 0,
8313 #define HANDLES(inner) 1,
8315 icall_uses_handles [] = {
8316 #include "metadata/icall-def.h"
8321 #endif /* DISABLE_ICALL_TABLES */
8323 static mono_mutex_t icall_mutex;
8324 static GHashTable *icall_hash = NULL;
8325 static GHashTable *jit_icall_hash_name = NULL;
8326 static GHashTable *jit_icall_hash_addr = NULL;
8329 mono_icall_init (void)
8331 #ifndef DISABLE_ICALL_TABLES
8334 /* check that tables are sorted: disable in release */
8337 const char *prev_class = NULL;
8338 const char *prev_method;
8340 for (i = 0; i < Icall_type_num; ++i) {
8341 const IcallTypeDesc *desc;
8344 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8345 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8346 prev_class = icall_type_name_get (i);
8347 desc = &icall_type_descs [i];
8348 num_icalls = icall_desc_num_icalls (desc);
8349 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8350 for (j = 0; j < num_icalls; ++j) {
8351 const char *methodn = icall_name_get (desc->first_icall + j);
8352 if (prev_method && strcmp (prev_method, methodn) >= 0)
8353 g_print ("method %s should come before method %s\n", methodn, prev_method);
8354 prev_method = methodn;
8360 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8361 mono_os_mutex_init (&icall_mutex);
8365 mono_icall_lock (void)
8367 mono_locks_os_acquire (&icall_mutex, IcallLock);
8371 mono_icall_unlock (void)
8373 mono_locks_os_release (&icall_mutex, IcallLock);
8377 mono_icall_cleanup (void)
8379 g_hash_table_destroy (icall_hash);
8380 g_hash_table_destroy (jit_icall_hash_name);
8381 g_hash_table_destroy (jit_icall_hash_addr);
8382 mono_os_mutex_destroy (&icall_mutex);
8386 * mono_add_internal_call:
8387 * @name: method specification to surface to the managed world
8388 * @method: pointer to a C method to invoke when the method is called
8390 * This method surfaces the C function pointed by @method as a method
8391 * that has been surfaced in managed code with the method specified in
8392 * @name as an internal call.
8394 * Internal calls are surfaced to all app domains loaded and they are
8395 * accessibly by a type with the specified name.
8397 * You must provide a fully qualified type name, that is namespaces
8398 * and type name, followed by a colon and the method name, with an
8399 * optional signature to bind.
8401 * For example, the following are all valid declarations:
8403 * "MyApp.Services.ScriptService:Accelerate"
8404 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8406 * You use method parameters in cases where there might be more than
8407 * one surface method to managed code. That way you can register different
8408 * internal calls for different method overloads.
8410 * The internal calls are invoked with no marshalling. This means that .NET
8411 * types like System.String are exposed as `MonoString *` parameters. This is
8412 * different than the way that strings are surfaced in P/Invoke.
8414 * For more information on how the parameters are marshalled, see the
8415 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8418 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8419 * reference for more information on the format of method descriptions.
8422 mono_add_internal_call (const char *name, gconstpointer method)
8426 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8428 mono_icall_unlock ();
8431 #ifndef DISABLE_ICALL_TABLES
8433 #ifdef HAVE_ARRAY_ELEM_INIT
8435 compare_method_imap (const void *key, const void *elem)
8437 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8438 return strcmp (key, method_name);
8442 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8444 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);
8447 return (nameslot - &icall_names_idx [0]);
8451 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8453 gsize slotnum = find_slot_icall (imap, name);
8456 return (gboolean)icall_uses_handles [slotnum];
8460 find_method_icall (const IcallTypeDesc *imap, const char *name)
8462 gsize slotnum = find_slot_icall (imap, name);
8465 return (gpointer)icall_functions [slotnum];
8469 compare_class_imap (const void *key, const void *elem)
8471 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8472 return strcmp (key, class_name);
8475 static const IcallTypeDesc*
8476 find_class_icalls (const char *name)
8478 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);
8481 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8484 #else /* HAVE_ARRAY_ELEM_INIT */
8487 compare_method_imap (const void *key, const void *elem)
8489 const char** method_name = (const char**)elem;
8490 return strcmp (key, *method_name);
8494 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8496 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8499 return nameslot - icall_names;
8503 find_method_icall (const IcallTypeDesc *imap, const char *name)
8505 gsize slotnum = find_slot_icall (imap, name);
8508 return (gpointer)icall_functions [slotnum];
8512 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8514 gsize slotnum = find_slot_icall (imap, name);
8517 return (gboolean)icall_uses_handles [slotnum];
8521 compare_class_imap (const void *key, const void *elem)
8523 const char** class_name = (const char**)elem;
8524 return strcmp (key, *class_name);
8527 static const IcallTypeDesc*
8528 find_class_icalls (const char *name)
8530 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8533 return &icall_type_descs [nameslot - icall_type_names];
8536 #endif /* HAVE_ARRAY_ELEM_INIT */
8538 #endif /* DISABLE_ICALL_TABLES */
8541 * we should probably export this as an helper (handle nested types).
8542 * Returns the number of chars written in buf.
8545 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8547 int nspacelen, cnamelen;
8548 nspacelen = strlen (klass->name_space);
8549 cnamelen = strlen (klass->name);
8550 if (nspacelen + cnamelen + 2 > bufsize)
8553 memcpy (buf, klass->name_space, nspacelen);
8554 buf [nspacelen ++] = '.';
8556 memcpy (buf + nspacelen, klass->name, cnamelen);
8557 buf [nspacelen + cnamelen] = 0;
8558 return nspacelen + cnamelen;
8561 #ifdef DISABLE_ICALL_TABLES
8563 no_icall_table (void)
8565 g_assert_not_reached ();
8570 * mono_lookup_internal_call_full:
8571 * @method: the method to look up
8572 * @uses_handles: out argument if method needs handles around managed objects.
8574 * Returns a pointer to the icall code for the given method. If
8575 * uses_handles is not NULL, it will be set to TRUE if the method
8576 * needs managed objects wrapped using the infrastructure in handle.h
8578 * If the method is not found, warns and returns NULL.
8581 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8586 int typelen = 0, mlen, siglen;
8588 #ifndef DISABLE_ICALL_TABLES
8589 const IcallTypeDesc *imap = NULL;
8592 g_assert (method != NULL);
8594 if (method->is_inflated)
8595 method = ((MonoMethodInflated *) method)->declaring;
8597 if (method->klass->nested_in) {
8598 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8602 mname [pos++] = '/';
8605 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8611 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8616 #ifndef DISABLE_ICALL_TABLES
8617 imap = find_class_icalls (mname);
8620 mname [typelen] = ':';
8621 mname [typelen + 1] = ':';
8623 mlen = strlen (method->name);
8624 memcpy (mname + typelen + 2, method->name, mlen);
8625 sigstart = mname + typelen + 2 + mlen;
8628 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8629 siglen = strlen (tmpsig);
8630 if (typelen + mlen + siglen + 6 > sizeof (mname))
8633 memcpy (sigstart + 1, tmpsig, siglen);
8634 sigstart [siglen + 1] = ')';
8635 sigstart [siglen + 2] = 0;
8640 res = g_hash_table_lookup (icall_hash, mname);
8643 *uses_handles = FALSE;
8644 mono_icall_unlock ();;
8647 /* try without signature */
8649 res = g_hash_table_lookup (icall_hash, mname);
8652 *uses_handles = FALSE;
8653 mono_icall_unlock ();
8657 #ifdef DISABLE_ICALL_TABLES
8658 mono_icall_unlock ();
8659 /* Fail only when the result is actually used */
8660 /* mono_marshal_get_native_wrapper () depends on this */
8661 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8662 return ves_icall_System_String_ctor_RedirectToCreateString;
8664 return no_icall_table;
8666 /* it wasn't found in the static call tables */
8669 *uses_handles = FALSE;
8670 mono_icall_unlock ();
8673 res = find_method_icall (imap, sigstart - mlen);
8676 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8677 mono_icall_unlock ();
8680 /* try _with_ signature */
8682 res = find_method_icall (imap, sigstart - mlen);
8685 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8686 mono_icall_unlock ();
8690 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8691 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8692 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8693 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8694 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");
8695 g_print ("If you see other errors or faults after this message they are probably related\n");
8696 g_print ("and you need to fix your mono install first.\n");
8698 mono_icall_unlock ();
8705 mono_lookup_internal_call (MonoMethod *method)
8707 return mono_lookup_internal_call_full (method, NULL);
8710 #ifdef ENABLE_ICALL_SYMBOL_MAP
8712 func_cmp (gconstpointer key, gconstpointer p)
8714 return (gsize)key - (gsize)*(gsize*)p;
8719 * mono_lookup_icall_symbol:
8721 * Given the icall METHOD, returns its C symbol.
8724 mono_lookup_icall_symbol (MonoMethod *m)
8726 #ifdef DISABLE_ICALL_TABLES
8727 g_assert_not_reached ();
8730 #ifdef ENABLE_ICALL_SYMBOL_MAP
8734 static gconstpointer *functions_sorted;
8735 static const char**symbols_sorted;
8736 static gboolean inited;
8741 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8742 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8743 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8744 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8745 /* Bubble sort the two arrays */
8749 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8750 if (functions_sorted [i] > functions_sorted [i + 1]) {
8753 tmp = functions_sorted [i];
8754 functions_sorted [i] = functions_sorted [i + 1];
8755 functions_sorted [i + 1] = tmp;
8756 tmp = symbols_sorted [i];
8757 symbols_sorted [i] = symbols_sorted [i + 1];
8758 symbols_sorted [i + 1] = tmp;
8765 func = mono_lookup_internal_call (m);
8768 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8772 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8774 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8775 g_assert_not_reached ();
8782 type_from_typename (char *type_name)
8784 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8786 if (!strcmp (type_name, "int"))
8787 klass = mono_defaults.int_class;
8788 else if (!strcmp (type_name, "ptr"))
8789 klass = mono_defaults.int_class;
8790 else if (!strcmp (type_name, "void"))
8791 klass = mono_defaults.void_class;
8792 else if (!strcmp (type_name, "int32"))
8793 klass = mono_defaults.int32_class;
8794 else if (!strcmp (type_name, "uint32"))
8795 klass = mono_defaults.uint32_class;
8796 else if (!strcmp (type_name, "int8"))
8797 klass = mono_defaults.sbyte_class;
8798 else if (!strcmp (type_name, "uint8"))
8799 klass = mono_defaults.byte_class;
8800 else if (!strcmp (type_name, "int16"))
8801 klass = mono_defaults.int16_class;
8802 else if (!strcmp (type_name, "uint16"))
8803 klass = mono_defaults.uint16_class;
8804 else if (!strcmp (type_name, "long"))
8805 klass = mono_defaults.int64_class;
8806 else if (!strcmp (type_name, "ulong"))
8807 klass = mono_defaults.uint64_class;
8808 else if (!strcmp (type_name, "float"))
8809 klass = mono_defaults.single_class;
8810 else if (!strcmp (type_name, "double"))
8811 klass = mono_defaults.double_class;
8812 else if (!strcmp (type_name, "object"))
8813 klass = mono_defaults.object_class;
8814 else if (!strcmp (type_name, "obj"))
8815 klass = mono_defaults.object_class;
8816 else if (!strcmp (type_name, "string"))
8817 klass = mono_defaults.string_class;
8818 else if (!strcmp (type_name, "bool"))
8819 klass = mono_defaults.boolean_class;
8820 else if (!strcmp (type_name, "boolean"))
8821 klass = mono_defaults.boolean_class;
8823 g_error ("%s", type_name);
8824 g_assert_not_reached ();
8826 return &klass->byval_arg;
8830 * LOCKING: Take the corlib image lock.
8832 MonoMethodSignature*
8833 mono_create_icall_signature (const char *sigstr)
8838 MonoMethodSignature *res, *res2;
8839 MonoImage *corlib = mono_defaults.corlib;
8841 mono_image_lock (corlib);
8842 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8843 mono_image_unlock (corlib);
8848 parts = g_strsplit (sigstr, " ", 256);
8857 res = mono_metadata_signature_alloc (corlib, len - 1);
8862 * Under windows, the default pinvoke calling convention is STDCALL but
8865 res->call_convention = MONO_CALL_C;
8868 res->ret = type_from_typename (parts [0]);
8869 for (i = 1; i < len; ++i) {
8870 res->params [i - 1] = type_from_typename (parts [i]);
8875 mono_image_lock (corlib);
8876 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8878 res = res2; /*Value is allocated in the image pool*/
8880 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8881 mono_image_unlock (corlib);
8887 mono_find_jit_icall_by_name (const char *name)
8889 MonoJitICallInfo *info;
8890 g_assert (jit_icall_hash_name);
8893 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8894 mono_icall_unlock ();
8899 mono_find_jit_icall_by_addr (gconstpointer addr)
8901 MonoJitICallInfo *info;
8902 g_assert (jit_icall_hash_addr);
8905 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8906 mono_icall_unlock ();
8912 * mono_get_jit_icall_info:
8914 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8915 * caller should access it while holding the icall lock.
8918 mono_get_jit_icall_info (void)
8920 return jit_icall_hash_name;
8924 * mono_lookup_jit_icall_symbol:
8926 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8929 mono_lookup_jit_icall_symbol (const char *name)
8931 MonoJitICallInfo *info;
8932 const char *res = NULL;
8935 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8937 res = info->c_symbol;
8938 mono_icall_unlock ();
8943 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8946 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8947 mono_icall_unlock ();
8951 * 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
8952 * icalls without wrappers in some cases.
8955 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8957 MonoJitICallInfo *info;
8964 if (!jit_icall_hash_name) {
8965 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8966 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8969 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8970 g_warning ("jit icall already defined \"%s\"\n", name);
8971 g_assert_not_reached ();
8974 info = g_new0 (MonoJitICallInfo, 1);
8979 info->c_symbol = c_symbol;
8980 info->no_raise = no_raise;
8983 info->wrapper = func;
8985 info->wrapper = NULL;
8988 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8989 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8991 mono_icall_unlock ();
8996 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8998 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);