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 (HOST_WIN32)
34 #if defined (HAVE_WCHAR_H)
38 #include "mono/utils/mono-membar.h"
39 #include <mono/metadata/object.h>
40 #include <mono/metadata/threads.h>
41 #include <mono/metadata/threads-types.h>
42 #include <mono/metadata/threadpool-ms.h>
43 #include <mono/metadata/threadpool-ms-io.h>
44 #include <mono/metadata/monitor.h>
45 #include <mono/metadata/reflection.h>
46 #include <mono/metadata/image-internals.h>
47 #include <mono/metadata/assembly.h>
48 #include <mono/metadata/assembly-internals.h>
49 #include <mono/metadata/tabledefs.h>
50 #include <mono/metadata/exception.h>
51 #include <mono/metadata/exception-internals.h>
52 #include <mono/metadata/file-io.h>
53 #include <mono/metadata/console-io.h>
54 #include <mono/metadata/mono-route.h>
55 #include <mono/metadata/socket-io.h>
56 #include <mono/metadata/mono-endian.h>
57 #include <mono/metadata/tokentype.h>
58 #include <mono/metadata/domain-internals.h>
59 #include <mono/metadata/metadata-internals.h>
60 #include <mono/metadata/class-internals.h>
61 #include <mono/metadata/reflection-internals.h>
62 #include <mono/metadata/marshal.h>
63 #include <mono/metadata/gc-internals.h>
64 #include <mono/metadata/mono-gc.h>
65 #include <mono/metadata/rand.h>
66 #include <mono/metadata/sysmath.h>
67 #include <mono/metadata/string-icalls.h>
68 #include <mono/metadata/debug-helpers.h>
69 #include <mono/metadata/process.h>
70 #include <mono/metadata/environment.h>
71 #include <mono/metadata/profiler-private.h>
72 #include <mono/metadata/locales.h>
73 #include <mono/metadata/filewatcher.h>
74 #include <mono/metadata/security.h>
75 #include <mono/metadata/mono-config.h>
76 #include <mono/metadata/cil-coff.h>
77 #include <mono/metadata/number-formatter.h>
78 #include <mono/metadata/security-manager.h>
79 #include <mono/metadata/security-core-clr.h>
80 #include <mono/metadata/mono-perfcounters.h>
81 #include <mono/metadata/mono-debug.h>
82 #include <mono/metadata/mono-ptr-array.h>
83 #include <mono/metadata/verify-internals.h>
84 #include <mono/metadata/runtime.h>
85 #include <mono/metadata/file-mmap.h>
86 #include <mono/metadata/seq-points-data.h>
87 #include <mono/metadata/handle.h>
88 #include <mono/metadata/w32mutex.h>
89 #include <mono/metadata/w32semaphore.h>
90 #include <mono/metadata/w32event.h>
91 #include <mono/io-layer/io-layer.h>
92 #include <mono/utils/monobitset.h>
93 #include <mono/utils/mono-time.h>
94 #include <mono/utils/mono-proclib.h>
95 #include <mono/utils/mono-string.h>
96 #include <mono/utils/mono-error-internals.h>
97 #include <mono/utils/mono-mmap.h>
98 #include <mono/utils/mono-io-portability.h>
99 #include <mono/utils/mono-digest.h>
100 #include <mono/utils/bsearch.h>
101 #include <mono/utils/mono-os-mutex.h>
102 #include <mono/utils/mono-threads.h>
104 #if defined (HOST_WIN32)
108 #include "decimal-ms.h"
109 #include "number-ms.h"
111 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
112 #include <sys/utsname.h>
116 #include <btls/btls-ssl.h>
117 #include <btls/btls-bio.h>
118 #include <btls/btls-error.h>
119 #include <btls/btls-key.h>
120 #include <btls/btls-pkcs12.h>
121 #include <btls/btls-x509-crl.h>
122 #include <btls/btls-x509-chain.h>
123 #include <btls/btls-x509-lookup.h>
124 #include <btls/btls-x509-lookup-mono.h>
125 #include <btls/btls-x509-name.h>
126 #include <btls/btls-x509-revoked.h>
127 #include <btls/btls-x509-store-ctx.h>
128 #include <btls/btls-x509-verify-param.h>
131 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
133 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
135 /* Lazy class loading functions */
136 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
137 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
138 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
139 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
140 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
141 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
144 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
146 static inline MonoBoolean
147 is_generic_parameter (MonoType *type)
149 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
153 mono_class_init_checked (MonoClass *klass, MonoError *error)
155 mono_error_init (error);
157 if (!mono_class_init (klass))
158 mono_error_set_for_class_failure (error, klass);
161 ICALL_EXPORT MonoObject *
162 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
168 MonoObject *result = NULL;
170 ac = (MonoClass *)arr->obj.vtable->klass;
172 esize = mono_array_element_size (ac);
173 ea = (gpointer*)((char*)arr->vector + (pos * esize));
175 if (ac->element_class->valuetype) {
176 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
177 mono_error_set_pending_exception (&error);
179 result = (MonoObject *)*ea;
183 ICALL_EXPORT MonoObject *
184 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
190 MONO_CHECK_ARG_NULL (idxs, NULL);
193 ic = (MonoClass *)io->obj.vtable->klass;
195 ac = (MonoClass *)arr->obj.vtable->klass;
197 g_assert (ic->rank == 1);
198 if (io->bounds != NULL || io->max_length != ac->rank) {
199 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
203 ind = (gint32 *)io->vector;
205 if (arr->bounds == NULL) {
206 if (*ind < 0 || *ind >= arr->max_length) {
207 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
211 return ves_icall_System_Array_GetValueImpl (arr, *ind);
214 for (i = 0; i < ac->rank; i++) {
215 if ((ind [i] < arr->bounds [i].lower_bound) ||
216 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
217 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
222 pos = ind [0] - arr->bounds [0].lower_bound;
223 for (i = 1; i < ac->rank; i++)
224 pos = pos * arr->bounds [i].length + ind [i] -
225 arr->bounds [i].lower_bound;
227 return ves_icall_System_Array_GetValueImpl (arr, pos);
231 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
234 MonoClass *ac, *vc, *ec;
243 mono_error_init (&error);
246 vc = value->vtable->klass;
250 ac = arr->obj.vtable->klass;
251 ec = ac->element_class;
253 esize = mono_array_element_size (ac);
254 ea = (gpointer*)((char*)arr->vector + (pos * esize));
255 va = (gpointer*)((char*)value + sizeof (MonoObject));
257 if (mono_class_is_nullable (ec)) {
258 mono_nullable_init ((guint8*)ea, value, ec);
263 mono_gc_bzero_atomic (ea, esize);
267 #define NO_WIDENING_CONVERSION G_STMT_START{\
268 mono_set_pending_exception (mono_get_exception_argument ( \
269 "value", "not a widening conversion")); \
273 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
274 if (esize < vsize + (extra)) { \
275 mono_set_pending_exception (mono_get_exception_argument ( \
276 "value", "not a widening conversion")); \
281 #define INVALID_CAST G_STMT_START{ \
282 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
283 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
287 /* Check element (destination) type. */
288 switch (ec->byval_arg.type) {
289 case MONO_TYPE_STRING:
290 switch (vc->byval_arg.type) {
291 case MONO_TYPE_STRING:
297 case MONO_TYPE_BOOLEAN:
298 switch (vc->byval_arg.type) {
299 case MONO_TYPE_BOOLEAN:
312 NO_WIDENING_CONVERSION;
321 if (!ec->valuetype) {
322 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
323 if (mono_error_set_pending_exception (&error))
327 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
331 if (mono_object_isinst_checked (value, ec, &error)) {
332 if (ec->has_references)
333 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
335 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
338 if (mono_error_set_pending_exception (&error))
344 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
346 et = ec->byval_arg.type;
347 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
348 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
350 vt = vc->byval_arg.type;
351 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
352 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
354 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
360 case MONO_TYPE_CHAR: \
361 CHECK_WIDENING_CONVERSION(0); \
362 *(etype *) ea = (etype) u64; \
364 /* You can't assign a signed value to an unsigned array. */ \
369 /* You can't assign a floating point number to an integer array. */ \
372 NO_WIDENING_CONVERSION; \
376 #define ASSIGN_SIGNED(etype) G_STMT_START{\
382 CHECK_WIDENING_CONVERSION(0); \
383 *(etype *) ea = (etype) i64; \
385 /* You can assign an unsigned value to a signed array if the array's */ \
386 /* element size is larger than the value size. */ \
391 case MONO_TYPE_CHAR: \
392 CHECK_WIDENING_CONVERSION(1); \
393 *(etype *) ea = (etype) u64; \
395 /* You can't assign a floating point number to an integer array. */ \
398 NO_WIDENING_CONVERSION; \
402 #define ASSIGN_REAL(etype) G_STMT_START{\
406 CHECK_WIDENING_CONVERSION(0); \
407 *(etype *) ea = (etype) r64; \
409 /* All integer values fit into a floating point array, so we don't */ \
410 /* need to CHECK_WIDENING_CONVERSION here. */ \
415 *(etype *) ea = (etype) i64; \
421 case MONO_TYPE_CHAR: \
422 *(etype *) ea = (etype) u64; \
429 u64 = *(guint8 *) va;
432 u64 = *(guint16 *) va;
435 u64 = *(guint32 *) va;
438 u64 = *(guint64 *) va;
444 i64 = *(gint16 *) va;
447 i64 = *(gint32 *) va;
450 i64 = *(gint64 *) va;
453 r64 = *(gfloat *) va;
456 r64 = *(gdouble *) va;
459 u64 = *(guint16 *) va;
461 case MONO_TYPE_BOOLEAN:
462 /* Boolean is only compatible with itself. */
475 NO_WIDENING_CONVERSION;
482 /* If we can't do a direct copy, let's try a widening conversion. */
485 ASSIGN_UNSIGNED (guint16);
487 ASSIGN_UNSIGNED (guint8);
489 ASSIGN_UNSIGNED (guint16);
491 ASSIGN_UNSIGNED (guint32);
493 ASSIGN_UNSIGNED (guint64);
495 ASSIGN_SIGNED (gint8);
497 ASSIGN_SIGNED (gint16);
499 ASSIGN_SIGNED (gint32);
501 ASSIGN_SIGNED (gint64);
503 ASSIGN_REAL (gfloat);
505 ASSIGN_REAL (gdouble);
509 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
513 #undef NO_WIDENING_CONVERSION
514 #undef CHECK_WIDENING_CONVERSION
515 #undef ASSIGN_UNSIGNED
521 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
527 MONO_CHECK_ARG_NULL (idxs,);
529 ic = idxs->obj.vtable->klass;
530 ac = arr->obj.vtable->klass;
532 g_assert (ic->rank == 1);
533 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
534 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
538 ind = (gint32 *)idxs->vector;
540 if (arr->bounds == NULL) {
541 if (*ind < 0 || *ind >= arr->max_length) {
542 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
546 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
550 for (i = 0; i < ac->rank; i++)
551 if ((ind [i] < arr->bounds [i].lower_bound) ||
552 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
553 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
557 pos = ind [0] - arr->bounds [0].lower_bound;
558 for (i = 1; i < ac->rank; i++)
559 pos = pos * arr->bounds [i].length + ind [i] -
560 arr->bounds [i].lower_bound;
562 ves_icall_System_Array_SetValueImpl (arr, value, pos);
565 ICALL_EXPORT MonoArray *
566 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
569 MonoClass *aklass, *klass;
572 gboolean bounded = FALSE;
574 MONO_CHECK_ARG_NULL (type, NULL);
575 MONO_CHECK_ARG_NULL (lengths, NULL);
577 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
579 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
581 for (i = 0; i < mono_array_length (lengths); i++) {
582 if (mono_array_get (lengths, gint32, i) < 0) {
583 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
588 klass = mono_class_from_mono_type (type->type);
589 mono_class_init_checked (klass, &error);
590 if (mono_error_set_pending_exception (&error))
593 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
594 /* vectors are not the same as one dimensional arrays with no-zero bounds */
599 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
601 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
602 for (i = 0; i < aklass->rank; ++i) {
603 sizes [i] = mono_array_get (lengths, guint32, i);
605 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
607 sizes [i + aklass->rank] = 0;
610 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
611 mono_error_set_pending_exception (&error);
616 ICALL_EXPORT MonoArray *
617 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
620 MonoClass *aklass, *klass;
623 gboolean bounded = FALSE;
625 MONO_CHECK_ARG_NULL (type, NULL);
626 MONO_CHECK_ARG_NULL (lengths, NULL);
628 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
630 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
632 for (i = 0; i < mono_array_length (lengths); i++) {
633 if ((mono_array_get (lengths, gint64, i) < 0) ||
634 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
635 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
640 klass = mono_class_from_mono_type (type->type);
641 mono_class_init_checked (klass, &error);
642 if (mono_error_set_pending_exception (&error))
645 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
646 /* vectors are not the same as one dimensional arrays with no-zero bounds */
651 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
653 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
654 for (i = 0; i < aklass->rank; ++i) {
655 sizes [i] = mono_array_get (lengths, guint64, i);
657 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
659 sizes [i + aklass->rank] = 0;
662 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
663 mono_error_set_pending_exception (&error);
669 ves_icall_System_Array_GetRank (MonoObject *arr)
671 return arr->vtable->klass->rank;
675 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
677 gint32 rank = arr->obj.vtable->klass->rank;
680 if ((dimension < 0) || (dimension >= rank)) {
681 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
685 if (arr->bounds == NULL)
686 length = arr->max_length;
688 length = arr->bounds [dimension].length;
690 #ifdef MONO_BIG_ARRAYS
691 if (length > G_MAXINT32) {
692 mono_set_pending_exception (mono_get_exception_overflow ());
700 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
702 gint32 rank = arr->obj.vtable->klass->rank;
704 if ((dimension < 0) || (dimension >= rank)) {
705 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
709 if (arr->bounds == NULL)
710 return arr->max_length;
712 return arr->bounds [dimension].length;
716 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
718 gint32 rank = arr->obj.vtable->klass->rank;
720 if ((dimension < 0) || (dimension >= rank)) {
721 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
725 if (arr->bounds == NULL)
728 return arr->bounds [dimension].lower_bound;
732 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
734 int sz = mono_array_element_size (mono_object_class (arr));
735 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
738 ICALL_EXPORT MonoArray*
739 ves_icall_System_Array_Clone (MonoArray *arr)
742 MonoArray *result = mono_array_clone_checked (arr, &error);
743 mono_error_set_pending_exception (&error);
747 ICALL_EXPORT gboolean
748 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
753 MonoVTable *src_vtable;
754 MonoVTable *dest_vtable;
755 MonoClass *src_class;
756 MonoClass *dest_class;
758 src_vtable = source->obj.vtable;
759 dest_vtable = dest->obj.vtable;
761 if (src_vtable->rank != dest_vtable->rank)
764 if (source->bounds || dest->bounds)
767 /* there's no integer overflow since mono_array_length returns an unsigned integer */
768 if ((dest_idx + length > mono_array_length_fast (dest)) ||
769 (source_idx + length > mono_array_length_fast (source)))
772 src_class = src_vtable->klass->element_class;
773 dest_class = dest_vtable->klass->element_class;
776 * Handle common cases.
779 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
780 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
782 if (src_class == mono_defaults.object_class && dest_class->valuetype)
785 /* Check if we're copying a char[] <==> (u)short[] */
786 if (src_class != dest_class) {
787 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
790 /* 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. */
791 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
795 if (dest_class->valuetype) {
796 element_size = mono_array_element_size (source->obj.vtable->klass);
797 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
798 if (dest_class->has_references) {
799 mono_value_copy_array (dest, dest_idx, source_addr, length);
801 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
802 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
805 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
812 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
818 ac = (MonoClass *)arr->obj.vtable->klass;
820 esize = mono_array_element_size (ac);
821 ea = (gpointer*)((char*)arr->vector + (pos * esize));
823 mono_gc_memmove_atomic (value, ea, esize);
827 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
833 ac = (MonoClass *)arr->obj.vtable->klass;
834 ec = ac->element_class;
836 esize = mono_array_element_size (ac);
837 ea = (gpointer*)((char*)arr->vector + (pos * esize));
839 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
840 g_assert (esize == sizeof (gpointer));
841 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
843 g_assert (ec->inited);
844 g_assert (esize == mono_class_value_size (ec, NULL));
845 if (ec->has_references)
846 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
848 mono_gc_memmove_atomic (ea, value, esize);
853 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
855 MonoClass *klass = array->obj.vtable->klass;
856 guint32 size = mono_array_element_size (klass);
857 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
859 const char *field_data;
861 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
862 MonoException *exc = mono_get_exception_argument("array",
863 "Cannot initialize array of non-primitive type.");
864 mono_set_pending_exception (exc);
868 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
869 MonoException *exc = mono_get_exception_argument("field_handle",
870 "Field doesn't have an RVA");
871 mono_set_pending_exception (exc);
875 size *= array->max_length;
876 field_data = mono_field_get_data (field_handle);
878 if (size > mono_type_size (field_handle->type, &align)) {
879 MonoException *exc = mono_get_exception_argument("field_handle",
880 "Field not large enough to fill array");
881 mono_set_pending_exception (exc);
885 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
887 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
888 guint ## n *src = (guint ## n *) field_data; \
890 nEnt = (size / sizeof(guint ## n)); \
892 for (i = 0; i < nEnt; i++) { \
893 data[i] = read ## n (&src[i]); \
897 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
899 switch (type->type) {
916 memcpy (mono_array_addr (array, char, 0), field_data, size);
920 memcpy (mono_array_addr (array, char, 0), field_data, size);
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
927 return offsetof (MonoString, chars);
930 ICALL_EXPORT MonoObject *
931 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
933 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
937 MonoObject *ret = mono_object_clone_checked (obj, &error);
938 mono_error_set_pending_exception (&error);
945 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
951 MONO_CHECK_ARG_NULL (handle,);
953 klass = mono_class_from_mono_type (handle);
954 MONO_CHECK_ARG (handle, klass,);
956 if (klass->generic_container)
959 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
960 if (!is_ok (&error)) {
961 mono_error_set_pending_exception (&error);
965 /* This will call the type constructor */
966 if (!mono_runtime_class_init_full (vtable, &error))
967 mono_error_set_pending_exception (&error);
971 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
975 mono_image_check_for_module_cctor (image);
976 if (image->has_module_cctor) {
977 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
978 if (!mono_error_ok (&error)) {
979 mono_error_set_pending_exception (&error);
982 /*It's fine to raise the exception here*/
983 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
984 if (!is_ok (&error)) {
985 mono_error_set_pending_exception (&error);
988 if (!mono_runtime_class_init_full (vtable, &error))
989 mono_error_set_pending_exception (&error);
993 ICALL_EXPORT MonoBoolean
994 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
996 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
997 // It does not work on win32
1003 MonoInternalThread *thread;
1005 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
1006 /* if we have no info we are optimistic and assume there is enough room */
1010 thread = mono_thread_internal_current ();
1011 // .net seems to check that at least 50% of stack is available
1012 min_size = thread->stack_size / 2;
1014 current = (guint8 *)&stack_addr;
1015 if (current > stack_addr) {
1016 if ((current - stack_addr) < min_size)
1019 if (current - (stack_addr - stack_size) < min_size)
1026 ICALL_EXPORT MonoObject *
1027 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1030 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1031 mono_error_set_pending_exception (&error);
1037 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1041 MonoObject **values = NULL;
1044 gint32 result = (int)(gsize)mono_defaults.int32_class;
1045 MonoClassField* field;
1048 klass = mono_object_class (this_obj);
1050 if (mono_class_num_fields (klass) == 0)
1054 * Compute the starting value of the hashcode for fields of primitive
1055 * types, and return the remaining fields in an array to the managed side.
1056 * This way, we can avoid costly reflection operations in managed code.
1059 while ((field = mono_class_get_fields (klass, &iter))) {
1060 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1062 if (mono_field_is_deleted (field))
1064 /* FIXME: Add more types */
1065 switch (field->type->type) {
1067 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1069 case MONO_TYPE_STRING: {
1071 s = *(MonoString**)((guint8*)this_obj + field->offset);
1073 result ^= mono_string_hash (s);
1078 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1079 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1080 if (!is_ok (&error)) {
1081 mono_error_set_pending_exception (&error);
1084 values [count++] = o;
1090 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1091 if (mono_error_set_pending_exception (&error))
1093 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1094 for (i = 0; i < count; ++i)
1095 mono_array_setref (*fields, i, values [i]);
1102 ICALL_EXPORT MonoBoolean
1103 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1107 MonoObject **values = NULL;
1109 MonoClassField* field;
1113 MONO_CHECK_ARG_NULL (that, FALSE);
1115 if (this_obj->vtable != that->vtable)
1118 klass = mono_object_class (this_obj);
1120 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1121 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1124 * Do the comparison for fields of primitive type and return a result if
1125 * possible. Otherwise, return the remaining fields in an array to the
1126 * managed side. This way, we can avoid costly reflection operations in
1131 while ((field = mono_class_get_fields (klass, &iter))) {
1132 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1134 if (mono_field_is_deleted (field))
1136 /* FIXME: Add more types */
1137 switch (field->type->type) {
1140 case MONO_TYPE_BOOLEAN:
1141 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1146 case MONO_TYPE_CHAR:
1147 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1152 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1157 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1161 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1165 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1170 case MONO_TYPE_STRING: {
1171 MonoString *s1, *s2;
1172 guint32 s1len, s2len;
1173 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1174 s2 = *(MonoString**)((guint8*)that + field->offset);
1177 if ((s1 == NULL) || (s2 == NULL))
1179 s1len = mono_string_length (s1);
1180 s2len = mono_string_length (s2);
1184 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1190 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1191 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1192 if (!is_ok (&error)) {
1193 mono_error_set_pending_exception (&error);
1196 values [count++] = o;
1197 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1198 if (!is_ok (&error)) {
1199 mono_error_set_pending_exception (&error);
1202 values [count++] = o;
1205 if (klass->enumtype)
1206 /* enums only have one non-static field */
1212 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1213 if (mono_error_set_pending_exception (&error))
1215 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1216 for (i = 0; i < count; ++i)
1217 mono_array_setref_fast (*fields, i, values [i]);
1224 ICALL_EXPORT MonoReflectionType *
1225 ves_icall_System_Object_GetType (MonoObject *obj)
1228 MonoReflectionType *ret;
1229 #ifndef DISABLE_REMOTING
1230 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1231 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1234 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1236 mono_error_set_pending_exception (&error);
1241 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1243 MonoMethod **dest = (MonoMethod **)data;
1245 /* skip unmanaged frames */
1250 if (!strcmp (m->klass->name_space, "System.Reflection"))
1259 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1261 MonoMethod **dest = (MonoMethod **)data;
1263 /* skip unmanaged frames */
1267 if (m->wrapper_type != MONO_WRAPPER_NONE)
1275 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1286 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1288 MonoMethod **dest = (MonoMethod **)data;
1290 /* skip unmanaged frames */
1294 if (m->wrapper_type != MONO_WRAPPER_NONE)
1302 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1303 || (!strcmp (m->klass->name_space, "System"))))
1313 static MonoReflectionType *
1314 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1316 MonoMethod *m, *dest;
1318 MonoType *type = NULL;
1319 MonoAssembly *assembly = NULL;
1320 gboolean type_resolve = FALSE;
1321 MonoImage *rootimage = NULL;
1323 mono_error_init (error);
1326 * We must compute the calling assembly as type loading must happen under a metadata context.
1327 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1328 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1330 m = mono_method_get_last_managed ();
1332 if (m && m->klass->image != mono_defaults.corlib) {
1333 /* Happens with inlining */
1335 /* Ugly hack: type_from_parsed_name is called from
1336 * System.Type.internal_from_name, which is called most
1337 * directly from System.Type.GetType(string,bool,bool) but
1338 * also indirectly from places such as
1339 * System.Type.GetType(string,func,func) (via
1340 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1341 * so we need to skip over all of those to find the true caller.
1343 * It would be nice if we had stack marks.
1345 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1351 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1352 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1353 * to crash. This only seems to happen in some strange remoting
1354 * scenarios and I was unable to figure out what's happening there.
1355 * Dec 10, 2005 - Martin.
1359 assembly = dest->klass->image->assembly;
1360 type_resolve = TRUE;
1361 rootimage = assembly->image;
1363 g_warning (G_STRLOC);
1366 if (info->assembly.name)
1367 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1370 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1371 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1372 return_val_if_nok (error, NULL);
1376 // Say we're looking for System.Generic.Dict<int, Local>
1377 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1378 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1379 // is messed up when we go to construct the Local as the type arg...
1381 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1382 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1383 if (!info->assembly.name && !type) {
1385 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1386 return_val_if_nok (error, NULL);
1388 if (assembly && !type && type_resolve) {
1389 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1390 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1391 return_val_if_nok (error, NULL);
1397 return mono_type_get_object_checked (mono_domain_get (), type, error);
1400 ICALL_EXPORT MonoReflectionType*
1401 ves_icall_System_Type_internal_from_name (MonoString *name,
1402 MonoBoolean throwOnError,
1403 MonoBoolean ignoreCase)
1406 MonoTypeNameParse info;
1407 MonoReflectionType *type = NULL;
1410 char *str = mono_string_to_utf8_checked (name, &error);
1411 if (!is_ok (&error))
1414 parsedOk = mono_reflection_parse_type (str, &info);
1416 /* mono_reflection_parse_type() mangles the string */
1418 mono_reflection_free_type_info (&info);
1420 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1424 type = type_from_parsed_name (&info, ignoreCase, &error);
1426 mono_reflection_free_type_info (&info);
1428 if (!is_ok (&error))
1433 mono_error_set_type_load_name (&error, g_strdup (str), g_strdup (""), "");
1440 if (!is_ok (&error)) {
1442 mono_error_set_pending_exception (&error);
1444 mono_error_cleanup (&error);
1452 ICALL_EXPORT MonoReflectionType*
1453 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1456 MonoReflectionType *ret;
1457 MonoDomain *domain = mono_domain_get ();
1459 ret = mono_type_get_object_checked (domain, handle, &error);
1460 mono_error_set_pending_exception (&error);
1465 ICALL_EXPORT MonoType*
1466 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1468 return mono_class_get_type (klass);
1472 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1474 g_ptr_array_free (ptr_array, TRUE);
1478 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1484 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1487 char *res = mono_string_to_utf8_checked (s, &error);
1488 mono_error_set_pending_exception (&error);
1492 /* System.TypeCode */
1511 TYPECODE_STRING = 18
1514 ICALL_EXPORT guint32
1515 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1517 int t = type->type->type;
1519 if (type->type->byref)
1520 return TYPECODE_OBJECT;
1524 case MONO_TYPE_VOID:
1525 return TYPECODE_OBJECT;
1526 case MONO_TYPE_BOOLEAN:
1527 return TYPECODE_BOOLEAN;
1529 return TYPECODE_BYTE;
1531 return TYPECODE_SBYTE;
1533 return TYPECODE_UINT16;
1535 return TYPECODE_INT16;
1536 case MONO_TYPE_CHAR:
1537 return TYPECODE_CHAR;
1541 return TYPECODE_OBJECT;
1543 return TYPECODE_UINT32;
1545 return TYPECODE_INT32;
1547 return TYPECODE_UINT64;
1549 return TYPECODE_INT64;
1551 return TYPECODE_SINGLE;
1553 return TYPECODE_DOUBLE;
1554 case MONO_TYPE_VALUETYPE: {
1555 MonoClass *klass = type->type->data.klass;
1557 if (klass->enumtype) {
1558 t = mono_class_enum_basetype (klass)->type;
1560 } else if (mono_is_corlib_image (klass->image)) {
1561 if (strcmp (klass->name_space, "System") == 0) {
1562 if (strcmp (klass->name, "Decimal") == 0)
1563 return TYPECODE_DECIMAL;
1564 else if (strcmp (klass->name, "DateTime") == 0)
1565 return TYPECODE_DATETIME;
1568 return TYPECODE_OBJECT;
1570 case MONO_TYPE_STRING:
1571 return TYPECODE_STRING;
1572 case MONO_TYPE_SZARRAY:
1573 case MONO_TYPE_ARRAY:
1574 case MONO_TYPE_OBJECT:
1576 case MONO_TYPE_MVAR:
1577 case MONO_TYPE_TYPEDBYREF:
1578 return TYPECODE_OBJECT;
1579 case MONO_TYPE_CLASS:
1581 MonoClass *klass = type->type->data.klass;
1582 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1583 if (strcmp (klass->name, "DBNull") == 0)
1584 return TYPECODE_DBNULL;
1587 return TYPECODE_OBJECT;
1588 case MONO_TYPE_GENERICINST:
1589 return TYPECODE_OBJECT;
1591 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1597 mono_type_is_primitive (MonoType *type)
1599 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1600 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1604 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1606 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1607 return mono_class_enum_basetype (type->data.klass);
1608 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1609 return mono_class_enum_basetype (type->data.generic_class->container_class);
1613 ICALL_EXPORT guint32
1614 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1619 g_assert (type != NULL);
1621 klass = mono_class_from_mono_type (type->type);
1622 klassc = mono_class_from_mono_type (c->type);
1624 if (type->type->byref ^ c->type->byref)
1627 if (type->type->byref) {
1628 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1629 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1631 klass = mono_class_from_mono_type (t);
1632 klassc = mono_class_from_mono_type (ot);
1634 if (mono_type_is_primitive (t)) {
1635 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1636 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1637 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1638 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1639 return t->type == ot->type;
1641 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1644 if (klass->valuetype)
1645 return klass == klassc;
1646 return klass->valuetype == klassc->valuetype;
1649 return mono_class_is_assignable_from (klass, klassc);
1652 ICALL_EXPORT guint32
1653 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1656 MonoClass *klass = mono_class_from_mono_type (type->type);
1657 mono_class_init_checked (klass, &error);
1658 if (!is_ok (&error)) {
1659 mono_error_set_pending_exception (&error);
1662 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1663 mono_error_set_pending_exception (&error);
1667 ICALL_EXPORT guint32
1668 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1670 MonoClass *klass = mono_class_from_mono_type (type->type);
1671 return klass->flags;
1674 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1675 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1678 MonoClass *klass = field->field->parent;
1679 MonoMarshalType *info;
1683 if (klass->generic_container ||
1684 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1687 ftype = mono_field_get_type (field->field);
1688 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1691 info = mono_marshal_load_type_info (klass);
1693 for (i = 0; i < info->num_fields; ++i) {
1694 if (info->fields [i].field == field->field) {
1695 if (!info->fields [i].mspec)
1698 MonoReflectionMarshalAsAttribute* obj;
1699 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1700 if (!mono_error_ok (&error))
1701 mono_error_set_pending_exception (&error);
1710 ICALL_EXPORT MonoReflectionField*
1711 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1714 gboolean found = FALSE;
1720 klass = handle->parent;
1722 klass = mono_class_from_mono_type (type);
1724 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1727 /* The managed code will throw the exception */
1731 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1732 mono_error_set_pending_exception (&error);
1736 ICALL_EXPORT MonoReflectionEvent*
1737 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1745 klass = handle->parent;
1747 klass = mono_class_from_mono_type (type);
1749 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1751 /* Managed code will throw an exception */
1755 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1756 mono_error_set_pending_exception (&error);
1761 ICALL_EXPORT MonoReflectionProperty*
1762 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1770 klass = handle->parent;
1772 klass = mono_class_from_mono_type (type);
1774 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1776 /* Managed code will throw an exception */
1780 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1781 mono_error_set_pending_exception (&error);
1785 ICALL_EXPORT MonoArray*
1786 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1789 MonoType *type = mono_field_get_type_checked (field->field, &error);
1792 if (!mono_error_ok (&error)) {
1793 mono_error_set_pending_exception (&error);
1797 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1798 mono_error_set_pending_exception (&error);
1803 vell_icall_get_method_attributes (MonoMethod *method)
1805 return method->flags;
1809 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1812 MonoReflectionType *rt;
1813 MonoDomain *domain = mono_domain_get ();
1814 MonoMethodSignature* sig;
1816 sig = mono_method_signature_checked (method, &error);
1817 if (!mono_error_ok (&error)) {
1818 mono_error_set_pending_exception (&error);
1822 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1823 if (!mono_error_ok (&error)) {
1824 mono_error_set_pending_exception (&error);
1828 MONO_STRUCT_SETREF (info, parent, rt);
1830 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1831 if (!mono_error_ok (&error)) {
1832 mono_error_set_pending_exception (&error);
1836 MONO_STRUCT_SETREF (info, ret, rt);
1838 info->attrs = method->flags;
1839 info->implattrs = method->iflags;
1840 if (sig->call_convention == MONO_CALL_DEFAULT)
1841 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1843 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1848 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1851 ICALL_EXPORT MonoArray*
1852 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1855 MonoDomain *domain = mono_domain_get ();
1857 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1858 mono_error_set_pending_exception (&error);
1862 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1863 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1866 MonoDomain *domain = mono_domain_get ();
1867 MonoReflectionMarshalAsAttribute* res = NULL;
1868 MonoMarshalSpec **mspecs;
1871 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1872 mono_method_get_marshal_info (method, mspecs);
1875 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1876 if (!mono_error_ok (&error)) {
1877 mono_error_set_pending_exception (&error);
1882 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1884 mono_metadata_free_marshal_spec (mspecs [i]);
1891 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1893 MonoClass *parent = field->field->parent;
1894 if (!parent->size_inited)
1895 mono_class_init (parent);
1896 mono_class_setup_fields_locking (parent);
1898 return field->field->offset - sizeof (MonoObject);
1901 ICALL_EXPORT MonoReflectionType*
1902 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1905 MonoReflectionType *ret;
1908 parent = declaring? field->field->parent: field->klass;
1910 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1911 mono_error_set_pending_exception (&error);
1917 ICALL_EXPORT MonoObject *
1918 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1921 MonoClass *fklass = field->klass;
1922 MonoClassField *cf = field->field;
1923 MonoDomain *domain = mono_object_domain (field);
1925 if (fklass->image->assembly->ref_only) {
1926 mono_set_pending_exception (mono_get_exception_invalid_operation (
1927 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1931 if (mono_security_core_clr_enabled () &&
1932 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1933 mono_error_set_pending_exception (&error);
1937 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1938 mono_error_set_pending_exception (&error);
1943 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1946 MonoClassField *cf = field->field;
1950 if (field->klass->image->assembly->ref_only) {
1951 mono_set_pending_exception (mono_get_exception_invalid_operation (
1952 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1956 if (mono_security_core_clr_enabled () &&
1957 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1958 mono_error_set_pending_exception (&error);
1962 type = mono_field_get_type_checked (cf, &error);
1963 if (!mono_error_ok (&error)) {
1964 mono_error_set_pending_exception (&error);
1968 v = (gchar *) value;
1970 switch (type->type) {
1973 case MONO_TYPE_BOOLEAN:
1976 case MONO_TYPE_CHAR:
1985 case MONO_TYPE_VALUETYPE:
1988 v += sizeof (MonoObject);
1990 case MONO_TYPE_STRING:
1991 case MONO_TYPE_OBJECT:
1992 case MONO_TYPE_CLASS:
1993 case MONO_TYPE_ARRAY:
1994 case MONO_TYPE_SZARRAY:
1997 case MONO_TYPE_GENERICINST: {
1998 MonoGenericClass *gclass = type->data.generic_class;
1999 g_assert (!gclass->context.class_inst->is_open);
2001 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2002 MonoClass *nklass = mono_class_from_mono_type (type);
2003 MonoObject *nullable;
2006 * Convert the boxed vtype into a Nullable structure.
2007 * This is complicated by the fact that Nullables have
2008 * a variable structure.
2010 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2011 if (!mono_error_ok (&error)) {
2012 mono_error_set_pending_exception (&error);
2016 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2018 v = (gchar *)mono_object_unbox (nullable);
2021 if (gclass->container_class->valuetype && (v != NULL))
2022 v += sizeof (MonoObject);
2026 g_error ("type 0x%x not handled in "
2027 "ves_icall_FieldInfo_SetValueInternal", type->type);
2032 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2033 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2034 if (!is_ok (&error)) {
2035 mono_error_set_pending_exception (&error);
2038 if (!vtable->initialized) {
2039 if (!mono_runtime_class_init_full (vtable, &error)) {
2040 mono_error_set_pending_exception (&error);
2044 mono_field_static_set_value (vtable, cf, v);
2046 mono_field_set_value (obj, cf, v);
2051 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2060 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2061 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2065 if (MONO_TYPE_IS_REFERENCE (f->type))
2066 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2068 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2071 ICALL_EXPORT MonoObject *
2072 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2074 MonoObject *o = NULL;
2075 MonoClassField *field = rfield->field;
2077 MonoDomain *domain = mono_object_domain (rfield);
2079 MonoTypeEnum def_type;
2080 const char *def_value;
2084 mono_class_init (field->parent);
2086 t = mono_field_get_type_checked (field, &error);
2087 if (!mono_error_ok (&error)) {
2088 mono_error_set_pending_exception (&error);
2092 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2093 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2097 if (image_is_dynamic (field->parent->image)) {
2098 MonoClass *klass = field->parent;
2099 int fidx = field - klass->fields;
2101 g_assert (fidx >= 0 && fidx < klass->field.count);
2102 g_assert (klass->ext);
2103 g_assert (klass->ext->field_def_values);
2104 def_type = klass->ext->field_def_values [fidx].def_type;
2105 def_value = klass->ext->field_def_values [fidx].data;
2106 if (def_type == MONO_TYPE_END) {
2107 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2111 def_value = mono_class_get_field_default_value (field, &def_type);
2112 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2114 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2119 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2123 case MONO_TYPE_BOOLEAN:
2126 case MONO_TYPE_CHAR:
2134 case MONO_TYPE_R8: {
2137 /* boxed value type */
2138 t = g_new0 (MonoType, 1);
2140 klass = mono_class_from_mono_type (t);
2142 o = mono_object_new_checked (domain, klass, &error);
2143 if (!mono_error_ok (&error)) {
2144 mono_error_set_pending_exception (&error);
2147 v = ((gchar *) o) + sizeof (MonoObject);
2148 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2149 if (mono_error_set_pending_exception (&error))
2153 case MONO_TYPE_STRING:
2154 case MONO_TYPE_CLASS:
2155 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2156 if (mono_error_set_pending_exception (&error))
2160 g_assert_not_reached ();
2166 ICALL_EXPORT MonoReflectionType*
2167 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2170 MonoReflectionType *ret;
2173 type = mono_field_get_type_checked (ref_field->field, &error);
2174 if (!mono_error_ok (&error)) {
2175 mono_error_set_pending_exception (&error);
2179 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2180 if (!mono_error_ok (&error)) {
2181 mono_error_set_pending_exception (&error);
2188 /* From MonoProperty.cs */
2190 PInfo_Attributes = 1,
2191 PInfo_GetMethod = 1 << 1,
2192 PInfo_SetMethod = 1 << 2,
2193 PInfo_ReflectedType = 1 << 3,
2194 PInfo_DeclaringType = 1 << 4,
2199 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2202 MonoReflectionType *rt;
2203 MonoReflectionMethod *rm;
2204 MonoDomain *domain = mono_object_domain (property);
2205 const MonoProperty *pproperty = property->property;
2207 if ((req_info & PInfo_ReflectedType) != 0) {
2208 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2209 if (mono_error_set_pending_exception (&error))
2212 MONO_STRUCT_SETREF (info, parent, rt);
2214 if ((req_info & PInfo_DeclaringType) != 0) {
2215 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2216 if (mono_error_set_pending_exception (&error))
2219 MONO_STRUCT_SETREF (info, declaring_type, rt);
2222 if ((req_info & PInfo_Name) != 0)
2223 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2225 if ((req_info & PInfo_Attributes) != 0)
2226 info->attrs = pproperty->attrs;
2228 if ((req_info & PInfo_GetMethod) != 0) {
2229 if (pproperty->get &&
2230 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2231 pproperty->get->klass == property->klass)) {
2232 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2233 if (mono_error_set_pending_exception (&error))
2239 MONO_STRUCT_SETREF (info, get, rm);
2241 if ((req_info & PInfo_SetMethod) != 0) {
2242 if (pproperty->set &&
2243 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2244 pproperty->set->klass == property->klass)) {
2245 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2246 if (mono_error_set_pending_exception (&error))
2252 MONO_STRUCT_SETREF (info, set, rm);
2255 * There may be other methods defined for properties, though, it seems they are not exposed
2256 * in the reflection API
2261 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2264 MonoReflectionType *rt;
2265 MonoReflectionMethod *rm;
2266 MonoDomain *domain = mono_object_domain (event);
2268 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2269 if (mono_error_set_pending_exception (&error))
2272 MONO_STRUCT_SETREF (info, reflected_type, rt);
2274 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2275 if (mono_error_set_pending_exception (&error))
2278 MONO_STRUCT_SETREF (info, declaring_type, rt);
2280 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2281 info->attrs = event->event->attrs;
2283 if (event->event->add) {
2284 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2285 if (mono_error_set_pending_exception (&error))
2291 MONO_STRUCT_SETREF (info, add_method, rm);
2293 if (event->event->remove) {
2294 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2295 if (mono_error_set_pending_exception (&error))
2301 MONO_STRUCT_SETREF (info, remove_method, rm);
2303 if (event->event->raise) {
2304 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2305 if (mono_error_set_pending_exception (&error))
2311 MONO_STRUCT_SETREF (info, raise_method, rm);
2313 #ifndef MONO_SMALL_CONFIG
2314 if (event->event->other) {
2316 while (event->event->other [n])
2318 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2319 if (mono_error_set_pending_exception (&error))
2321 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2323 for (i = 0; i < n; i++) {
2324 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2325 if (mono_error_set_pending_exception (&error))
2327 mono_array_setref (info->other_methods, i, rm);
2334 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2339 mono_class_setup_interfaces (klass, error);
2340 if (!mono_error_ok (error))
2343 for (i = 0; i < klass->interface_count; i++) {
2344 ic = klass->interfaces [i];
2345 g_hash_table_insert (ifaces, ic, ic);
2347 collect_interfaces (ic, ifaces, error);
2348 if (!mono_error_ok (error))
2354 MonoArray *iface_array;
2355 MonoGenericContext *context;
2359 } FillIfaceArrayData;
2362 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2364 MonoReflectionType *rt;
2365 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2366 MonoClass *ic = (MonoClass *)key;
2367 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2369 if (!mono_error_ok (data->error))
2372 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2373 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2374 if (!mono_error_ok (data->error))
2378 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2379 if (!mono_error_ok (data->error))
2382 mono_array_setref (data->iface_array, data->next_idx++, rt);
2385 mono_metadata_free_type (inflated);
2389 get_interfaces_hash (gconstpointer v1)
2391 MonoClass *k = (MonoClass*)v1;
2393 return k->type_token;
2396 ICALL_EXPORT MonoArray*
2397 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2400 MonoClass *klass = mono_class_from_mono_type (type->type);
2402 FillIfaceArrayData data = { 0 };
2405 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2407 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2408 data.context = mono_class_get_context (klass);
2409 klass = klass->generic_class->container_class;
2412 for (parent = klass; parent; parent = parent->parent) {
2413 mono_class_setup_interfaces (parent, &error);
2414 if (!mono_error_ok (&error))
2416 collect_interfaces (parent, iface_hash, &error);
2417 if (!mono_error_ok (&error))
2421 data.error = &error;
2422 data.domain = mono_object_domain (type);
2424 len = g_hash_table_size (iface_hash);
2426 g_hash_table_destroy (iface_hash);
2427 if (!data.domain->empty_types) {
2428 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2429 if (!is_ok (&error))
2432 return data.domain->empty_types;
2435 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2436 if (!is_ok (&error))
2438 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2439 if (!mono_error_ok (&error))
2442 g_hash_table_destroy (iface_hash);
2443 return data.iface_array;
2446 g_hash_table_destroy (iface_hash);
2447 mono_error_set_pending_exception (&error);
2452 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2454 gboolean variance_used;
2455 MonoClass *klass = mono_class_from_mono_type (type->type);
2456 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2457 MonoReflectionMethod *member;
2460 int i = 0, len, ioffset;
2464 mono_class_init_checked (klass, &error);
2465 if (mono_error_set_pending_exception (&error))
2467 mono_class_init_checked (iclass, &error);
2468 if (mono_error_set_pending_exception (&error))
2471 mono_class_setup_vtable (klass);
2473 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2477 len = mono_class_num_methods (iclass);
2478 domain = mono_object_domain (type);
2479 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2480 if (mono_error_set_pending_exception (&error))
2482 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2483 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2484 if (mono_error_set_pending_exception (&error))
2486 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2488 while ((method = mono_class_get_methods (iclass, &iter))) {
2489 member = mono_method_get_object_checked (domain, method, iclass, &error);
2490 if (mono_error_set_pending_exception (&error))
2492 mono_array_setref (*methods, i, member);
2493 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2494 if (mono_error_set_pending_exception (&error))
2496 mono_array_setref (*targets, i, member);
2503 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2506 MonoClass *klass = mono_class_from_mono_type (type->type);
2508 mono_class_init_checked (klass, &error);
2509 if (mono_error_set_pending_exception (&error))
2512 if (image_is_dynamic (klass->image)) {
2513 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2514 *packing = tb->packing_size;
2515 *size = tb->class_size;
2517 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2521 ICALL_EXPORT MonoReflectionType*
2522 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2525 MonoReflectionType *ret;
2528 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2529 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2530 mono_error_set_pending_exception (&error);
2534 klass = mono_class_from_mono_type (type->type);
2535 mono_class_init_checked (klass, &error);
2536 if (mono_error_set_pending_exception (&error))
2540 // GetElementType should only return a type for:
2541 // Array Pointer PassedByRef
2542 if (type->type->byref)
2543 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2544 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2545 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2546 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2547 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2551 mono_error_set_pending_exception (&error);
2556 ICALL_EXPORT MonoReflectionType*
2557 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2560 MonoReflectionType *ret;
2562 if (type->type->byref)
2565 MonoClass *klass = mono_class_from_mono_type (type->type);
2569 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2570 mono_error_set_pending_exception (&error);
2575 ICALL_EXPORT MonoBoolean
2576 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2578 return type->type->type == MONO_TYPE_PTR;
2581 ICALL_EXPORT MonoBoolean
2582 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2584 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)));
2587 ICALL_EXPORT MonoBoolean
2588 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2590 return type->type->byref;
2593 ICALL_EXPORT MonoBoolean
2594 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2597 MonoClass *klass = mono_class_from_mono_type (type->type);
2598 mono_class_init_checked (klass, &error);
2599 if (mono_error_set_pending_exception (&error))
2602 return mono_class_is_com_object (klass);
2605 ICALL_EXPORT guint32
2606 ves_icall_reflection_get_token (MonoObject* obj)
2609 guint32 result = mono_reflection_get_token_checked (obj, &error);
2610 mono_error_set_pending_exception (&error);
2614 ICALL_EXPORT MonoReflectionModule*
2615 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2618 MonoReflectionModule *result = NULL;
2619 MonoClass *klass = mono_class_from_mono_type (type->type);
2620 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2621 mono_error_set_pending_exception (&error);
2625 ICALL_EXPORT MonoReflectionAssembly*
2626 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2629 MonoDomain *domain = mono_domain_get ();
2630 MonoClass *klass = mono_class_from_mono_type (type->type);
2631 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2632 mono_error_set_pending_exception (&error);
2636 ICALL_EXPORT MonoReflectionType*
2637 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2640 MonoReflectionType *ret;
2641 MonoDomain *domain = mono_domain_get ();
2644 if (type->type->byref)
2646 if (type->type->type == MONO_TYPE_VAR) {
2647 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2648 klass = param ? param->owner.klass : NULL;
2649 } else if (type->type->type == MONO_TYPE_MVAR) {
2650 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2651 klass = param ? param->owner.method->klass : NULL;
2653 klass = mono_class_from_mono_type (type->type)->nested_in;
2659 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2660 mono_error_set_pending_exception (&error);
2665 ICALL_EXPORT MonoStringHandle
2666 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2668 MonoDomain *domain = mono_domain_get ();
2669 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2670 MonoClass *klass = mono_class_from_mono_type (type);
2673 char *n = g_strdup_printf ("%s&", klass->name);
2674 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2680 return mono_string_new_handle (domain, klass->name, error);
2684 ICALL_EXPORT MonoStringHandle
2685 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2687 MonoDomain *domain = mono_domain_get ();
2688 MonoClass *klass = mono_class_from_mono_type_handle (type);
2690 while (klass->nested_in)
2691 klass = klass->nested_in;
2693 if (klass->name_space [0] == '\0')
2694 return NULL_HANDLE_STRING;
2696 return mono_string_new_handle (domain, klass->name_space, error);
2700 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2704 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2705 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2709 klass = mono_class_from_mono_type (type->type);
2715 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2717 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2720 ICALL_EXPORT MonoArray*
2721 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2724 MonoReflectionType *rt;
2726 MonoClass *klass, *pklass;
2727 MonoDomain *domain = mono_object_domain (type);
2730 klass = mono_class_from_mono_type (type->type);
2732 if (klass->generic_container) {
2733 MonoGenericContainer *container = klass->generic_container;
2734 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2735 if (mono_error_set_pending_exception (&error))
2737 for (i = 0; i < container->type_argc; ++i) {
2738 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2740 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2741 if (mono_error_set_pending_exception (&error))
2744 mono_array_setref (res, i, rt);
2746 } else if (klass->generic_class) {
2747 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2748 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2749 if (mono_error_set_pending_exception (&error))
2751 for (i = 0; i < inst->type_argc; ++i) {
2752 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2753 if (mono_error_set_pending_exception (&error))
2756 mono_array_setref (res, i, rt);
2764 ICALL_EXPORT gboolean
2765 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2769 if (!IS_MONOTYPE (type))
2772 if (type->type->byref)
2775 klass = mono_class_from_mono_type (type->type);
2776 return klass->generic_container != NULL;
2779 ICALL_EXPORT MonoReflectionType*
2780 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2783 MonoReflectionType *ret;
2786 if (type->type->byref)
2789 klass = mono_class_from_mono_type (type->type);
2791 if (klass->generic_container) {
2792 return type; /* check this one */
2794 if (klass->generic_class) {
2795 MonoClass *generic_class = klass->generic_class->container_class;
2798 tb = mono_class_get_ref_info (generic_class);
2800 if (generic_class->wastypebuilder && tb)
2801 return (MonoReflectionType *)tb;
2803 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2804 mono_error_set_pending_exception (&error);
2812 ICALL_EXPORT MonoReflectionType*
2813 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2816 MonoReflectionType *ret;
2818 MonoType *geninst, **types;
2821 g_assert (IS_MONOTYPE (type));
2822 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2823 if (mono_error_set_pending_exception (&error))
2826 count = mono_array_length (type_array);
2827 types = g_new0 (MonoType *, count);
2829 for (i = 0; i < count; i++) {
2830 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2831 types [i] = t->type;
2834 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2837 mono_error_set_pending_exception (&error);
2841 klass = mono_class_from_mono_type (geninst);
2843 /*we might inflate to the GTD*/
2844 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2845 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2849 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2850 mono_error_set_pending_exception (&error);
2855 ICALL_EXPORT gboolean
2856 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2860 if (!IS_MONOTYPE (type))
2863 if (type->type->byref)
2866 klass = mono_class_from_mono_type (type->type);
2867 return klass->generic_class != NULL || klass->generic_container != NULL;
2871 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2873 if (!IS_MONOTYPE (type))
2876 if (is_generic_parameter (type->type))
2877 return mono_type_get_generic_param_num (type->type);
2881 ICALL_EXPORT MonoGenericParamInfo *
2882 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2884 return mono_generic_param_info (type->type->data.generic_param);
2887 ICALL_EXPORT MonoBoolean
2888 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2890 return is_generic_parameter (type->type);
2893 ICALL_EXPORT MonoReflectionMethod*
2894 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2895 MonoReflectionMethod* generic)
2902 MonoReflectionMethod *ret = NULL;
2904 domain = ((MonoObject *)type)->vtable->domain;
2906 klass = mono_class_from_mono_type (type->type);
2907 mono_class_init_checked (klass, &error);
2908 if (mono_error_set_pending_exception (&error))
2912 while ((method = mono_class_get_methods (klass, &iter))) {
2913 if (method->token == generic->method->token) {
2914 ret = mono_method_get_object_checked (domain, method, klass, &error);
2915 if (mono_error_set_pending_exception (&error))
2923 ICALL_EXPORT MonoReflectionMethod *
2924 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2927 MonoType *type = ref_type->type;
2929 MonoReflectionMethod *ret = NULL;
2931 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2932 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2935 if (type->type == MONO_TYPE_VAR)
2938 method = mono_type_get_generic_param_owner (type)->owner.method;
2941 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2942 if (!mono_error_ok (&error))
2943 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2947 ICALL_EXPORT MonoBoolean
2948 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2950 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2954 ICALL_EXPORT MonoBoolean
2955 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2957 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2962 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2964 MonoDomain *domain = mono_domain_get ();
2965 MonoImage *image = method->method->klass->image;
2966 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2967 MonoTableInfo *tables = image->tables;
2968 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2969 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2970 guint32 im_cols [MONO_IMPLMAP_SIZE];
2971 guint32 scope_token;
2972 const char *import = NULL;
2973 const char *scope = NULL;
2975 if (image_is_dynamic (image)) {
2976 MonoReflectionMethodAux *method_aux =
2977 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2979 import = method_aux->dllentry;
2980 scope = method_aux->dll;
2983 if (!import || !scope) {
2984 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2989 if (piinfo->implmap_idx) {
2990 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2992 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2993 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2994 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2995 scope = mono_metadata_string_heap (image, scope_token);
2999 *flags = piinfo->piflags;
3000 *entry_point = mono_string_new (domain, import);
3001 *dll_name = mono_string_new (domain, scope);
3004 ICALL_EXPORT MonoReflectionMethod *
3005 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3007 MonoMethodInflated *imethod;
3009 MonoReflectionMethod *ret = NULL;
3012 if (method->method->is_generic)
3015 if (!method->method->is_inflated)
3018 imethod = (MonoMethodInflated *) method->method;
3020 result = imethod->declaring;
3021 /* Not a generic method. */
3022 if (!result->is_generic)
3025 if (image_is_dynamic (method->method->klass->image)) {
3026 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3027 MonoReflectionMethod *res;
3030 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3031 * the dynamic case as well ?
3033 mono_image_lock ((MonoImage*)image);
3034 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3035 mono_image_unlock ((MonoImage*)image);
3041 if (imethod->context.class_inst) {
3042 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3043 /*Generic methods gets the context of the GTD.*/
3044 if (mono_class_get_context (klass)) {
3045 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3046 if (!mono_error_ok (&error))
3051 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3053 if (!mono_error_ok (&error))
3054 mono_error_set_pending_exception (&error);
3058 ICALL_EXPORT gboolean
3059 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3061 return mono_method_signature (method->method)->generic_param_count != 0;
3064 ICALL_EXPORT gboolean
3065 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3067 return method->method->is_generic;
3070 ICALL_EXPORT MonoArray*
3071 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3074 MonoReflectionType *rt;
3079 domain = mono_object_domain (method);
3081 if (method->method->is_inflated) {
3082 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3085 count = inst->type_argc;
3086 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3087 if (mono_error_set_pending_exception (&error))
3090 for (i = 0; i < count; i++) {
3091 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3092 if (mono_error_set_pending_exception (&error))
3095 mono_array_setref (res, i, rt);
3102 count = mono_method_signature (method->method)->generic_param_count;
3103 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3104 if (mono_error_set_pending_exception (&error))
3107 for (i = 0; i < count; i++) {
3108 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3109 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3110 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3112 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3113 if (mono_error_set_pending_exception (&error))
3116 mono_array_setref (res, i, rt);
3122 ICALL_EXPORT MonoObject *
3123 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3127 * Invoke from reflection is supposed to always be a virtual call (the API
3128 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3129 * greater flexibility.
3131 MonoMethod *m = method->method;
3132 MonoMethodSignature *sig = mono_method_signature (m);
3135 void *obj = this_arg;
3139 if (mono_security_core_clr_enabled () &&
3140 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3141 mono_error_set_pending_exception (&error);
3145 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3146 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3147 mono_error_cleanup (&error); /* FIXME does this make sense? */
3148 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3153 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3154 if (!is_ok (&error)) {
3155 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3158 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3159 char *target_name = mono_type_get_full_name (m->klass);
3160 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3161 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3163 g_free (target_name);
3167 m = mono_object_get_virtual_method (this_arg, m);
3168 /* must pass the pointer to the value for valuetype methods */
3169 if (m->klass->valuetype)
3170 obj = mono_object_unbox (this_arg);
3171 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3172 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3177 if (sig->ret->byref) {
3178 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"));
3182 pcount = params? mono_array_length (params): 0;
3183 if (pcount != sig->param_count) {
3184 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3188 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3189 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."));
3193 image = m->klass->image;
3194 if (image->assembly->ref_only) {
3195 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."));
3199 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3200 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3204 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3208 intptr_t *lower_bounds;
3209 pcount = mono_array_length (params);
3210 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3211 /* Note: the synthetized array .ctors have int32 as argument type */
3212 for (i = 0; i < pcount; ++i)
3213 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3215 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3216 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3217 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3218 if (!mono_error_ok (&error)) {
3219 mono_error_set_pending_exception (&error);
3223 for (i = 0; i < mono_array_length (arr); ++i) {
3224 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3225 if (!mono_error_ok (&error)) {
3226 mono_error_set_pending_exception (&error);
3229 mono_array_setref_fast (arr, i, subarray);
3231 return (MonoObject*)arr;
3234 if (m->klass->rank == pcount) {
3235 /* Only lengths provided. */
3236 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3237 if (!mono_error_ok (&error)) {
3238 mono_error_set_pending_exception (&error);
3242 return (MonoObject*)arr;
3244 g_assert (pcount == (m->klass->rank * 2));
3245 /* The arguments are lower-bound-length pairs */
3246 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3248 for (i = 0; i < pcount / 2; ++i) {
3249 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3250 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3253 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3254 if (!mono_error_ok (&error)) {
3255 mono_error_set_pending_exception (&error);
3259 return (MonoObject*)arr;
3262 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3263 mono_error_set_pending_exception (&error);
3267 #ifndef DISABLE_REMOTING
3268 ICALL_EXPORT MonoObject *
3269 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3272 MonoDomain *domain = mono_object_domain (method);
3273 MonoMethod *m = method->method;
3274 MonoMethodSignature *sig = mono_method_signature (m);
3275 MonoArray *out_args;
3277 int i, j, outarg_count = 0;
3279 if (m->klass == mono_defaults.object_class) {
3280 if (!strcmp (m->name, "FieldGetter")) {
3281 MonoClass *k = this_arg->vtable->klass;
3285 /* If this is a proxy, then it must be a CBO */
3286 if (k == mono_defaults.transparent_proxy_class) {
3287 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3288 this_arg = tp->rp->unwrapped_server;
3289 g_assert (this_arg);
3290 k = this_arg->vtable->klass;
3293 name = mono_array_get (params, MonoString *, 1);
3294 str = mono_string_to_utf8_checked (name, &error);
3295 if (mono_error_set_pending_exception (&error))
3299 MonoClassField* field = mono_class_get_field_from_name (k, str);
3302 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3303 if (field_klass->valuetype) {
3304 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3305 if (mono_error_set_pending_exception (&error))
3308 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3310 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3311 if (mono_error_set_pending_exception (&error))
3313 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3314 mono_array_setref (out_args, 0, result);
3321 g_assert_not_reached ();
3323 } else if (!strcmp (m->name, "FieldSetter")) {
3324 MonoClass *k = this_arg->vtable->klass;
3330 /* If this is a proxy, then it must be a CBO */
3331 if (k == mono_defaults.transparent_proxy_class) {
3332 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3333 this_arg = tp->rp->unwrapped_server;
3334 g_assert (this_arg);
3335 k = this_arg->vtable->klass;
3338 name = mono_array_get (params, MonoString *, 1);
3339 str = mono_string_to_utf8_checked (name, &error);
3340 if (mono_error_set_pending_exception (&error))
3344 MonoClassField* field = mono_class_get_field_from_name (k, str);
3347 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3348 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3350 if (field_klass->valuetype) {
3351 size = mono_type_size (field->type, &align);
3352 g_assert (size == mono_class_value_size (field_klass, NULL));
3353 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3355 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3358 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3359 if (mono_error_set_pending_exception (&error))
3361 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3370 g_assert_not_reached ();
3375 for (i = 0; i < mono_array_length (params); i++) {
3376 if (sig->params [i]->byref)
3380 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3381 if (mono_error_set_pending_exception (&error))
3384 /* handle constructors only for objects already allocated */
3385 if (!strcmp (method->method->name, ".ctor"))
3386 g_assert (this_arg);
3388 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3389 g_assert (!method->method->klass->valuetype);
3390 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3391 if (mono_error_set_pending_exception (&error))
3394 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3395 if (sig->params [i]->byref) {
3397 arg = mono_array_get (params, gpointer, i);
3398 mono_array_setref (out_args, j, arg);
3403 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3410 read_enum_value (const char *mem, int type)
3413 case MONO_TYPE_BOOLEAN:
3415 return *(guint8*)mem;
3417 return *(gint8*)mem;
3418 case MONO_TYPE_CHAR:
3420 return read16 (mem);
3422 return (gint16) read16 (mem);
3424 return read32 (mem);
3426 return (gint32) read32 (mem);
3429 return read64 (mem);
3431 g_assert_not_reached ();
3437 write_enum_value (char *mem, int type, guint64 value)
3441 case MONO_TYPE_I1: {
3442 guint8 *p = (guint8*)mem;
3448 case MONO_TYPE_CHAR: {
3449 guint16 *p = (guint16 *)mem;
3454 case MONO_TYPE_I4: {
3455 guint32 *p = (guint32 *)mem;
3460 case MONO_TYPE_I8: {
3461 guint64 *p = (guint64 *)mem;
3466 g_assert_not_reached ();
3471 ICALL_EXPORT MonoObject *
3472 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3480 domain = mono_object_domain (enumType);
3481 enumc = mono_class_from_mono_type (enumType->type);
3483 mono_class_init_checked (enumc, &error);
3484 if (mono_error_set_pending_exception (&error))
3487 etype = mono_class_enum_basetype (enumc);
3489 res = mono_object_new_checked (domain, enumc, &error);
3490 if (mono_error_set_pending_exception (&error))
3492 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3497 ICALL_EXPORT MonoBoolean
3498 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3500 int size = mono_class_value_size (a->vtable->klass, NULL);
3501 guint64 a_val = 0, b_val = 0;
3503 memcpy (&a_val, mono_object_unbox (a), size);
3504 memcpy (&b_val, mono_object_unbox (b), size);
3506 return (a_val & b_val) == b_val;
3509 ICALL_EXPORT MonoObject *
3510 ves_icall_System_Enum_get_value (MonoObject *eobj)
3522 g_assert (eobj->vtable->klass->enumtype);
3524 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3525 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3526 if (mono_error_set_pending_exception (&error))
3528 dst = (char *)res + sizeof (MonoObject);
3529 src = (char *)eobj + sizeof (MonoObject);
3530 size = mono_class_value_size (enumc, NULL);
3532 memcpy (dst, src, size);
3537 ICALL_EXPORT MonoReflectionType *
3538 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3541 MonoReflectionType *ret;
3545 klass = mono_class_from_mono_type (type->type);
3546 mono_class_init_checked (klass, &error);
3547 if (mono_error_set_pending_exception (&error))
3550 etype = mono_class_enum_basetype (klass);
3552 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3556 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3557 mono_error_set_pending_exception (&error);
3563 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3565 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3566 gpointer odata = (char *)other + sizeof (MonoObject);
3567 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3568 g_assert (basetype);
3573 if (eobj->vtable->klass != other->vtable->klass)
3576 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3577 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3578 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3581 return me > other ? 1 : -1; \
3584 switch (basetype->type) {
3586 COMPARE_ENUM_VALUES (guint8);
3588 COMPARE_ENUM_VALUES (gint8);
3589 case MONO_TYPE_CHAR:
3591 COMPARE_ENUM_VALUES (guint16);
3593 COMPARE_ENUM_VALUES (gint16);
3595 COMPARE_ENUM_VALUES (guint32);
3597 COMPARE_ENUM_VALUES (gint32);
3599 COMPARE_ENUM_VALUES (guint64);
3601 COMPARE_ENUM_VALUES (gint64);
3605 #undef COMPARE_ENUM_VALUES
3606 /* indicates that the enum was of an unsupported unerlying type */
3611 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3613 gpointer data = (char *)eobj + sizeof (MonoObject);
3614 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3615 g_assert (basetype);
3617 switch (basetype->type) {
3618 case MONO_TYPE_I1: {
3619 gint8 value = *((gint8*)data);
3620 return ((int)value ^ (int)value << 8);
3623 return *((guint8*)data);
3624 case MONO_TYPE_CHAR:
3626 return *((guint16*)data);
3628 case MONO_TYPE_I2: {
3629 gint16 value = *((gint16*)data);
3630 return ((int)(guint16)value | (((int)value) << 16));
3633 return *((guint32*)data);
3635 return *((gint32*)data);
3637 case MONO_TYPE_I8: {
3638 gint64 value = *((gint64*)data);
3639 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3642 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3647 ICALL_EXPORT MonoBoolean
3648 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3651 MonoDomain *domain = mono_object_domain (type);
3652 MonoClass *enumc = mono_class_from_mono_type (type->type);
3653 guint j = 0, nvalues;
3655 MonoClassField *field;
3657 guint64 field_value, previous_value = 0;
3658 gboolean sorted = TRUE;
3660 mono_class_init_checked (enumc, &error);
3661 if (mono_error_set_pending_exception (&error))
3665 if (!enumc->enumtype) {
3666 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3670 base_type = mono_class_enum_basetype (enumc)->type;
3672 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3673 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3674 if (mono_error_set_pending_exception (&error))
3676 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3677 if (mono_error_set_pending_exception (&error))
3681 while ((field = mono_class_get_fields (enumc, &iter))) {
3683 MonoTypeEnum def_type;
3685 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3687 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3689 if (mono_field_is_deleted (field))
3691 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3693 p = mono_class_get_field_default_value (field, &def_type);
3694 /* len = */ mono_metadata_decode_blob_size (p, &p);
3696 field_value = read_enum_value (p, base_type);
3697 mono_array_set (*values, guint64, j, field_value);
3699 if (previous_value > field_value)
3702 previous_value = field_value;
3710 BFLAGS_IgnoreCase = 1,
3711 BFLAGS_DeclaredOnly = 2,
3712 BFLAGS_Instance = 4,
3714 BFLAGS_Public = 0x10,
3715 BFLAGS_NonPublic = 0x20,
3716 BFLAGS_FlattenHierarchy = 0x40,
3717 BFLAGS_InvokeMethod = 0x100,
3718 BFLAGS_CreateInstance = 0x200,
3719 BFLAGS_GetField = 0x400,
3720 BFLAGS_SetField = 0x800,
3721 BFLAGS_GetProperty = 0x1000,
3722 BFLAGS_SetProperty = 0x2000,
3723 BFLAGS_ExactBinding = 0x10000,
3724 BFLAGS_SuppressChangeType = 0x20000,
3725 BFLAGS_OptionalParamBinding = 0x40000
3728 ICALL_EXPORT GPtrArray*
3729 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3732 MonoClass *startklass, *klass;
3735 int (*compare_func) (const char *s1, const char *s2) = NULL;
3736 MonoClassField *field;
3738 if (type->type->byref) {
3739 return g_ptr_array_new ();
3742 mono_error_init (&error);
3744 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3746 klass = startklass = mono_class_from_mono_type (type->type);
3748 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3751 if (mono_class_has_failure (klass)) {
3752 mono_error_set_for_class_failure (&error, klass);
3757 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3758 guint32 flags = mono_field_get_flags (field);
3760 if (mono_field_is_deleted_with_flags (field, flags))
3762 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3763 if (bflags & BFLAGS_Public)
3765 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3766 if (bflags & BFLAGS_NonPublic) {
3773 if (flags & FIELD_ATTRIBUTE_STATIC) {
3774 if (bflags & BFLAGS_Static)
3775 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3778 if (bflags & BFLAGS_Instance)
3785 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3788 g_ptr_array_add (ptr_array, field);
3790 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3796 g_ptr_array_free (ptr_array, TRUE);
3797 mono_error_set_pending_exception (&error);
3802 method_nonpublic (MonoMethod* method, gboolean start_klass)
3804 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3805 case METHOD_ATTRIBUTE_ASSEM:
3806 return (start_klass || mono_defaults.generic_ilist_class);
3807 case METHOD_ATTRIBUTE_PRIVATE:
3809 case METHOD_ATTRIBUTE_PUBLIC:
3817 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3820 MonoClass *startklass;
3824 /*FIXME, use MonoBitSet*/
3825 guint32 method_slots_default [8];
3826 guint32 *method_slots = NULL;
3827 int (*compare_func) (const char *s1, const char *s2) = NULL;
3829 array = g_ptr_array_new ();
3831 mono_error_init (error);
3834 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3836 /* An optimization for calls made from Delegate:CreateDelegate () */
3837 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3838 method = mono_get_delegate_invoke (klass);
3841 g_ptr_array_add (array, method);
3845 mono_class_setup_methods (klass);
3846 mono_class_setup_vtable (klass);
3847 if (mono_class_has_failure (klass))
3850 if (is_generic_parameter (&klass->byval_arg))
3851 nslots = mono_class_get_vtable_size (klass->parent);
3853 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3854 if (nslots >= sizeof (method_slots_default) * 8) {
3855 method_slots = g_new0 (guint32, nslots / 32 + 1);
3857 method_slots = method_slots_default;
3858 memset (method_slots, 0, sizeof (method_slots_default));
3861 mono_class_setup_methods (klass);
3862 mono_class_setup_vtable (klass);
3863 if (mono_class_has_failure (klass))
3867 while ((method = mono_class_get_methods (klass, &iter))) {
3869 if (method->slot != -1) {
3870 g_assert (method->slot < nslots);
3871 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3873 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3874 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3877 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3879 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3880 if (bflags & BFLAGS_Public)
3882 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3888 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3889 if (bflags & BFLAGS_Static)
3890 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3893 if (bflags & BFLAGS_Instance)
3901 if (compare_func (name, method->name))
3906 g_ptr_array_add (array, method);
3908 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3910 if (method_slots != method_slots_default)
3911 g_free (method_slots);
3916 if (method_slots != method_slots_default)
3917 g_free (method_slots);
3918 g_ptr_array_free (array, TRUE);
3920 g_assert (mono_class_has_failure (klass));
3921 mono_error_set_for_class_failure (error, klass);
3925 ICALL_EXPORT GPtrArray*
3926 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3929 GPtrArray *method_array;
3932 klass = mono_class_from_mono_type (type->type);
3933 if (type->type->byref) {
3934 return g_ptr_array_new ();
3937 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3938 mono_error_set_pending_exception (&error);
3939 return method_array;
3942 ICALL_EXPORT GPtrArray*
3943 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3945 MonoClass *startklass, *klass;
3948 gpointer iter = NULL;
3949 GPtrArray *res_array;
3952 if (type->type->byref) {
3953 return g_ptr_array_new ();
3956 klass = startklass = mono_class_from_mono_type (type->type);
3958 mono_class_setup_methods (klass);
3959 if (mono_class_has_failure (klass)) {
3960 mono_error_init (&error);
3961 mono_error_set_for_class_failure (&error, klass);
3962 mono_error_set_pending_exception (&error);
3966 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3969 while ((method = mono_class_get_methods (klass, &iter))) {
3971 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3973 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3974 if (bflags & BFLAGS_Public)
3977 if (bflags & BFLAGS_NonPublic)
3983 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3984 if (bflags & BFLAGS_Static)
3985 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3988 if (bflags & BFLAGS_Instance)
3994 g_ptr_array_add (res_array, method);
4001 property_hash (gconstpointer data)
4003 MonoProperty *prop = (MonoProperty*)data;
4005 return g_str_hash (prop->name);
4009 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4011 if (method1->slot != -1 && method1->slot == method2->slot)
4014 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4015 if (method1->is_inflated)
4016 method1 = ((MonoMethodInflated*) method1)->declaring;
4017 if (method2->is_inflated)
4018 method2 = ((MonoMethodInflated*) method2)->declaring;
4021 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4025 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4027 // Properties are hide-by-name-and-signature
4028 if (!g_str_equal (prop1->name, prop2->name))
4031 /* If we see a property in a generic method, we want to
4032 compare the generic signatures, not the inflated signatures
4033 because we might conflate two properties that were
4037 public T this[T t] { getter { return t; } } // method 1
4038 public U this[U u] { getter { return u; } } // method 2
4041 If we see int Foo<int,int>::Item[int] we need to know if
4042 the indexer came from method 1 or from method 2, and we
4043 shouldn't conflate them. (Bugzilla 36283)
4045 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4048 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4055 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4060 return method_nonpublic (accessor, start_klass);
4063 ICALL_EXPORT GPtrArray*
4064 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4067 MonoClass *startklass, *klass;
4072 int (*compare_func) (const char *s1, const char *s2) = NULL;
4074 GHashTable *properties = NULL;
4075 GPtrArray *res_array;
4077 if (type->type->byref) {
4078 return g_ptr_array_new ();
4081 mono_error_init (&error);
4083 klass = startklass = mono_class_from_mono_type (type->type);
4085 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4087 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4089 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4091 mono_class_setup_methods (klass);
4092 mono_class_setup_vtable (klass);
4093 if (mono_class_has_failure (klass)) {
4094 mono_error_set_for_class_failure (&error, klass);
4099 while ((prop = mono_class_get_properties (klass, &iter))) {
4105 flags = method->flags;
4108 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4109 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4110 if (bflags & BFLAGS_Public)
4112 } else if (bflags & BFLAGS_NonPublic) {
4113 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4114 property_accessor_nonpublic(prop->set, startklass == klass)) {
4121 if (flags & METHOD_ATTRIBUTE_STATIC) {
4122 if (bflags & BFLAGS_Static)
4123 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4126 if (bflags & BFLAGS_Instance)
4134 if (propname != NULL && compare_func (propname, prop->name))
4137 if (g_hash_table_lookup (properties, prop))
4140 g_ptr_array_add (res_array, prop);
4142 g_hash_table_insert (properties, prop, prop);
4144 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4147 g_hash_table_destroy (properties);
4154 g_hash_table_destroy (properties);
4155 g_ptr_array_free (res_array, TRUE);
4157 mono_error_set_pending_exception (&error);
4163 event_hash (gconstpointer data)
4165 MonoEvent *event = (MonoEvent*)data;
4167 return g_str_hash (event->name);
4171 event_equal (MonoEvent *event1, MonoEvent *event2)
4173 // Events are hide-by-name
4174 return g_str_equal (event1->name, event2->name);
4177 ICALL_EXPORT GPtrArray*
4178 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4181 MonoClass *startklass, *klass;
4186 int (*compare_func) (const char *s1, const char *s2) = NULL;
4187 GHashTable *events = NULL;
4188 GPtrArray *res_array;
4190 if (type->type->byref) {
4191 return g_ptr_array_new ();
4194 mono_error_init (&error);
4196 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4198 res_array = g_ptr_array_sized_new (4);
4200 klass = startklass = mono_class_from_mono_type (type->type);
4202 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4204 mono_class_setup_methods (klass);
4205 mono_class_setup_vtable (klass);
4206 if (mono_class_has_failure (klass)) {
4207 mono_error_set_for_class_failure (&error, klass);
4212 while ((event = mono_class_get_events (klass, &iter))) {
4214 method = event->add;
4216 method = event->remove;
4218 method = event->raise;
4220 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4221 if (bflags & BFLAGS_Public)
4223 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4224 if (bflags & BFLAGS_NonPublic)
4229 if (bflags & BFLAGS_NonPublic)
4235 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4236 if (bflags & BFLAGS_Static)
4237 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4240 if (bflags & BFLAGS_Instance)
4245 if (bflags & BFLAGS_Instance)
4250 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4253 if (g_hash_table_lookup (events, event))
4256 g_ptr_array_add (res_array, event);
4258 g_hash_table_insert (events, event, event);
4260 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4263 g_hash_table_destroy (events);
4269 g_hash_table_destroy (events);
4271 g_ptr_array_free (res_array, TRUE);
4273 mono_error_set_pending_exception (&error);
4277 ICALL_EXPORT GPtrArray *
4278 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4284 GPtrArray *res_array;
4286 if (type->type->byref) {
4287 return g_ptr_array_new ();
4290 klass = mono_class_from_mono_type (type->type);
4293 * If a nested type is generic, return its generic type definition.
4294 * Note that this means that the return value is essentially the set
4295 * of nested types of the generic type definition of @klass.
4297 * A note in MSDN claims that a generic type definition can have
4298 * nested types that aren't generic. In any case, the container of that
4299 * nested type would be the generic type definition.
4301 if (klass->generic_class)
4302 klass = klass->generic_class->container_class;
4304 res_array = g_ptr_array_new ();
4307 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4309 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4310 if (bflags & BFLAGS_Public)
4313 if (bflags & BFLAGS_NonPublic)
4319 if (str != NULL && strcmp (nested->name, str))
4322 g_ptr_array_add (res_array, &nested->byval_arg);
4328 ICALL_EXPORT MonoReflectionType*
4329 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4332 MonoReflectionType *ret;
4334 MonoType *type = NULL;
4335 MonoTypeNameParse info;
4336 gboolean type_resolve;
4338 /* On MS.NET, this does not fire a TypeResolve event */
4339 type_resolve = TRUE;
4340 str = mono_string_to_utf8_checked (name, &error);
4341 if (mono_error_set_pending_exception (&error))
4343 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4344 if (!mono_reflection_parse_type (str, &info)) {
4346 mono_reflection_free_type_info (&info);
4348 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4351 /*g_print ("failed parse\n");*/
4355 if (info.assembly.name) {
4357 mono_reflection_free_type_info (&info);
4359 /* 1.0 and 2.0 throw different exceptions */
4360 if (mono_defaults.generic_ilist_class)
4361 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4363 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4369 if (module != NULL) {
4370 if (module->image) {
4371 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4372 if (!is_ok (&error)) {
4374 mono_reflection_free_type_info (&info);
4375 mono_error_set_pending_exception (&error);
4382 if (assembly_is_dynamic (assembly->assembly)) {
4383 /* Enumerate all modules */
4384 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4388 if (abuilder->modules) {
4389 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4390 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4391 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4392 if (!is_ok (&error)) {
4394 mono_reflection_free_type_info (&info);
4395 mono_error_set_pending_exception (&error);
4403 if (!type && abuilder->loaded_modules) {
4404 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4405 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4406 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4407 if (!is_ok (&error)) {
4409 mono_reflection_free_type_info (&info);
4410 mono_error_set_pending_exception (&error);
4419 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4420 if (!is_ok (&error)) {
4422 mono_reflection_free_type_info (&info);
4423 mono_error_set_pending_exception (&error);
4428 mono_reflection_free_type_info (&info);
4430 MonoException *e = NULL;
4433 e = mono_get_exception_type_load (name, NULL);
4436 mono_set_pending_exception (e);
4440 if (type->type == MONO_TYPE_CLASS) {
4441 MonoClass *klass = mono_type_get_class (type);
4443 /* need to report exceptions ? */
4444 if (throwOnError && mono_class_has_failure (klass)) {
4445 /* report SecurityException (or others) that occured when loading the assembly */
4446 mono_error_set_for_class_failure (&error, klass);
4447 mono_error_set_pending_exception (&error);
4452 /* g_print ("got it\n"); */
4453 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4454 mono_error_set_pending_exception (&error);
4460 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4463 gchar *shadow_ini_file;
4466 /* Check for shadow-copied assembly */
4467 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4468 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4470 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4471 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4477 g_free (shadow_ini_file);
4478 if (content != NULL) {
4481 *filename = content;
4488 ICALL_EXPORT MonoString *
4489 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4491 MonoDomain *domain = mono_object_domain (assembly);
4492 MonoAssembly *mass = assembly->assembly;
4493 MonoString *res = NULL;
4498 if (g_path_is_absolute (mass->image->name)) {
4499 absolute = g_strdup (mass->image->name);
4500 dirname = g_path_get_dirname (absolute);
4502 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4503 dirname = g_strdup (mass->basedir);
4506 replace_shadow_path (domain, dirname, &absolute);
4511 for (i = strlen (absolute) - 1; i >= 0; i--)
4512 if (absolute [i] == '\\')
4517 uri = g_filename_to_uri (absolute, NULL, NULL);
4519 const char *prepend = "file://";
4521 if (*absolute == '/' && *(absolute + 1) == '/') {
4524 prepend = "file:///";
4527 uri = g_strconcat (prepend, absolute, NULL);
4531 res = mono_string_new (domain, uri);
4538 ICALL_EXPORT MonoBoolean
4539 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4541 MonoAssembly *mass = assembly->assembly;
4543 return mass->in_gac;
4546 ICALL_EXPORT MonoReflectionAssembly*
4547 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4552 MonoImageOpenStatus status;
4553 MonoReflectionAssembly* result = NULL;
4555 name = mono_string_to_utf8_checked (mname, &error);
4556 if (mono_error_set_pending_exception (&error))
4558 res = mono_assembly_load_with_partial_name (name, &status);
4564 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4566 mono_error_set_pending_exception (&error);
4570 ICALL_EXPORT MonoStringHandle
4571 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4573 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4574 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4575 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4578 ICALL_EXPORT MonoBoolean
4579 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4581 return assembly->assembly->ref_only;
4584 ICALL_EXPORT MonoStringHandle
4585 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4587 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4588 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4590 return mono_string_new_handle (domain, assembly->image->version, error);
4593 ICALL_EXPORT MonoReflectionMethod*
4594 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4597 MonoReflectionMethod *res = NULL;
4600 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4604 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4605 if (!mono_error_ok (&error))
4608 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4611 if (!mono_error_ok (&error))
4612 mono_error_set_pending_exception (&error);
4616 ICALL_EXPORT MonoReflectionModule*
4617 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4620 MonoReflectionModule *result = NULL;
4621 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4622 if (!mono_error_ok (&error))
4623 mono_error_set_pending_exception (&error);
4627 ICALL_EXPORT MonoArray*
4628 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4631 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4632 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4633 if (mono_error_set_pending_exception (&error))
4638 for (i = 0; i < table->rows; ++i) {
4639 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4640 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4645 ICALL_EXPORT MonoStringHandle
4646 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4649 guint8 aotid_sum = 0;
4650 MonoDomain* domain = mono_domain_get ();
4652 if (!domain->entry_assembly || !domain->entry_assembly->image)
4655 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4657 for (i = 0; i < 16; ++i)
4658 aotid_sum |= (*aotid)[i];
4663 gchar *guid = mono_guid_to_string((guint8*) aotid);
4664 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4670 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4672 static MonoMethod *create_version = NULL;
4676 mono_error_init (error);
4679 if (!create_version) {
4680 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4681 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4682 g_assert (create_version);
4683 mono_method_desc_free (desc);
4689 args [3] = &revision;
4690 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4691 return_val_if_nok (error, NULL);
4693 mono_runtime_invoke_checked (create_version, result, args, error);
4694 return_val_if_nok (error, NULL);
4699 ICALL_EXPORT MonoArray*
4700 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4704 MonoDomain *domain = mono_object_domain (assembly);
4706 static MonoMethod *create_culture = NULL;
4707 MonoImage *image = assembly->assembly->image;
4711 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4714 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4715 if (mono_error_set_pending_exception (&error))
4719 if (count > 0 && !create_culture) {
4720 MonoMethodDesc *desc = mono_method_desc_new (
4721 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4722 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4723 g_assert (create_culture);
4724 mono_method_desc_free (desc);
4727 for (i = 0; i < count; i++) {
4728 MonoObject *version;
4729 MonoReflectionAssemblyName *aname;
4730 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4732 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4734 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4735 domain, mono_class_get_assembly_name_class (), &error);
4736 if (mono_error_set_pending_exception (&error))
4739 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4741 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4742 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4743 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4744 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4745 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4746 aname->versioncompat = 1; /* SameMachine (default) */
4747 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4749 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4750 if (mono_error_set_pending_exception (&error))
4753 MONO_OBJECT_SETREF (aname, version, version);
4755 if (create_culture) {
4757 MonoBoolean assembly_ref = 1;
4758 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4759 args [1] = &assembly_ref;
4761 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4762 if (mono_error_set_pending_exception (&error))
4765 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4768 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4769 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4770 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4772 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4773 /* public key token isn't copied - the class library will
4774 automatically generate it from the public key if required */
4775 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4776 if (mono_error_set_pending_exception (&error))
4779 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4780 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4782 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4783 if (mono_error_set_pending_exception (&error))
4786 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4787 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4790 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4791 if (mono_error_set_pending_exception (&error))
4794 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4797 /* note: this function doesn't return the codebase on purpose (i.e. it can
4798 be used under partial trust as path information isn't present). */
4800 mono_array_setref (result, i, aname);
4805 /* move this in some file in mono/util/ */
4807 g_concat_dir_and_file (const char *dir, const char *file)
4809 g_return_val_if_fail (dir != NULL, NULL);
4810 g_return_val_if_fail (file != NULL, NULL);
4813 * If the directory name doesn't have a / on the end, we need
4814 * to add one so we get a proper path to the file
4816 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4817 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4819 return g_strconcat (dir, file, NULL);
4823 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4826 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4828 guint32 cols [MONO_MANIFEST_SIZE];
4829 guint32 impl, file_idx;
4833 char *n = mono_string_to_utf8_checked (name, &error);
4834 if (mono_error_set_pending_exception (&error))
4837 for (i = 0; i < table->rows; ++i) {
4838 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4839 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4840 if (strcmp (val, n) == 0)
4844 if (i == table->rows)
4847 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4850 * this code should only be called after obtaining the
4851 * ResourceInfo and handling the other cases.
4853 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4854 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4856 module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
4857 if (mono_error_set_pending_exception (&error) || !module)
4861 module = assembly->assembly->image;
4864 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4865 if (mono_error_set_pending_exception (&error))
4867 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4869 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4872 ICALL_EXPORT gboolean
4873 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4876 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4878 guint32 cols [MONO_MANIFEST_SIZE];
4879 guint32 file_cols [MONO_FILE_SIZE];
4883 n = mono_string_to_utf8_checked (name, &error);
4884 if (mono_error_set_pending_exception (&error))
4886 for (i = 0; i < table->rows; ++i) {
4887 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4888 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4889 if (strcmp (val, n) == 0)
4893 if (i == table->rows)
4896 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4897 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4900 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4901 case MONO_IMPLEMENTATION_FILE:
4902 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4903 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4904 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4905 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4906 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4907 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4910 info->location = RESOURCE_LOCATION_EMBEDDED;
4913 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4914 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4915 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4916 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4917 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4918 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4920 mono_set_pending_exception (ex);
4923 MonoReflectionAssembly *assm_obj;
4924 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4926 mono_error_set_pending_exception (&error);
4929 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4931 /* Obtain info recursively */
4932 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4933 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4936 case MONO_IMPLEMENTATION_EXP_TYPE:
4937 g_assert_not_reached ();
4945 ICALL_EXPORT MonoObject*
4946 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4949 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4950 MonoArray *result = NULL;
4955 /* check hash if needed */
4957 n = mono_string_to_utf8_checked (name, &error);
4958 if (mono_error_set_pending_exception (&error))
4961 for (i = 0; i < table->rows; ++i) {
4962 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4963 if (strcmp (val, n) == 0) {
4966 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4967 fn = mono_string_new (mono_object_domain (assembly), n);
4969 return (MonoObject*)fn;
4977 for (i = 0; i < table->rows; ++i) {
4978 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4982 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4983 if (mono_error_set_pending_exception (&error))
4988 for (i = 0; i < table->rows; ++i) {
4989 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4990 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4991 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4992 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4997 return (MonoObject*)result;
5000 ICALL_EXPORT MonoArray*
5001 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5004 MonoDomain *domain = mono_domain_get();
5007 int i, j, file_count = 0;
5008 MonoImage **modules;
5009 guint32 module_count, real_module_count;
5010 MonoTableInfo *table;
5011 guint32 cols [MONO_FILE_SIZE];
5012 MonoImage *image = assembly->assembly->image;
5014 g_assert (image != NULL);
5015 g_assert (!assembly_is_dynamic (assembly->assembly));
5017 table = &image->tables [MONO_TABLE_FILE];
5018 file_count = table->rows;
5020 modules = image->modules;
5021 module_count = image->module_count;
5023 real_module_count = 0;
5024 for (i = 0; i < module_count; ++i)
5026 real_module_count ++;
5028 klass = mono_class_get_module_class ();
5029 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5030 if (mono_error_set_pending_exception (&error))
5033 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5034 if (mono_error_set_pending_exception (&error))
5037 mono_array_setref (res, 0, image_obj);
5039 for (i = 0; i < module_count; ++i)
5041 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5042 if (mono_error_set_pending_exception (&error))
5044 mono_array_setref (res, j, rm);
5048 for (i = 0; i < file_count; ++i, ++j) {
5049 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5050 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5051 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5052 if (mono_error_set_pending_exception (&error))
5054 mono_array_setref (res, j, rm);
5057 MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
5058 if (mono_error_set_pending_exception (&error))
5061 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5062 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5065 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5066 if (mono_error_set_pending_exception (&error))
5068 mono_array_setref (res, j, rm);
5075 ICALL_EXPORT MonoReflectionMethod*
5076 ves_icall_GetCurrentMethod (void)
5078 MonoReflectionMethod *res = NULL;
5081 MonoMethod *m = mono_method_get_last_managed ();
5084 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5088 while (m->is_inflated)
5089 m = ((MonoMethodInflated*)m)->declaring;
5091 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5092 mono_error_set_pending_exception (&error);
5098 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5101 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5104 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5105 //method is inflated, we should inflate it on the other class
5106 MonoGenericContext ctx;
5107 ctx.method_inst = inflated->context.method_inst;
5108 ctx.class_inst = inflated->context.class_inst;
5109 if (klass->generic_class)
5110 ctx.class_inst = klass->generic_class->context.class_inst;
5111 else if (klass->generic_container)
5112 ctx.class_inst = klass->generic_container->context.class_inst;
5113 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5114 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5118 mono_class_setup_methods (method->klass);
5119 if (mono_class_has_failure (method->klass))
5121 for (i = 0; i < method->klass->method.count; ++i) {
5122 if (method->klass->methods [i] == method) {
5127 mono_class_setup_methods (klass);
5128 if (mono_class_has_failure (klass))
5130 g_assert (offset >= 0 && offset < klass->method.count);
5131 return klass->methods [offset];
5134 ICALL_EXPORT MonoReflectionMethod*
5135 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5137 MonoReflectionMethod *res = NULL;
5140 if (type && generic_check) {
5141 klass = mono_class_from_mono_type (type);
5142 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5145 if (method->klass != klass) {
5146 method = mono_method_get_equivalent_method (method, klass);
5151 klass = mono_class_from_mono_type (type);
5153 klass = method->klass;
5154 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5155 mono_error_set_pending_exception (&error);
5159 ICALL_EXPORT MonoReflectionMethodBody*
5160 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5163 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5164 mono_error_set_pending_exception (&error);
5168 ICALL_EXPORT MonoReflectionAssembly*
5169 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5172 MonoReflectionAssembly *result;
5173 MonoMethod *dest = NULL;
5175 mono_stack_walk_no_il (get_executing, &dest);
5177 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5179 mono_error_set_pending_exception (&error);
5184 ICALL_EXPORT MonoReflectionAssembly*
5185 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5188 MonoReflectionAssembly *result;
5189 MonoDomain* domain = mono_domain_get ();
5191 if (!domain->entry_assembly)
5194 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5196 mono_error_set_pending_exception (&error);
5200 ICALL_EXPORT MonoReflectionAssembly*
5201 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5206 MonoReflectionAssembly *result;
5209 mono_stack_walk_no_il (get_executing, &dest);
5211 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5215 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5218 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5220 mono_error_set_pending_exception (&error);
5224 ICALL_EXPORT MonoStringHandle
5225 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5226 gboolean assembly_qualified, MonoError *error)
5228 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5229 MonoType *type = MONO_HANDLE_RAW (object)->type;
5230 MonoTypeNameFormat format;
5231 MonoStringHandle res;
5235 format = assembly_qualified ?
5236 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5237 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5239 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5241 name = mono_type_get_name_full (type, format);
5243 return NULL_HANDLE_STRING;
5245 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5247 return NULL_HANDLE_STRING;
5250 res = mono_string_new_handle (domain, name, error);
5257 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5260 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5262 mono_class_init_checked (klass, &error);
5263 mono_error_set_pending_exception (&error);
5264 return mono_security_core_clr_class_level (klass);
5268 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5270 MonoClassField *field = rfield->field;
5271 return mono_security_core_clr_field_level (field, TRUE);
5275 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5277 MonoMethod *method = rfield->method;
5278 return mono_security_core_clr_method_level (method, TRUE);
5282 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token, MonoError *error)
5284 static MonoMethod *create_culture = NULL;
5288 const char *pkey_ptr;
5290 MonoBoolean assembly_ref = 0;
5292 mono_error_init (error);
5294 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5295 aname->major = name->major;
5296 aname->minor = name->minor;
5297 aname->build = name->build;
5298 aname->flags = name->flags;
5299 aname->revision = name->revision;
5300 aname->hashalg = name->hash_alg;
5301 aname->versioncompat = 1; /* SameMachine (default) */
5302 aname->processor_architecture = name->arch;
5304 if (by_default_version) {
5305 MonoObject *version;
5307 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5308 return_if_nok (error);
5310 MONO_OBJECT_SETREF (aname, version, version);
5314 if (absolute != NULL && *absolute != '\0') {
5315 const gchar *prepend = "file://";
5318 codebase = g_strdup (absolute);
5323 for (i = strlen (codebase) - 1; i >= 0; i--)
5324 if (codebase [i] == '\\')
5327 if (*codebase == '/' && *(codebase + 1) == '/') {
5330 prepend = "file:///";
5334 result = g_strconcat (prepend, codebase, NULL);
5340 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5344 if (!create_culture) {
5345 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5346 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5347 g_assert (create_culture);
5348 mono_method_desc_free (desc);
5351 if (name->culture) {
5352 args [0] = mono_string_new (domain, name->culture);
5353 args [1] = &assembly_ref;
5355 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5356 return_if_nok (error);
5358 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5361 if (name->public_key) {
5362 pkey_ptr = (char*)name->public_key;
5363 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5365 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5366 return_if_nok (error);
5367 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5368 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5369 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5370 } else if (default_publickey) {
5371 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5372 return_if_nok (error);
5373 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5374 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5377 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5378 if (name->public_key_token [0]) {
5382 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5383 return_if_nok (error);
5385 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5386 p = mono_array_addr (keyToken, char, 0);
5388 for (i = 0, j = 0; i < 8; i++) {
5389 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5390 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5393 } else if (default_token) {
5394 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5395 return_if_nok (error);
5396 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5400 ICALL_EXPORT MonoString *
5401 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5403 MonoDomain *domain = mono_object_domain (assembly);
5404 MonoAssembly *mass = assembly->assembly;
5408 name = mono_stringify_assembly_name (&mass->aname);
5409 res = mono_string_new (domain, name);
5415 ICALL_EXPORT MonoAssemblyName *
5416 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5418 return &mass->aname;
5422 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5426 MonoImageOpenStatus status = MONO_IMAGE_OK;
5429 MonoAssemblyName name;
5432 filename = mono_string_to_utf8_checked (fname, &error);
5433 if (mono_error_set_pending_exception (&error))
5436 dirname = g_path_get_dirname (filename);
5437 replace_shadow_path (mono_domain_get (), dirname, &filename);
5440 image = mono_image_open (filename, &status);
5446 if (status == MONO_IMAGE_IMAGE_INVALID)
5447 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5449 exc = mono_get_exception_file_not_found2 (NULL, fname);
5450 mono_set_pending_exception (exc);
5454 res = mono_assembly_fill_assembly_name (image, &name);
5456 mono_image_close (image);
5458 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5462 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5463 mono_error_set_pending_exception (&error);
5465 mono_image_close (image);
5469 ICALL_EXPORT MonoBoolean
5470 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5471 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5473 MonoBoolean result = FALSE;
5474 MonoDeclSecurityEntry entry;
5476 /* SecurityAction.RequestMinimum */
5477 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5478 *minimum = entry.blob;
5479 *minLength = entry.size;
5482 /* SecurityAction.RequestOptional */
5483 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5484 *optional = entry.blob;
5485 *optLength = entry.size;
5488 /* SecurityAction.RequestRefuse */
5489 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5490 *refused = entry.blob;
5491 *refLength = entry.size;
5499 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5501 guint32 attrs, visibility;
5503 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5504 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5505 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5508 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5514 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5516 MonoReflectionType *rt;
5519 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5522 mono_error_init (error);
5524 /* we start the count from 1 because we skip the special type <Module> */
5527 for (i = 1; i < tdef->rows; ++i) {
5528 if (mono_module_type_is_visible (tdef, image, i + 1))
5532 count = tdef->rows - 1;
5534 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5535 return_val_if_nok (error, NULL);
5536 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5537 return_val_if_nok (error, NULL);
5539 for (i = 1; i < tdef->rows; ++i) {
5540 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5541 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5544 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5545 return_val_if_nok (error, NULL);
5547 mono_array_setref (res, count, rt);
5549 MonoException *ex = mono_error_convert_to_exception (error);
5550 mono_array_setref (*exceptions, count, ex);
5559 ICALL_EXPORT MonoArray*
5560 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5563 MonoArray *res = NULL;
5564 MonoArray *exceptions = NULL;
5565 MonoImage *image = NULL;
5566 MonoTableInfo *table = NULL;
5569 int i, len, ex_count;
5571 domain = mono_object_domain (assembly);
5573 g_assert (!assembly_is_dynamic (assembly->assembly));
5574 image = assembly->assembly->image;
5575 table = &image->tables [MONO_TABLE_FILE];
5576 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5577 if (mono_error_set_pending_exception (&error))
5580 /* Append data from all modules in the assembly */
5581 for (i = 0; i < table->rows; ++i) {
5582 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5583 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5584 if (mono_error_set_pending_exception (&error))
5590 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5591 if (mono_error_set_pending_exception (&error))
5595 /* Append the new types to the end of the array */
5596 if (mono_array_length (res2) > 0) {
5598 MonoArray *res3, *ex3;
5600 len1 = mono_array_length (res);
5601 len2 = mono_array_length (res2);
5603 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5604 if (mono_error_set_pending_exception (&error))
5606 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5607 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5610 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5611 if (mono_error_set_pending_exception (&error))
5613 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5614 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5621 /* the ReflectionTypeLoadException must have all the types (Types property),
5622 * NULL replacing types which throws an exception. The LoaderException must
5623 * contain all exceptions for NULL items.
5626 len = mono_array_length (res);
5629 for (i = 0; i < len; i++) {
5630 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5634 klass = mono_type_get_class (t->type);
5635 if ((klass != NULL) && mono_class_has_failure (klass)) {
5636 /* keep the class in the list */
5637 list = g_list_append (list, klass);
5638 /* and replace Type with NULL */
5639 mono_array_setref (res, i, NULL);
5646 if (list || ex_count) {
5648 MonoException *exc = NULL;
5649 MonoArray *exl = NULL;
5650 int j, length = g_list_length (list) + ex_count;
5652 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5653 if (mono_error_set_pending_exception (&error)) {
5657 /* Types for which mono_class_get_checked () succeeded */
5658 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5659 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5660 mono_array_setref (exl, i, exc);
5662 /* Types for which it don't */
5663 for (j = 0; j < mono_array_length (exceptions); ++j) {
5664 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5666 g_assert (i < length);
5667 mono_array_setref (exl, i, exc);
5674 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5675 if (!is_ok (&error)) {
5676 mono_error_set_pending_exception (&error);
5679 mono_set_pending_exception (exc);
5687 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5689 mono_assembly_name_free (aname);
5692 ICALL_EXPORT gboolean
5693 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5695 *is_version_definited = *is_token_defined = FALSE;
5697 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5700 ICALL_EXPORT MonoReflectionType*
5701 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5704 MonoReflectionType *ret;
5705 MonoDomain *domain = mono_object_domain (module);
5708 g_assert (module->image);
5710 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5711 /* These images do not have a global type */
5714 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5715 if (!mono_error_ok (&error)) {
5716 mono_error_set_pending_exception (&error);
5720 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5721 if (!mono_error_ok (&error)) {
5722 mono_error_set_pending_exception (&error);
5730 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5732 /*if (module->image)
5733 mono_image_close (module->image);*/
5736 ICALL_EXPORT MonoStringHandle
5737 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5739 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5740 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5743 return mono_string_new_handle (domain, image->guid, error);
5746 ICALL_EXPORT gpointer
5747 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5750 if (module->image && module->image->is_module_handle)
5751 return module->image->raw_data;
5754 return (gpointer) (-1);
5758 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5760 if (image_is_dynamic (image)) {
5761 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5762 *pe_kind = dyn->pe_kind;
5763 *machine = dyn->machine;
5766 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5767 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5772 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5774 return (image->md_version_major << 16) | (image->md_version_minor);
5777 ICALL_EXPORT MonoArray*
5778 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5781 MonoArray *exceptions;
5784 if (!module->image) {
5785 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5786 mono_error_set_pending_exception (&error);
5791 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5792 if (mono_error_set_pending_exception (&error))
5795 for (i = 0; i < mono_array_length (exceptions); ++i) {
5796 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5798 mono_set_pending_exception (ex);
5807 mono_memberref_is_method (MonoImage *image, guint32 token)
5809 if (!image_is_dynamic (image)) {
5810 guint32 cols [MONO_MEMBERREF_SIZE];
5812 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5813 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5814 mono_metadata_decode_blob_size (sig, &sig);
5815 return (*sig != 0x6);
5818 MonoClass *handle_class;
5820 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5821 mono_error_cleanup (&error); /* just probing, ignore error */
5825 return mono_defaults.methodhandle_class == handle_class;
5830 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5833 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5834 mono_array_addr (type_args, MonoType*, 0));
5836 context->class_inst = NULL;
5838 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5839 mono_array_addr (method_args, MonoType*, 0));
5841 context->method_inst = NULL;
5844 ICALL_EXPORT MonoType*
5845 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5848 int table = mono_metadata_token_table (token);
5849 int index = mono_metadata_token_index (token);
5850 MonoGenericContext context;
5853 *resolve_error = ResolveTokenError_Other;
5855 /* Validate token */
5856 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5857 (table != MONO_TABLE_TYPESPEC)) {
5858 *resolve_error = ResolveTokenError_BadTable;
5862 if (image_is_dynamic (image)) {
5863 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5864 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5865 mono_error_cleanup (&error);
5866 return klass ? &klass->byval_arg : NULL;
5869 init_generic_context_from_args (&context, type_args, method_args);
5870 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5871 mono_error_cleanup (&error);
5872 return klass ? &klass->byval_arg : NULL;
5875 if ((index <= 0) || (index > image->tables [table].rows)) {
5876 *resolve_error = ResolveTokenError_OutOfRange;
5880 init_generic_context_from_args (&context, type_args, method_args);
5881 klass = mono_class_get_checked (image, token, &error);
5883 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5884 if (!mono_error_ok (&error)) {
5885 mono_error_set_pending_exception (&error);
5890 return &klass->byval_arg;
5895 ICALL_EXPORT MonoMethod*
5896 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5899 int table = mono_metadata_token_table (token);
5900 int index = mono_metadata_token_index (token);
5901 MonoGenericContext context;
5904 *resolve_error = ResolveTokenError_Other;
5906 /* Validate token */
5907 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5908 (table != MONO_TABLE_MEMBERREF)) {
5909 *resolve_error = ResolveTokenError_BadTable;
5913 if (image_is_dynamic (image)) {
5914 if (table == MONO_TABLE_METHOD) {
5915 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5916 mono_error_cleanup (&error);
5920 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5921 *resolve_error = ResolveTokenError_BadTable;
5925 init_generic_context_from_args (&context, type_args, method_args);
5926 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5927 mono_error_cleanup (&error);
5931 if ((index <= 0) || (index > image->tables [table].rows)) {
5932 *resolve_error = ResolveTokenError_OutOfRange;
5935 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5936 *resolve_error = ResolveTokenError_BadTable;
5940 init_generic_context_from_args (&context, type_args, method_args);
5941 method = mono_get_method_checked (image, token, NULL, &context, &error);
5942 mono_error_set_pending_exception (&error);
5947 ICALL_EXPORT MonoString*
5948 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5951 int index = mono_metadata_token_index (token);
5953 *resolve_error = ResolveTokenError_Other;
5955 /* Validate token */
5956 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5957 *resolve_error = ResolveTokenError_BadTable;
5961 if (image_is_dynamic (image)) {
5962 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5963 mono_error_cleanup (&error);
5967 if ((index <= 0) || (index >= image->heap_us.size)) {
5968 *resolve_error = ResolveTokenError_OutOfRange;
5972 /* FIXME: What to do if the index points into the middle of a string ? */
5974 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5975 mono_error_set_pending_exception (&error);
5979 ICALL_EXPORT MonoClassField*
5980 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5984 int table = mono_metadata_token_table (token);
5985 int index = mono_metadata_token_index (token);
5986 MonoGenericContext context;
5987 MonoClassField *field;
5989 *resolve_error = ResolveTokenError_Other;
5991 /* Validate token */
5992 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5993 *resolve_error = ResolveTokenError_BadTable;
5997 if (image_is_dynamic (image)) {
5998 if (table == MONO_TABLE_FIELD) {
5999 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6000 mono_error_cleanup (&error);
6004 if (mono_memberref_is_method (image, token)) {
6005 *resolve_error = ResolveTokenError_BadTable;
6009 init_generic_context_from_args (&context, type_args, method_args);
6010 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6011 mono_error_cleanup (&error);
6015 if ((index <= 0) || (index > image->tables [table].rows)) {
6016 *resolve_error = ResolveTokenError_OutOfRange;
6019 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6020 *resolve_error = ResolveTokenError_BadTable;
6024 init_generic_context_from_args (&context, type_args, method_args);
6025 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6026 mono_error_set_pending_exception (&error);
6032 ICALL_EXPORT MonoObject*
6033 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6037 int table = mono_metadata_token_table (token);
6039 *error = ResolveTokenError_Other;
6042 case MONO_TABLE_TYPEDEF:
6043 case MONO_TABLE_TYPEREF:
6044 case MONO_TABLE_TYPESPEC: {
6045 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6047 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6048 mono_error_set_pending_exception (&merror);
6055 case MONO_TABLE_METHOD:
6056 case MONO_TABLE_METHODSPEC: {
6057 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6059 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6060 mono_error_set_pending_exception (&merror);
6066 case MONO_TABLE_FIELD: {
6067 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6069 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6070 mono_error_set_pending_exception (&merror);
6076 case MONO_TABLE_MEMBERREF:
6077 if (mono_memberref_is_method (image, token)) {
6078 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6080 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6081 mono_error_set_pending_exception (&merror);
6088 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6090 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6091 mono_error_set_pending_exception (&merror);
6100 *error = ResolveTokenError_BadTable;
6106 ICALL_EXPORT MonoArray*
6107 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6110 int table = mono_metadata_token_table (token);
6111 int idx = mono_metadata_token_index (token);
6112 MonoTableInfo *tables = image->tables;
6117 *resolve_error = ResolveTokenError_OutOfRange;
6119 /* FIXME: Support other tables ? */
6120 if (table != MONO_TABLE_STANDALONESIG)
6123 if (image_is_dynamic (image))
6126 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6129 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6131 ptr = mono_metadata_blob_heap (image, sig);
6132 len = mono_metadata_decode_blob_size (ptr, &ptr);
6134 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6135 if (mono_error_set_pending_exception (&error))
6137 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6141 ICALL_EXPORT MonoBoolean
6142 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6148 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6154 check_for_invalid_type (MonoClass *klass, MonoError *error)
6158 mono_error_init (error);
6160 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6163 name = mono_type_get_full_name (klass);
6164 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6166 ICALL_EXPORT MonoReflectionType *
6167 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6170 MonoReflectionType *ret;
6171 MonoClass *klass, *aklass;
6173 klass = mono_class_from_mono_type (type->type);
6174 check_for_invalid_type (klass, &error);
6175 if (mono_error_set_pending_exception (&error))
6178 if (rank == 0) //single dimentional array
6179 aklass = mono_array_class_get (klass, 1);
6181 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6183 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6184 mono_error_set_pending_exception (&error);
6189 ICALL_EXPORT MonoReflectionType *
6190 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6193 MonoReflectionType *ret;
6196 klass = mono_class_from_mono_type (type->type);
6197 mono_class_init_checked (klass, &error);
6198 if (mono_error_set_pending_exception (&error))
6201 check_for_invalid_type (klass, &error);
6202 if (mono_error_set_pending_exception (&error))
6205 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6206 mono_error_set_pending_exception (&error);
6211 ICALL_EXPORT MonoReflectionType *
6212 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6215 MonoReflectionType *ret;
6216 MonoClass *klass, *pklass;
6218 klass = mono_class_from_mono_type (type->type);
6219 mono_class_init_checked (klass, &error);
6220 if (mono_error_set_pending_exception (&error))
6222 check_for_invalid_type (klass, &error);
6223 if (mono_error_set_pending_exception (&error))
6226 pklass = mono_ptr_class_get (type->type);
6228 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6229 mono_error_set_pending_exception (&error);
6234 ICALL_EXPORT MonoObject *
6235 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6236 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6239 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6240 MonoObject *delegate;
6242 MonoMethod *method = info->method;
6243 MonoMethodSignature *sig = mono_method_signature(method);
6245 mono_class_init_checked (delegate_class, &error);
6246 if (mono_error_set_pending_exception (&error))
6249 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6250 /* FIXME improve this exception message */
6251 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6253 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6254 mono_error_set_pending_exception (&error);
6258 if (mono_security_core_clr_enabled ()) {
6259 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6260 if (throwOnBindFailure)
6261 mono_error_set_pending_exception (&error);
6263 mono_error_cleanup (&error);
6268 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6269 if (!method->is_inflated) {
6270 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"));
6275 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6276 if (mono_error_set_pending_exception (&error))
6279 if (method_is_dynamic (method)) {
6280 /* Creating a trampoline would leak memory */
6281 func = mono_compile_method_checked (method, &error);
6282 if (mono_error_set_pending_exception (&error))
6285 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6286 method = mono_object_get_virtual_method (target, method);
6287 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6288 if (mono_error_set_pending_exception (&error))
6290 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6293 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6294 if (mono_error_set_pending_exception (&error))
6299 ICALL_EXPORT MonoMulticastDelegate *
6300 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6303 MonoMulticastDelegate *ret;
6305 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6307 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6308 if (mono_error_set_pending_exception (&error))
6311 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6316 ICALL_EXPORT MonoReflectionMethod*
6317 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6319 MonoReflectionMethod *ret = NULL;
6321 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6322 mono_error_set_pending_exception (&error);
6328 static inline gint32
6329 mono_array_get_byte_length (MonoArray *array)
6335 klass = array->obj.vtable->klass;
6337 if (array->bounds == NULL)
6338 length = array->max_length;
6341 for (i = 0; i < klass->rank; ++ i)
6342 length *= array->bounds [i].length;
6345 switch (klass->element_class->byval_arg.type) {
6348 case MONO_TYPE_BOOLEAN:
6352 case MONO_TYPE_CHAR:
6360 return length * sizeof (gpointer);
6371 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6373 return mono_array_get_byte_length (array);
6377 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6379 return mono_array_get (array, gint8, idx);
6383 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6385 mono_array_set (array, gint8, idx, value);
6388 ICALL_EXPORT MonoBoolean
6389 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6391 guint8 *src_buf, *dest_buf;
6394 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6398 g_assert (count >= 0);
6400 /* This is called directly from the class libraries without going through the managed wrapper */
6401 MONO_CHECK_ARG_NULL (src, FALSE);
6402 MONO_CHECK_ARG_NULL (dest, FALSE);
6404 /* watch out for integer overflow */
6405 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6408 src_buf = (guint8 *)src->vector + src_offset;
6409 dest_buf = (guint8 *)dest->vector + dest_offset;
6412 memcpy (dest_buf, src_buf, count);
6414 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6419 #ifndef DISABLE_REMOTING
6420 ICALL_EXPORT MonoObject *
6421 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6424 MonoDomain *domain = mono_object_domain (this_obj);
6426 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6427 MonoTransparentProxy *tp;
6431 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6432 if (mono_error_set_pending_exception (&error))
6435 tp = (MonoTransparentProxy*) res;
6437 MONO_OBJECT_SETREF (tp, rp, rp);
6438 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6439 klass = mono_class_from_mono_type (type);
6441 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6442 mono_class_setup_vtable (klass);
6443 if (mono_class_has_failure (klass)) {
6444 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6448 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6449 if (mono_error_set_pending_exception (&error))
6451 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6452 if (mono_error_set_pending_exception (&error))
6455 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6456 if (mono_error_set_pending_exception (&error))
6461 ICALL_EXPORT MonoReflectionType *
6462 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6465 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6466 mono_error_set_pending_exception (&error);
6472 /* System.Environment */
6475 ves_icall_System_Environment_get_UserName (void)
6477 /* using glib is more portable */
6478 return mono_string_new (mono_domain_get (), g_get_user_name ());
6482 ICALL_EXPORT MonoString *
6483 ves_icall_System_Environment_get_MachineName (void)
6485 #if defined (HOST_WIN32)
6490 len = MAX_COMPUTERNAME_LENGTH + 1;
6491 buf = g_new (gunichar2, len);
6494 if (GetComputerName (buf, (PDWORD) &len)) {
6496 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6497 mono_error_set_pending_exception (&error);
6502 #elif !defined(DISABLE_SOCKETS)
6506 #if defined _SC_HOST_NAME_MAX
6507 n = sysconf (_SC_HOST_NAME_MAX);
6511 buf = g_malloc (n+1);
6513 if (gethostname (buf, n) == 0){
6515 result = mono_string_new (mono_domain_get (), buf);
6522 return mono_string_new (mono_domain_get (), "mono");
6527 ves_icall_System_Environment_get_Platform (void)
6529 #if defined (TARGET_WIN32)
6532 #elif defined(__MACH__)
6535 // Notice that the value is hidden from user code, and only exposed
6536 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6537 // define and making assumptions based on Unix/128/4 values before there
6538 // was a MacOS define. Lots of code would assume that not-Unix meant
6539 // Windows, but in this case, it would be OSX.
6548 ICALL_EXPORT MonoString *
6549 ves_icall_System_Environment_get_NewLine (void)
6551 #if defined (HOST_WIN32)
6552 return mono_string_new (mono_domain_get (), "\r\n");
6554 return mono_string_new (mono_domain_get (), "\n");
6558 ICALL_EXPORT MonoBoolean
6559 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6561 #if SIZEOF_VOID_P == 8
6565 gboolean isWow64Process = FALSE;
6566 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6567 return (MonoBoolean)isWow64Process;
6569 #elif defined(HAVE_SYS_UTSNAME_H)
6570 struct utsname name;
6572 if (uname (&name) >= 0) {
6573 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6580 ICALL_EXPORT MonoStringHandle
6581 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6585 if (utf8_name == NULL)
6586 return NULL_HANDLE_STRING;
6588 value = g_getenv (utf8_name);
6591 return NULL_HANDLE_STRING;
6593 return mono_string_new_handle (mono_domain_get (), value, error);
6597 * There is no standard way to get at environ.
6600 #ifndef __MINGW32_VERSION
6601 #if defined(__APPLE__)
6602 #if defined (TARGET_OSX)
6603 /* Apple defines this in crt_externs.h but doesn't provide that header for
6604 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6605 * in fact exist on all implementations (so far)
6607 gchar ***_NSGetEnviron(void);
6608 #define environ (*_NSGetEnviron())
6610 static char *mono_environ[1] = { NULL };
6611 #define environ mono_environ
6612 #endif /* defined (TARGET_OSX) */
6620 ICALL_EXPORT MonoArray *
6621 ves_icall_System_Environment_GetCoomandLineArgs (void)
6624 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6625 mono_error_set_pending_exception (&error);
6629 ICALL_EXPORT MonoArray *
6630 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6642 env_strings = GetEnvironmentStrings();
6645 env_string = env_strings;
6646 while (*env_string != '\0') {
6647 /* weird case that MS seems to skip */
6648 if (*env_string != '=')
6650 while (*env_string != '\0')
6656 domain = mono_domain_get ();
6657 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6658 if (mono_error_set_pending_exception (&error))
6663 env_string = env_strings;
6664 while (*env_string != '\0') {
6665 /* weird case that MS seems to skip */
6666 if (*env_string != '=') {
6667 equal_str = wcschr(env_string, '=');
6668 g_assert(equal_str);
6670 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6671 if (mono_error_set_pending_exception (&error))
6674 mono_array_setref (names, n, str);
6677 while (*env_string != '\0')
6682 FreeEnvironmentStrings (env_strings);
6696 for (e = environ; *e != 0; ++ e)
6699 domain = mono_domain_get ();
6700 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6701 if (mono_error_set_pending_exception (&error))
6705 for (e = environ; *e != 0; ++ e) {
6706 parts = g_strsplit (*e, "=", 2);
6708 str = mono_string_new (domain, *parts);
6709 mono_array_setref (names, n, str);
6722 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6725 gunichar2 *utf16_name, *utf16_value;
6727 gchar *utf8_name, *utf8_value;
6732 utf16_name = mono_string_to_utf16 (name);
6733 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6734 SetEnvironmentVariable (utf16_name, NULL);
6735 g_free (utf16_name);
6739 utf16_value = mono_string_to_utf16 (value);
6741 SetEnvironmentVariable (utf16_name, utf16_value);
6743 g_free (utf16_name);
6744 g_free (utf16_value);
6746 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6747 if (mono_error_set_pending_exception (&error))
6750 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6751 g_unsetenv (utf8_name);
6756 utf8_value = mono_string_to_utf8_checked (value, &error);
6757 if (!mono_error_ok (&error)) {
6759 mono_error_set_pending_exception (&error);
6762 g_setenv (utf8_name, utf8_value, TRUE);
6765 g_free (utf8_value);
6770 ves_icall_System_Environment_Exit (int result)
6772 mono_environment_exitcode_set (result);
6774 /* FIXME: There are some cleanup hangs that should be worked out, but
6775 * if the program is going to exit, everything will be cleaned up when
6776 * NaCl exits anyway.
6778 #ifndef __native_client__
6779 if (!mono_runtime_try_shutdown ())
6780 mono_thread_exit ();
6782 /* Suspend all managed threads since the runtime is going away */
6783 mono_thread_suspend_all_other_threads ();
6785 mono_runtime_quit ();
6788 /* we may need to do some cleanup here... */
6792 ICALL_EXPORT MonoStringHandle
6793 ves_icall_System_Environment_GetGacPath (MonoError *error)
6795 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6798 ICALL_EXPORT MonoString*
6799 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6801 #if defined (HOST_WIN32)
6802 #ifndef CSIDL_FLAG_CREATE
6803 #define CSIDL_FLAG_CREATE 0x8000
6806 WCHAR path [MAX_PATH];
6807 /* Create directory if no existing */
6808 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6813 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6814 mono_error_set_pending_exception (&error);
6818 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6820 return mono_string_new (mono_domain_get (), "");
6823 ICALL_EXPORT MonoArray *
6824 ves_icall_System_Environment_GetLogicalDrives (void)
6827 gunichar2 buf [256], *ptr, *dname;
6829 guint initial_size = 127, size = 128;
6832 MonoString *drivestr;
6833 MonoDomain *domain = mono_domain_get ();
6839 while (size > initial_size) {
6840 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6841 if (size > initial_size) {
6844 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6845 initial_size = size;
6859 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6860 if (mono_error_set_pending_exception (&error))
6867 while (*u16) { u16++; len ++; }
6868 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6869 if (mono_error_set_pending_exception (&error))
6872 mono_array_setref (result, ndrives++, drivestr);
6883 ICALL_EXPORT MonoString *
6884 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6887 gunichar2 volume_name [MAX_PATH + 1];
6889 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6891 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6892 mono_error_set_pending_exception (&error);
6896 ICALL_EXPORT MonoStringHandle
6897 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6899 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6902 static const char *encodings [] = {
6904 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6905 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6906 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6908 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6909 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6910 "x_unicode_2_0_utf_7",
6912 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6913 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6915 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6918 "unicodefffe", "utf_16be",
6925 * Returns the internal codepage, if the value of "int_code_page" is
6926 * 1 at entry, and we can not compute a suitable code page number,
6927 * returns the code page as a string
6929 ICALL_EXPORT MonoString*
6930 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6935 char *codepage = NULL;
6937 int want_name = *int_code_page;
6940 *int_code_page = -1;
6942 g_get_charset (&cset);
6943 c = codepage = strdup (cset);
6944 for (c = codepage; *c; c++){
6945 if (isascii (*c) && isalpha (*c))
6950 /* g_print ("charset: %s\n", cset); */
6952 /* handle some common aliases */
6955 for (i = 0; p != 0; ){
6958 p = encodings [++i];
6961 if (strcmp (p, codepage) == 0){
6962 *int_code_page = code;
6965 p = encodings [++i];
6968 if (strstr (codepage, "utf_8") != NULL)
6969 *int_code_page |= 0x10000000;
6972 if (want_name && *int_code_page == -1)
6973 return mono_string_new (mono_domain_get (), cset);
6978 ICALL_EXPORT MonoBoolean
6979 ves_icall_System_Environment_get_HasShutdownStarted (void)
6981 if (mono_runtime_is_shutting_down ())
6984 if (mono_domain_is_unloading (mono_domain_get ()))
6991 ves_icall_System_Environment_BroadcastSettingChange (void)
6994 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7000 ves_icall_System_Environment_get_TickCount (void)
7002 /* this will overflow after ~24 days */
7003 return (gint32) (mono_msec_boottime () & 0xffffffff);
7007 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7012 #ifndef DISABLE_REMOTING
7013 ICALL_EXPORT MonoBoolean
7014 ves_icall_IsTransparentProxy (MonoObject *proxy)
7019 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7025 ICALL_EXPORT MonoReflectionMethod *
7026 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7027 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7029 MonoReflectionMethod *ret = NULL;
7034 MonoMethod **vtable;
7035 MonoMethod *res = NULL;
7037 MONO_CHECK_ARG_NULL (rtype, NULL);
7038 MONO_CHECK_ARG_NULL (rmethod, NULL);
7040 method = rmethod->method;
7041 klass = mono_class_from_mono_type (rtype->type);
7042 mono_class_init_checked (klass, &error);
7043 if (mono_error_set_pending_exception (&error))
7046 if (MONO_CLASS_IS_INTERFACE (klass))
7049 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7052 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7053 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7059 mono_class_setup_vtable (klass);
7060 vtable = klass->vtable;
7062 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7063 gboolean variance_used = FALSE;
7064 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7065 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7067 res = vtable [offs + method->slot];
7069 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7072 if (method->slot != -1)
7073 res = vtable [method->slot];
7079 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7080 mono_error_set_pending_exception (&error);
7085 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7091 klass = mono_class_from_mono_type (type->type);
7092 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7093 if (!is_ok (&error)) {
7094 mono_error_set_pending_exception (&error);
7098 mono_vtable_set_is_remote (vtable, enable);
7101 #else /* DISABLE_REMOTING */
7104 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7106 g_assert_not_reached ();
7111 ICALL_EXPORT MonoObject *
7112 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7119 domain = mono_object_domain (type);
7120 klass = mono_class_from_mono_type (type->type);
7121 mono_class_init_checked (klass, &error);
7122 if (mono_error_set_pending_exception (&error))
7125 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7126 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7130 if (klass->rank >= 1) {
7131 g_assert (klass->rank == 1);
7132 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7133 mono_error_set_pending_exception (&error);
7136 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7137 if (!is_ok (&error)) {
7138 mono_error_set_pending_exception (&error);
7141 /* Bypass remoting object creation check */
7142 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7143 mono_error_set_pending_exception (&error);
7149 ICALL_EXPORT MonoStringHandle
7150 ves_icall_System_IO_get_temp_path (MonoError *error)
7152 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7155 #ifndef PLATFORM_NO_DRIVEINFO
7156 ICALL_EXPORT MonoBoolean
7157 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7158 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7162 ULARGE_INTEGER wapi_free_bytes_avail;
7163 ULARGE_INTEGER wapi_total_number_of_bytes;
7164 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7166 *error = ERROR_SUCCESS;
7167 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7168 &wapi_total_number_of_free_bytes);
7171 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7172 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7173 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7175 *free_bytes_avail = 0;
7176 *total_number_of_bytes = 0;
7177 *total_number_of_free_bytes = 0;
7178 *error = GetLastError ();
7184 ICALL_EXPORT guint32
7185 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7187 return GetDriveType (mono_string_chars (root_path_name));
7191 ICALL_EXPORT gpointer
7192 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7195 gpointer result = mono_compile_method_checked (method, &error);
7196 mono_error_set_pending_exception (&error);
7200 ICALL_EXPORT MonoString *
7201 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7206 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7208 #if defined (HOST_WIN32)
7209 /* Avoid mixing '/' and '\\' */
7212 for (i = strlen (path) - 1; i >= 0; i--)
7213 if (path [i] == '/')
7217 mcpath = mono_string_new (mono_domain_get (), path);
7223 /* this is an icall */
7225 get_bundled_app_config (void)
7228 const gchar *app_config;
7231 gchar *config_file_name, *config_file_path;
7232 gsize len, config_file_path_length, config_ext_length;
7235 domain = mono_domain_get ();
7236 file = domain->setup->configuration_file;
7237 if (!file || file->length == 0)
7240 // Retrieve config file and remove the extension
7241 config_file_name = mono_string_to_utf8_checked (file, &error);
7242 if (mono_error_set_pending_exception (&error))
7244 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7245 if (!config_file_path)
7246 config_file_path = config_file_name;
7248 config_file_path_length = strlen (config_file_path);
7249 config_ext_length = strlen (".config");
7250 if (config_file_path_length <= config_ext_length)
7253 len = config_file_path_length - config_ext_length;
7254 module = (gchar *)g_malloc0 (len + 1);
7255 memcpy (module, config_file_path, len);
7256 // Get the config file from the module name
7257 app_config = mono_config_string_for_assembly_file (module);
7260 if (config_file_name != config_file_path)
7261 g_free (config_file_name);
7262 g_free (config_file_path);
7267 return mono_string_new (mono_domain_get (), app_config);
7270 static MonoStringHandle
7271 get_bundled_machine_config (MonoError *error)
7273 const gchar *machine_config;
7275 machine_config = mono_get_machine_config ();
7277 if (!machine_config)
7278 return NULL_HANDLE_STRING;
7280 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7283 static MonoStringHandle
7284 ves_icall_System_Configuration_DefaultConfig_get_bundled_machine_config (MonoError *error)
7286 return get_bundled_machine_config (error);
7289 static MonoStringHandle
7290 ves_icall_System_Configuration_InternalConfigurationHost_get_bundled_machine_config (MonoError *error)
7292 return get_bundled_machine_config (error);
7296 ICALL_EXPORT MonoString *
7297 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7302 path = g_path_get_dirname (mono_get_config_dir ());
7304 #if defined (HOST_WIN32)
7305 /* Avoid mixing '/' and '\\' */
7308 for (i = strlen (path) - 1; i >= 0; i--)
7309 if (path [i] == '/')
7313 ipath = mono_string_new (mono_domain_get (), path);
7319 ICALL_EXPORT gboolean
7320 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7322 MonoPEResourceDataEntry *entry;
7325 if (!assembly || !result || !size)
7330 image = assembly->assembly->image;
7331 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7335 *result = mono_image_rva_map (image, entry->rde_data_offset);
7340 *size = entry->rde_size;
7345 ICALL_EXPORT MonoBoolean
7346 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7348 return mono_is_debugger_attached ();
7351 ICALL_EXPORT MonoBoolean
7352 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7354 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7355 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7361 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7363 if (mono_get_runtime_callbacks ()->debug_log)
7364 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7368 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7370 #if defined (HOST_WIN32)
7371 OutputDebugString (mono_string_chars (message));
7373 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7377 /* Only used for value types */
7378 ICALL_EXPORT MonoObject *
7379 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7386 domain = mono_object_domain (type);
7387 klass = mono_class_from_mono_type (type->type);
7388 mono_class_init_checked (klass, &error);
7389 if (mono_error_set_pending_exception (&error))
7392 if (mono_class_is_nullable (klass))
7393 /* No arguments -> null */
7396 result = mono_object_new_checked (domain, klass, &error);
7397 mono_error_set_pending_exception (&error);
7401 ICALL_EXPORT MonoReflectionMethod *
7402 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7404 MonoReflectionMethod *ret = NULL;
7407 MonoClass *klass, *parent;
7408 MonoGenericContext *generic_inst = NULL;
7409 MonoMethod *method = m->method;
7410 MonoMethod *result = NULL;
7413 if (method->klass == NULL)
7416 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7417 MONO_CLASS_IS_INTERFACE (method->klass) ||
7418 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7421 slot = mono_method_get_vtable_slot (method);
7425 klass = method->klass;
7426 if (klass->generic_class) {
7427 generic_inst = mono_class_get_context (klass);
7428 klass = klass->generic_class->container_class;
7433 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7434 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7435 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7436 or klass is the generic container class and generic_inst is the instantiation.
7438 when we go to the parent, if the parent is an open constructed type, we need to
7439 replace the type parameters by the definitions from the generic_inst, and then take it
7440 apart again into the klass and the generic_inst.
7442 For cases like this:
7443 class C<T> : B<T, int> {
7444 public override void Foo () { ... }
7446 class B<U,V> : A<HashMap<U,V>> {
7447 public override void Foo () { ... }
7450 public virtual void Foo () { ... }
7453 if at each iteration the parent isn't open, we can skip inflating it. if at some
7454 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7457 MonoGenericContext *parent_inst = NULL;
7458 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7459 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7460 if (!mono_error_ok (&error)) {
7461 mono_error_set_pending_exception (&error);
7465 if (parent->generic_class) {
7466 parent_inst = mono_class_get_context (parent);
7467 parent = parent->generic_class->container_class;
7470 mono_class_setup_vtable (parent);
7471 if (parent->vtable_size <= slot)
7474 generic_inst = parent_inst;
7477 klass = klass->parent;
7480 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7481 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7482 if (!mono_error_ok (&error)) {
7483 mono_error_set_pending_exception (&error);
7487 generic_inst = NULL;
7489 if (klass->generic_class) {
7490 generic_inst = mono_class_get_context (klass);
7491 klass = klass->generic_class->container_class;
7497 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7498 if (!mono_error_ok (&error)) {
7499 mono_error_set_pending_exception (&error);
7504 if (klass == method->klass)
7507 /*This is possible if definition == FALSE.
7508 * Do it here to be really sure we don't read invalid memory.
7510 if (slot >= klass->vtable_size)
7513 mono_class_setup_vtable (klass);
7515 result = klass->vtable [slot];
7516 if (result == NULL) {
7517 /* It is an abstract method */
7518 gboolean found = FALSE;
7519 gpointer iter = NULL;
7520 while ((result = mono_class_get_methods (klass, &iter))) {
7521 if (result->slot == slot) {
7526 /* found might be FALSE if we looked in an abstract class
7527 * that doesn't override an abstract method of its
7529 * abstract class Base {
7530 * public abstract void Foo ();
7532 * abstract class Derived : Base { }
7533 * class Child : Derived {
7534 * public override void Foo () { }
7537 * if m was Child.Foo and we ask for the base method,
7538 * then we get here with klass == Derived and found == FALSE
7540 /* but it shouldn't be the case that if we're looking
7541 * for the definition and didn't find a result; the
7542 * loop above should've taken us as far as we could
7544 g_assert (!(definition && !found));
7549 g_assert (result != NULL);
7551 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7552 mono_error_set_pending_exception (&error);
7556 ICALL_EXPORT MonoString*
7557 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7559 MonoMethod *method = m->method;
7561 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7566 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7568 iter->sig = *(MonoMethodSignature**)argsp;
7570 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7571 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7574 /* FIXME: it's not documented what start is exactly... */
7578 iter->args = argsp + sizeof (gpointer);
7580 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7582 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7585 ICALL_EXPORT MonoTypedRef
7586 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7588 guint32 i, arg_size;
7592 i = iter->sig->sentinelpos + iter->next_arg;
7594 g_assert (i < iter->sig->param_count);
7596 res.type = iter->sig->params [i];
7597 res.klass = mono_class_from_mono_type (res.type);
7598 arg_size = mono_type_stack_size (res.type, &align);
7599 #if defined(__arm__) || defined(__mips__)
7600 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7602 res.value = iter->args;
7603 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7604 /* Values are stored as 8 byte register sized objects, but 'value'
7605 * is dereferenced as a pointer in other routines.
7607 res.value = (char*)res.value + 4;
7609 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7610 if (arg_size <= sizeof (gpointer)) {
7612 int padding = arg_size - mono_type_size (res.type, &dummy);
7613 res.value = (guint8*)res.value + padding;
7616 iter->args = (char*)iter->args + arg_size;
7619 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7624 ICALL_EXPORT MonoTypedRef
7625 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7627 guint32 i, arg_size;
7631 i = iter->sig->sentinelpos + iter->next_arg;
7633 g_assert (i < iter->sig->param_count);
7635 while (i < iter->sig->param_count) {
7636 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7638 res.type = iter->sig->params [i];
7639 res.klass = mono_class_from_mono_type (res.type);
7640 /* FIXME: endianess issue... */
7641 arg_size = mono_type_stack_size (res.type, &align);
7642 #if defined(__arm__) || defined(__mips__)
7643 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7645 res.value = iter->args;
7646 iter->args = (char*)iter->args + arg_size;
7648 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7651 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7659 ICALL_EXPORT MonoType*
7660 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7664 i = iter->sig->sentinelpos + iter->next_arg;
7666 g_assert (i < iter->sig->param_count);
7668 return iter->sig->params [i];
7671 ICALL_EXPORT MonoObject*
7672 mono_TypedReference_ToObject (MonoTypedRef* tref)
7675 MonoObject *result = NULL;
7676 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7677 MonoObject** objp = (MonoObject **)tref->value;
7681 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7682 mono_error_set_pending_exception (&error);
7686 ICALL_EXPORT MonoTypedRef
7687 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7690 MonoReflectionField *f;
7692 MonoType *ftype = NULL;
7696 memset (&res, 0, sizeof (res));
7699 g_assert (mono_array_length (fields) > 0);
7701 klass = target->vtable->klass;
7703 for (i = 0; i < mono_array_length (fields); ++i) {
7704 f = mono_array_get (fields, MonoReflectionField*, i);
7706 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7709 if (f->field->parent != klass) {
7710 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7714 p = (guint8*)target + f->field->offset;
7716 p += f->field->offset - sizeof (MonoObject);
7717 klass = mono_class_from_mono_type (f->field->type);
7718 ftype = f->field->type;
7722 res.klass = mono_class_from_mono_type (ftype);
7729 prelink_method (MonoMethod *method, MonoError *error)
7731 const char *exc_class, *exc_arg;
7733 mono_error_init (error);
7734 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7736 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7738 mono_error_set_exception_instance (error,
7739 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7742 /* create the wrapper, too? */
7746 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7750 prelink_method (method->method, &error);
7751 mono_error_set_pending_exception (&error);
7755 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7758 MonoClass *klass = mono_class_from_mono_type (type->type);
7760 gpointer iter = NULL;
7762 mono_class_init_checked (klass, &error);
7763 if (mono_error_set_pending_exception (&error))
7766 while ((m = mono_class_get_methods (klass, &iter))) {
7767 prelink_method (m, &error);
7768 if (mono_error_set_pending_exception (&error))
7773 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7775 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7776 gint32 const **exponents,
7777 gunichar2 const **digitLowerTable,
7778 gunichar2 const **digitUpperTable,
7779 gint64 const **tenPowersList,
7780 gint32 const **decHexDigits)
7782 *mantissas = Formatter_MantissaBitsTable;
7783 *exponents = Formatter_TensExponentTable;
7784 *digitLowerTable = Formatter_DigitLowerTable;
7785 *digitUpperTable = Formatter_DigitUpperTable;
7786 *tenPowersList = Formatter_TenPowersList;
7787 *decHexDigits = Formatter_DecHexDigits;
7791 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7792 * and avoid useless allocations.
7795 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7797 MonoReflectionType *rt;
7801 mono_error_init (error);
7802 for (i = 0; i < type->num_mods; ++i) {
7803 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7808 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7809 return_val_if_nok (error, NULL);
7811 for (i = 0; i < type->num_mods; ++i) {
7812 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7813 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7814 return_val_if_nok (error, NULL);
7816 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7817 return_val_if_nok (error, NULL);
7819 mono_array_setref (res, count, rt);
7826 ICALL_EXPORT MonoArray*
7827 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7830 MonoType *type = param->ClassImpl->type;
7831 MonoClass *member_class = mono_object_class (param->MemberImpl);
7832 MonoMethod *method = NULL;
7835 MonoMethodSignature *sig;
7838 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7839 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7840 method = rmethod->method;
7841 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7842 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7843 if (!(method = prop->property->get))
7844 method = prop->property->set;
7847 char *type_name = mono_type_get_full_name (member_class);
7848 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7849 MonoException *ex = mono_get_exception_not_supported (msg);
7852 mono_set_pending_exception (ex);
7856 image = method->klass->image;
7857 pos = param->PositionImpl;
7858 sig = mono_method_signature (method);
7862 type = sig->params [pos];
7864 res = type_array_from_modifiers (image, type, optional, &error);
7865 mono_error_set_pending_exception (&error);
7870 get_property_type (MonoProperty *prop)
7872 MonoMethodSignature *sig;
7874 sig = mono_method_signature (prop->get);
7876 } else if (prop->set) {
7877 sig = mono_method_signature (prop->set);
7878 return sig->params [sig->param_count - 1];
7883 ICALL_EXPORT MonoArray*
7884 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7887 MonoType *type = get_property_type (property->property);
7888 MonoImage *image = property->klass->image;
7893 res = type_array_from_modifiers (image, type, optional, &error);
7894 mono_error_set_pending_exception (&error);
7899 *Construct a MonoType suited to be used to decode a constant blob object.
7901 * @type is the target type which will be constructed
7902 * @blob_type is the blob type, for example, that comes from the constant table
7903 * @real_type is the expected constructed type.
7906 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7908 type->type = blob_type;
7909 type->data.klass = NULL;
7910 if (blob_type == MONO_TYPE_CLASS)
7911 type->data.klass = mono_defaults.object_class;
7912 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7913 /* For enums, we need to use the base type */
7914 type->type = MONO_TYPE_VALUETYPE;
7915 type->data.klass = mono_class_from_mono_type (real_type);
7917 type->data.klass = mono_class_from_mono_type (real_type);
7920 ICALL_EXPORT MonoObject*
7921 property_info_get_default_value (MonoReflectionProperty *property)
7925 MonoProperty *prop = property->property;
7926 MonoType *type = get_property_type (prop);
7927 MonoDomain *domain = mono_object_domain (property);
7928 MonoTypeEnum def_type;
7929 const char *def_value;
7932 mono_class_init (prop->parent);
7934 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7935 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7939 def_value = mono_class_get_property_default_value (prop, &def_type);
7941 mono_type_from_blob_type (&blob_type, def_type, type);
7942 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7944 mono_error_set_pending_exception (&error);
7948 ICALL_EXPORT MonoBoolean
7949 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7952 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7953 MonoCustomAttrInfo *cinfo;
7956 mono_class_init_checked (attr_class, &error);
7957 if (mono_error_set_pending_exception (&error))
7960 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7961 if (!is_ok (&error)) {
7962 mono_error_set_pending_exception (&error);
7967 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7969 mono_custom_attrs_free (cinfo);
7973 ICALL_EXPORT MonoArray*
7974 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7976 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7981 mono_class_init_checked (attr_class, &error);
7982 if (mono_error_set_pending_exception (&error))
7986 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7987 if (!mono_error_ok (&error)) {
7988 mono_error_set_pending_exception (&error);
7995 ICALL_EXPORT MonoArray*
7996 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8000 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8001 mono_error_set_pending_exception (&error);
8006 ICALL_EXPORT MonoString*
8007 ves_icall_Mono_Runtime_GetDisplayName (void)
8010 MonoString *display_name;
8012 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8013 display_name = mono_string_new (mono_domain_get (), info);
8015 return display_name;
8018 ICALL_EXPORT MonoString*
8019 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8022 MonoString *message;
8026 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8027 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8030 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8032 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8033 if (mono_error_set_pending_exception (&error))
8040 ICALL_EXPORT gpointer
8041 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8043 return GetCurrentProcess ();
8046 ICALL_EXPORT MonoBoolean
8047 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8049 return GetExitCodeProcess (handle, (guint32*) exitcode);
8052 ICALL_EXPORT MonoBoolean
8053 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8055 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8056 return CloseHandle (handle);
8058 return CloseProcess (handle);
8062 ICALL_EXPORT MonoBoolean
8063 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8065 return TerminateProcess (handle, exitcode);
8069 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8072 return WaitForInputIdle (handle, milliseconds);
8074 /*TODO: Not implemented*/
8075 return WAIT_TIMEOUT;
8079 ICALL_EXPORT MonoBoolean
8080 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8082 return GetProcessWorkingSetSize (handle, min, max);
8085 ICALL_EXPORT MonoBoolean
8086 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8088 return SetProcessWorkingSetSize (handle, min, max);
8091 ICALL_EXPORT MonoBoolean
8092 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8094 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8098 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8100 return mono_process_current_pid ();
8104 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8106 return GetPriorityClass (handle);
8109 ICALL_EXPORT MonoBoolean
8110 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8112 return SetPriorityClass (handle, priorityClass);
8115 ICALL_EXPORT MonoBoolean
8116 ves_icall_Mono_Btls_Provider_IsSupported (void)
8125 #ifndef DISABLE_ICALL_TABLES
8127 #define ICALL_TYPE(id,name,first)
8128 #define ICALL(id,name,func) Icall_ ## id,
8129 #define HANDLES(inner) inner
8132 #include "metadata/icall-def.h"
8138 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8139 #define ICALL(id,name,func)
8141 #define HANDLES(inner) inner
8143 #include "metadata/icall-def.h"
8149 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8150 #define ICALL(id,name,func)
8152 #define HANDLES(inner) inner
8154 guint16 first_icall;
8157 static const IcallTypeDesc
8158 icall_type_descs [] = {
8159 #include "metadata/icall-def.h"
8163 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8166 #define HANDLES(inner) inner
8168 #define ICALL_TYPE(id,name,first)
8171 #ifdef HAVE_ARRAY_ELEM_INIT
8172 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8173 #define MSGSTRFIELD1(line) str##line
8175 static const struct msgstrtn_t {
8176 #define ICALL(id,name,func)
8178 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8179 #include "metadata/icall-def.h"
8181 } icall_type_names_str = {
8182 #define ICALL_TYPE(id,name,first) (name),
8183 #include "metadata/icall-def.h"
8186 static const guint16 icall_type_names_idx [] = {
8187 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8188 #include "metadata/icall-def.h"
8191 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8193 static const struct msgstr_t {
8195 #define ICALL_TYPE(id,name,first)
8196 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8197 #include "metadata/icall-def.h"
8199 } icall_names_str = {
8200 #define ICALL(id,name,func) (name),
8201 #include "metadata/icall-def.h"
8204 static const guint16 icall_names_idx [] = {
8205 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8206 #include "metadata/icall-def.h"
8209 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8215 #define ICALL_TYPE(id,name,first) name,
8216 #define ICALL(id,name,func)
8217 static const char* const
8218 icall_type_names [] = {
8219 #include "metadata/icall-def.h"
8223 #define icall_type_name_get(id) (icall_type_names [(id)])
8227 #define ICALL_TYPE(id,name,first)
8228 #define ICALL(id,name,func) name,
8229 static const char* const
8231 #include "metadata/icall-def.h"
8234 #define icall_name_get(id) icall_names [(id)]
8236 #endif /* !HAVE_ARRAY_ELEM_INIT */
8239 #define HANDLES(inner) inner
8242 #define ICALL_TYPE(id,name,first)
8243 #define ICALL(id,name,func) func,
8244 static const gconstpointer
8245 icall_functions [] = {
8246 #include "metadata/icall-def.h"
8250 #ifdef ENABLE_ICALL_SYMBOL_MAP
8252 #define HANDLES(inner) inner
8255 #define ICALL_TYPE(id,name,first)
8256 #define ICALL(id,name,func) #func,
8257 static const gconstpointer
8258 icall_symbols [] = {
8259 #include "metadata/icall-def.h"
8266 #define ICALL_TYPE(id,name,first)
8267 #define ICALL(id,name,func) 0,
8269 #define HANDLES(inner) 1,
8271 icall_uses_handles [] = {
8272 #include "metadata/icall-def.h"
8277 #endif /* DISABLE_ICALL_TABLES */
8279 static mono_mutex_t icall_mutex;
8280 static GHashTable *icall_hash = NULL;
8281 static GHashTable *jit_icall_hash_name = NULL;
8282 static GHashTable *jit_icall_hash_addr = NULL;
8285 mono_icall_init (void)
8287 #ifndef DISABLE_ICALL_TABLES
8290 /* check that tables are sorted: disable in release */
8293 const char *prev_class = NULL;
8294 const char *prev_method;
8296 for (i = 0; i < Icall_type_num; ++i) {
8297 const IcallTypeDesc *desc;
8300 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8301 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8302 prev_class = icall_type_name_get (i);
8303 desc = &icall_type_descs [i];
8304 num_icalls = icall_desc_num_icalls (desc);
8305 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8306 for (j = 0; j < num_icalls; ++j) {
8307 const char *methodn = icall_name_get (desc->first_icall + j);
8308 if (prev_method && strcmp (prev_method, methodn) >= 0)
8309 g_print ("method %s should come before method %s\n", methodn, prev_method);
8310 prev_method = methodn;
8316 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8317 mono_os_mutex_init (&icall_mutex);
8321 mono_icall_lock (void)
8323 mono_locks_os_acquire (&icall_mutex, IcallLock);
8327 mono_icall_unlock (void)
8329 mono_locks_os_release (&icall_mutex, IcallLock);
8333 mono_icall_cleanup (void)
8335 g_hash_table_destroy (icall_hash);
8336 g_hash_table_destroy (jit_icall_hash_name);
8337 g_hash_table_destroy (jit_icall_hash_addr);
8338 mono_os_mutex_destroy (&icall_mutex);
8342 * mono_add_internal_call:
8343 * @name: method specification to surface to the managed world
8344 * @method: pointer to a C method to invoke when the method is called
8346 * This method surfaces the C function pointed by @method as a method
8347 * that has been surfaced in managed code with the method specified in
8348 * @name as an internal call.
8350 * Internal calls are surfaced to all app domains loaded and they are
8351 * accessibly by a type with the specified name.
8353 * You must provide a fully qualified type name, that is namespaces
8354 * and type name, followed by a colon and the method name, with an
8355 * optional signature to bind.
8357 * For example, the following are all valid declarations:
8359 * "MyApp.Services.ScriptService:Accelerate"
8360 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8362 * You use method parameters in cases where there might be more than
8363 * one surface method to managed code. That way you can register different
8364 * internal calls for different method overloads.
8366 * The internal calls are invoked with no marshalling. This means that .NET
8367 * types like System.String are exposed as `MonoString *` parameters. This is
8368 * different than the way that strings are surfaced in P/Invoke.
8370 * For more information on how the parameters are marshalled, see the
8371 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8374 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8375 * reference for more information on the format of method descriptions.
8378 mono_add_internal_call (const char *name, gconstpointer method)
8382 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8384 mono_icall_unlock ();
8387 #ifndef DISABLE_ICALL_TABLES
8389 #ifdef HAVE_ARRAY_ELEM_INIT
8391 compare_method_imap (const void *key, const void *elem)
8393 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8394 return strcmp (key, method_name);
8398 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8400 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);
8403 return (nameslot - &icall_names_idx [0]);
8407 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8409 gsize slotnum = find_slot_icall (imap, name);
8412 return (gboolean)icall_uses_handles [slotnum];
8416 find_method_icall (const IcallTypeDesc *imap, const char *name)
8418 gsize slotnum = find_slot_icall (imap, name);
8421 return (gpointer)icall_functions [slotnum];
8425 compare_class_imap (const void *key, const void *elem)
8427 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8428 return strcmp (key, class_name);
8431 static const IcallTypeDesc*
8432 find_class_icalls (const char *name)
8434 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);
8437 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8440 #else /* HAVE_ARRAY_ELEM_INIT */
8443 compare_method_imap (const void *key, const void *elem)
8445 const char** method_name = (const char**)elem;
8446 return strcmp (key, *method_name);
8450 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8452 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8455 return nameslot - icall_names;
8459 find_method_icall (const IcallTypeDesc *imap, const char *name)
8461 gsize slotnum = find_slot_icall (imap, name);
8464 return (gpointer)icall_functions [slotnum];
8468 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8470 gsize slotnum = find_slot_icall (imap, name);
8473 return (gboolean)icall_uses_handles [slotnum];
8477 compare_class_imap (const void *key, const void *elem)
8479 const char** class_name = (const char**)elem;
8480 return strcmp (key, *class_name);
8483 static const IcallTypeDesc*
8484 find_class_icalls (const char *name)
8486 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8489 return &icall_type_descs [nameslot - icall_type_names];
8492 #endif /* HAVE_ARRAY_ELEM_INIT */
8494 #endif /* DISABLE_ICALL_TABLES */
8497 * we should probably export this as an helper (handle nested types).
8498 * Returns the number of chars written in buf.
8501 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8503 int nspacelen, cnamelen;
8504 nspacelen = strlen (klass->name_space);
8505 cnamelen = strlen (klass->name);
8506 if (nspacelen + cnamelen + 2 > bufsize)
8509 memcpy (buf, klass->name_space, nspacelen);
8510 buf [nspacelen ++] = '.';
8512 memcpy (buf + nspacelen, klass->name, cnamelen);
8513 buf [nspacelen + cnamelen] = 0;
8514 return nspacelen + cnamelen;
8517 #ifdef DISABLE_ICALL_TABLES
8519 no_icall_table (void)
8521 g_assert_not_reached ();
8526 * mono_lookup_internal_call_full:
8527 * @method: the method to look up
8528 * @uses_handles: out argument if method needs handles around managed objects.
8530 * Returns a pointer to the icall code for the given method. If
8531 * uses_handles is not NULL, it will be set to TRUE if the method
8532 * needs managed objects wrapped using the infrastructure in handle.h
8534 * If the method is not found, warns and returns NULL.
8537 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8542 int typelen = 0, mlen, siglen;
8544 #ifndef DISABLE_ICALL_TABLES
8545 const IcallTypeDesc *imap = NULL;
8548 g_assert (method != NULL);
8550 if (method->is_inflated)
8551 method = ((MonoMethodInflated *) method)->declaring;
8553 if (method->klass->nested_in) {
8554 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8558 mname [pos++] = '/';
8561 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8567 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8572 #ifndef DISABLE_ICALL_TABLES
8573 imap = find_class_icalls (mname);
8576 mname [typelen] = ':';
8577 mname [typelen + 1] = ':';
8579 mlen = strlen (method->name);
8580 memcpy (mname + typelen + 2, method->name, mlen);
8581 sigstart = mname + typelen + 2 + mlen;
8584 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8585 siglen = strlen (tmpsig);
8586 if (typelen + mlen + siglen + 6 > sizeof (mname))
8589 memcpy (sigstart + 1, tmpsig, siglen);
8590 sigstart [siglen + 1] = ')';
8591 sigstart [siglen + 2] = 0;
8596 res = g_hash_table_lookup (icall_hash, mname);
8599 *uses_handles = FALSE;
8600 mono_icall_unlock ();;
8603 /* try without signature */
8605 res = g_hash_table_lookup (icall_hash, mname);
8608 *uses_handles = FALSE;
8609 mono_icall_unlock ();
8613 #ifdef DISABLE_ICALL_TABLES
8614 mono_icall_unlock ();
8615 /* Fail only when the result is actually used */
8616 /* mono_marshal_get_native_wrapper () depends on this */
8617 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8618 return ves_icall_System_String_ctor_RedirectToCreateString;
8620 return no_icall_table;
8622 /* it wasn't found in the static call tables */
8625 *uses_handles = FALSE;
8626 mono_icall_unlock ();
8629 res = find_method_icall (imap, sigstart - mlen);
8632 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8633 mono_icall_unlock ();
8636 /* try _with_ signature */
8638 res = find_method_icall (imap, sigstart - mlen);
8641 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8642 mono_icall_unlock ();
8646 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8647 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8648 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8649 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8650 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");
8651 g_print ("If you see other errors or faults after this message they are probably related\n");
8652 g_print ("and you need to fix your mono install first.\n");
8654 mono_icall_unlock ();
8661 mono_lookup_internal_call (MonoMethod *method)
8663 return mono_lookup_internal_call_full (method, NULL);
8666 #ifdef ENABLE_ICALL_SYMBOL_MAP
8668 func_cmp (gconstpointer key, gconstpointer p)
8670 return (gsize)key - (gsize)*(gsize*)p;
8675 * mono_lookup_icall_symbol:
8677 * Given the icall METHOD, returns its C symbol.
8680 mono_lookup_icall_symbol (MonoMethod *m)
8682 #ifdef DISABLE_ICALL_TABLES
8683 g_assert_not_reached ();
8686 #ifdef ENABLE_ICALL_SYMBOL_MAP
8690 static gconstpointer *functions_sorted;
8691 static const char**symbols_sorted;
8692 static gboolean inited;
8697 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8698 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8699 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8700 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8701 /* Bubble sort the two arrays */
8705 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8706 if (functions_sorted [i] > functions_sorted [i + 1]) {
8709 tmp = functions_sorted [i];
8710 functions_sorted [i] = functions_sorted [i + 1];
8711 functions_sorted [i + 1] = tmp;
8712 tmp = symbols_sorted [i];
8713 symbols_sorted [i] = symbols_sorted [i + 1];
8714 symbols_sorted [i + 1] = tmp;
8721 func = mono_lookup_internal_call (m);
8724 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8728 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8730 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8731 g_assert_not_reached ();
8738 type_from_typename (char *type_name)
8740 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8742 if (!strcmp (type_name, "int"))
8743 klass = mono_defaults.int_class;
8744 else if (!strcmp (type_name, "ptr"))
8745 klass = mono_defaults.int_class;
8746 else if (!strcmp (type_name, "void"))
8747 klass = mono_defaults.void_class;
8748 else if (!strcmp (type_name, "int32"))
8749 klass = mono_defaults.int32_class;
8750 else if (!strcmp (type_name, "uint32"))
8751 klass = mono_defaults.uint32_class;
8752 else if (!strcmp (type_name, "int8"))
8753 klass = mono_defaults.sbyte_class;
8754 else if (!strcmp (type_name, "uint8"))
8755 klass = mono_defaults.byte_class;
8756 else if (!strcmp (type_name, "int16"))
8757 klass = mono_defaults.int16_class;
8758 else if (!strcmp (type_name, "uint16"))
8759 klass = mono_defaults.uint16_class;
8760 else if (!strcmp (type_name, "long"))
8761 klass = mono_defaults.int64_class;
8762 else if (!strcmp (type_name, "ulong"))
8763 klass = mono_defaults.uint64_class;
8764 else if (!strcmp (type_name, "float"))
8765 klass = mono_defaults.single_class;
8766 else if (!strcmp (type_name, "double"))
8767 klass = mono_defaults.double_class;
8768 else if (!strcmp (type_name, "object"))
8769 klass = mono_defaults.object_class;
8770 else if (!strcmp (type_name, "obj"))
8771 klass = mono_defaults.object_class;
8772 else if (!strcmp (type_name, "string"))
8773 klass = mono_defaults.string_class;
8774 else if (!strcmp (type_name, "bool"))
8775 klass = mono_defaults.boolean_class;
8776 else if (!strcmp (type_name, "boolean"))
8777 klass = mono_defaults.boolean_class;
8779 g_error ("%s", type_name);
8780 g_assert_not_reached ();
8782 return &klass->byval_arg;
8786 * LOCKING: Take the corlib image lock.
8788 MonoMethodSignature*
8789 mono_create_icall_signature (const char *sigstr)
8794 MonoMethodSignature *res, *res2;
8795 MonoImage *corlib = mono_defaults.corlib;
8797 mono_image_lock (corlib);
8798 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8799 mono_image_unlock (corlib);
8804 parts = g_strsplit (sigstr, " ", 256);
8813 res = mono_metadata_signature_alloc (corlib, len - 1);
8818 * Under windows, the default pinvoke calling convention is STDCALL but
8821 res->call_convention = MONO_CALL_C;
8824 res->ret = type_from_typename (parts [0]);
8825 for (i = 1; i < len; ++i) {
8826 res->params [i - 1] = type_from_typename (parts [i]);
8831 mono_image_lock (corlib);
8832 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8834 res = res2; /*Value is allocated in the image pool*/
8836 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8837 mono_image_unlock (corlib);
8843 mono_find_jit_icall_by_name (const char *name)
8845 MonoJitICallInfo *info;
8846 g_assert (jit_icall_hash_name);
8849 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8850 mono_icall_unlock ();
8855 mono_find_jit_icall_by_addr (gconstpointer addr)
8857 MonoJitICallInfo *info;
8858 g_assert (jit_icall_hash_addr);
8861 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8862 mono_icall_unlock ();
8868 * mono_get_jit_icall_info:
8870 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8871 * caller should access it while holding the icall lock.
8874 mono_get_jit_icall_info (void)
8876 return jit_icall_hash_name;
8880 * mono_lookup_jit_icall_symbol:
8882 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8885 mono_lookup_jit_icall_symbol (const char *name)
8887 MonoJitICallInfo *info;
8888 const char *res = NULL;
8891 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8893 res = info->c_symbol;
8894 mono_icall_unlock ();
8899 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8902 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8903 mono_icall_unlock ();
8907 * 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
8908 * icalls without wrappers in some cases.
8911 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8913 MonoJitICallInfo *info;
8920 if (!jit_icall_hash_name) {
8921 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8922 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8925 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8926 g_warning ("jit icall already defined \"%s\"\n", name);
8927 g_assert_not_reached ();
8930 info = g_new0 (MonoJitICallInfo, 1);
8935 info->c_symbol = c_symbol;
8936 info->no_raise = no_raise;
8939 info->wrapper = func;
8941 info->wrapper = NULL;
8944 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8945 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8947 mono_icall_unlock ();
8952 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8954 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);