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)
999 /* later make this configurable and per-arch */
1000 int min_size = 4096 * 4 * sizeof (void*);
1001 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
1002 /* if we have no info we are optimistic and assume there is enough room */
1005 current = (guint8 *)&stack_addr;
1006 if (current > stack_addr) {
1007 if ((current - stack_addr) < min_size)
1010 if (current - (stack_addr - stack_size) < min_size)
1016 ICALL_EXPORT MonoObject *
1017 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1020 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1021 mono_error_set_pending_exception (&error);
1027 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1031 MonoObject **values = NULL;
1034 gint32 result = (int)(gsize)mono_defaults.int32_class;
1035 MonoClassField* field;
1038 klass = mono_object_class (this_obj);
1040 if (mono_class_num_fields (klass) == 0)
1044 * Compute the starting value of the hashcode for fields of primitive
1045 * types, and return the remaining fields in an array to the managed side.
1046 * This way, we can avoid costly reflection operations in managed code.
1049 while ((field = mono_class_get_fields (klass, &iter))) {
1050 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1052 if (mono_field_is_deleted (field))
1054 /* FIXME: Add more types */
1055 switch (field->type->type) {
1057 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1059 case MONO_TYPE_STRING: {
1061 s = *(MonoString**)((guint8*)this_obj + field->offset);
1063 result ^= mono_string_hash (s);
1068 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1069 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1070 if (!is_ok (&error)) {
1071 mono_error_set_pending_exception (&error);
1074 values [count++] = o;
1080 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1081 if (mono_error_set_pending_exception (&error))
1083 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1084 for (i = 0; i < count; ++i)
1085 mono_array_setref (*fields, i, values [i]);
1092 ICALL_EXPORT MonoBoolean
1093 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1097 MonoObject **values = NULL;
1099 MonoClassField* field;
1103 MONO_CHECK_ARG_NULL (that, FALSE);
1105 if (this_obj->vtable != that->vtable)
1108 klass = mono_object_class (this_obj);
1110 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1111 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1114 * Do the comparison for fields of primitive type and return a result if
1115 * possible. Otherwise, return the remaining fields in an array to the
1116 * managed side. This way, we can avoid costly reflection operations in
1121 while ((field = mono_class_get_fields (klass, &iter))) {
1122 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1124 if (mono_field_is_deleted (field))
1126 /* FIXME: Add more types */
1127 switch (field->type->type) {
1130 case MONO_TYPE_BOOLEAN:
1131 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1136 case MONO_TYPE_CHAR:
1137 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1142 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1147 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1151 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1155 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1160 case MONO_TYPE_STRING: {
1161 MonoString *s1, *s2;
1162 guint32 s1len, s2len;
1163 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1164 s2 = *(MonoString**)((guint8*)that + field->offset);
1167 if ((s1 == NULL) || (s2 == NULL))
1169 s1len = mono_string_length (s1);
1170 s2len = mono_string_length (s2);
1174 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1180 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1181 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1182 if (!is_ok (&error)) {
1183 mono_error_set_pending_exception (&error);
1186 values [count++] = o;
1187 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1188 if (!is_ok (&error)) {
1189 mono_error_set_pending_exception (&error);
1192 values [count++] = o;
1195 if (klass->enumtype)
1196 /* enums only have one non-static field */
1202 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1203 if (mono_error_set_pending_exception (&error))
1205 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1206 for (i = 0; i < count; ++i)
1207 mono_array_setref_fast (*fields, i, values [i]);
1214 ICALL_EXPORT MonoReflectionType *
1215 ves_icall_System_Object_GetType (MonoObject *obj)
1218 MonoReflectionType *ret;
1219 #ifndef DISABLE_REMOTING
1220 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1221 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1224 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1226 mono_error_set_pending_exception (&error);
1231 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1233 MonoMethod **dest = (MonoMethod **)data;
1235 /* skip unmanaged frames */
1240 if (!strcmp (m->klass->name_space, "System.Reflection"))
1249 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1251 MonoMethod **dest = (MonoMethod **)data;
1253 /* skip unmanaged frames */
1257 if (m->wrapper_type != MONO_WRAPPER_NONE)
1265 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1276 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1278 MonoMethod **dest = (MonoMethod **)data;
1280 /* skip unmanaged frames */
1284 if (m->wrapper_type != MONO_WRAPPER_NONE)
1292 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1293 || (!strcmp (m->klass->name_space, "System"))))
1303 static MonoReflectionType *
1304 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1306 MonoMethod *m, *dest;
1308 MonoType *type = NULL;
1309 MonoAssembly *assembly = NULL;
1310 gboolean type_resolve = FALSE;
1311 MonoImage *rootimage = NULL;
1313 mono_error_init (error);
1316 * We must compute the calling assembly as type loading must happen under a metadata context.
1317 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1318 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1320 m = mono_method_get_last_managed ();
1322 if (m && m->klass->image != mono_defaults.corlib) {
1323 /* Happens with inlining */
1325 /* Ugly hack: type_from_parsed_name is called from
1326 * System.Type.internal_from_name, which is called most
1327 * directly from System.Type.GetType(string,bool,bool) but
1328 * also indirectly from places such as
1329 * System.Type.GetType(string,func,func) (via
1330 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1331 * so we need to skip over all of those to find the true caller.
1333 * It would be nice if we had stack marks.
1335 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1341 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1342 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1343 * to crash. This only seems to happen in some strange remoting
1344 * scenarios and I was unable to figure out what's happening there.
1345 * Dec 10, 2005 - Martin.
1349 assembly = dest->klass->image->assembly;
1350 type_resolve = TRUE;
1351 rootimage = assembly->image;
1353 g_warning (G_STRLOC);
1356 if (info->assembly.name)
1357 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1360 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1361 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1362 return_val_if_nok (error, NULL);
1366 // Say we're looking for System.Generic.Dict<int, Local>
1367 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1368 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1369 // is messed up when we go to construct the Local as the type arg...
1371 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1372 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1373 if (!info->assembly.name && !type) {
1375 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1376 return_val_if_nok (error, NULL);
1378 if (assembly && !type && type_resolve) {
1379 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1380 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1381 return_val_if_nok (error, NULL);
1387 return mono_type_get_object_checked (mono_domain_get (), type, error);
1390 ICALL_EXPORT MonoReflectionType*
1391 ves_icall_System_Type_internal_from_name (MonoString *name,
1392 MonoBoolean throwOnError,
1393 MonoBoolean ignoreCase)
1396 MonoTypeNameParse info;
1397 MonoReflectionType *type = NULL;
1400 char *str = mono_string_to_utf8_checked (name, &error);
1401 if (!is_ok (&error))
1404 parsedOk = mono_reflection_parse_type (str, &info);
1406 /* mono_reflection_parse_type() mangles the string */
1408 mono_reflection_free_type_info (&info);
1410 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1414 type = type_from_parsed_name (&info, ignoreCase, &error);
1416 mono_reflection_free_type_info (&info);
1418 if (!is_ok (&error))
1423 mono_error_set_type_load_name (&error, g_strdup (str), g_strdup (""), "");
1430 if (!is_ok (&error)) {
1432 mono_error_set_pending_exception (&error);
1434 mono_error_cleanup (&error);
1442 ICALL_EXPORT MonoReflectionType*
1443 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1446 MonoReflectionType *ret;
1447 MonoDomain *domain = mono_domain_get ();
1449 ret = mono_type_get_object_checked (domain, handle, &error);
1450 mono_error_set_pending_exception (&error);
1455 ICALL_EXPORT MonoType*
1456 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1458 return mono_class_get_type (klass);
1462 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1464 g_ptr_array_free (ptr_array, TRUE);
1468 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1474 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1477 char *res = mono_string_to_utf8_checked (s, &error);
1478 mono_error_set_pending_exception (&error);
1482 /* System.TypeCode */
1501 TYPECODE_STRING = 18
1504 ICALL_EXPORT guint32
1505 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1507 int t = type->type->type;
1509 if (type->type->byref)
1510 return TYPECODE_OBJECT;
1514 case MONO_TYPE_VOID:
1515 return TYPECODE_OBJECT;
1516 case MONO_TYPE_BOOLEAN:
1517 return TYPECODE_BOOLEAN;
1519 return TYPECODE_BYTE;
1521 return TYPECODE_SBYTE;
1523 return TYPECODE_UINT16;
1525 return TYPECODE_INT16;
1526 case MONO_TYPE_CHAR:
1527 return TYPECODE_CHAR;
1531 return TYPECODE_OBJECT;
1533 return TYPECODE_UINT32;
1535 return TYPECODE_INT32;
1537 return TYPECODE_UINT64;
1539 return TYPECODE_INT64;
1541 return TYPECODE_SINGLE;
1543 return TYPECODE_DOUBLE;
1544 case MONO_TYPE_VALUETYPE: {
1545 MonoClass *klass = type->type->data.klass;
1547 if (klass->enumtype) {
1548 t = mono_class_enum_basetype (klass)->type;
1550 } else if (mono_is_corlib_image (klass->image)) {
1551 if (strcmp (klass->name_space, "System") == 0) {
1552 if (strcmp (klass->name, "Decimal") == 0)
1553 return TYPECODE_DECIMAL;
1554 else if (strcmp (klass->name, "DateTime") == 0)
1555 return TYPECODE_DATETIME;
1558 return TYPECODE_OBJECT;
1560 case MONO_TYPE_STRING:
1561 return TYPECODE_STRING;
1562 case MONO_TYPE_SZARRAY:
1563 case MONO_TYPE_ARRAY:
1564 case MONO_TYPE_OBJECT:
1566 case MONO_TYPE_MVAR:
1567 case MONO_TYPE_TYPEDBYREF:
1568 return TYPECODE_OBJECT;
1569 case MONO_TYPE_CLASS:
1571 MonoClass *klass = type->type->data.klass;
1572 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1573 if (strcmp (klass->name, "DBNull") == 0)
1574 return TYPECODE_DBNULL;
1577 return TYPECODE_OBJECT;
1578 case MONO_TYPE_GENERICINST:
1579 return TYPECODE_OBJECT;
1581 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1587 mono_type_is_primitive (MonoType *type)
1589 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1590 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1594 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1596 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1597 return mono_class_enum_basetype (type->data.klass);
1598 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1599 return mono_class_enum_basetype (type->data.generic_class->container_class);
1603 ICALL_EXPORT guint32
1604 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1609 g_assert (type != NULL);
1611 klass = mono_class_from_mono_type (type->type);
1612 klassc = mono_class_from_mono_type (c->type);
1614 if (type->type->byref ^ c->type->byref)
1617 if (type->type->byref) {
1618 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1619 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1621 klass = mono_class_from_mono_type (t);
1622 klassc = mono_class_from_mono_type (ot);
1624 if (mono_type_is_primitive (t)) {
1625 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1626 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1627 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1628 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1629 return t->type == ot->type;
1631 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1634 if (klass->valuetype)
1635 return klass == klassc;
1636 return klass->valuetype == klassc->valuetype;
1639 return mono_class_is_assignable_from (klass, klassc);
1642 ICALL_EXPORT guint32
1643 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1646 MonoClass *klass = mono_class_from_mono_type (type->type);
1647 mono_class_init_checked (klass, &error);
1648 if (!is_ok (&error)) {
1649 mono_error_set_pending_exception (&error);
1652 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1653 mono_error_set_pending_exception (&error);
1657 ICALL_EXPORT guint32
1658 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1660 MonoClass *klass = mono_class_from_mono_type (type->type);
1661 return klass->flags;
1664 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1665 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1668 MonoClass *klass = field->field->parent;
1669 MonoMarshalType *info;
1673 if (klass->generic_container ||
1674 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1677 ftype = mono_field_get_type (field->field);
1678 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1681 info = mono_marshal_load_type_info (klass);
1683 for (i = 0; i < info->num_fields; ++i) {
1684 if (info->fields [i].field == field->field) {
1685 if (!info->fields [i].mspec)
1688 MonoReflectionMarshalAsAttribute* obj;
1689 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1690 if (!mono_error_ok (&error))
1691 mono_error_set_pending_exception (&error);
1700 ICALL_EXPORT MonoReflectionField*
1701 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1704 gboolean found = FALSE;
1710 klass = handle->parent;
1712 klass = mono_class_from_mono_type (type);
1714 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1717 /* The managed code will throw the exception */
1721 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1722 mono_error_set_pending_exception (&error);
1726 ICALL_EXPORT MonoReflectionEvent*
1727 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1735 klass = handle->parent;
1737 klass = mono_class_from_mono_type (type);
1739 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1741 /* Managed code will throw an exception */
1745 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1746 mono_error_set_pending_exception (&error);
1751 ICALL_EXPORT MonoReflectionProperty*
1752 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1760 klass = handle->parent;
1762 klass = mono_class_from_mono_type (type);
1764 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1766 /* Managed code will throw an exception */
1770 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1771 mono_error_set_pending_exception (&error);
1775 ICALL_EXPORT MonoArray*
1776 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1779 MonoType *type = mono_field_get_type_checked (field->field, &error);
1782 if (!mono_error_ok (&error)) {
1783 mono_error_set_pending_exception (&error);
1787 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1788 mono_error_set_pending_exception (&error);
1793 vell_icall_get_method_attributes (MonoMethod *method)
1795 return method->flags;
1799 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1802 MonoReflectionType *rt;
1803 MonoDomain *domain = mono_domain_get ();
1804 MonoMethodSignature* sig;
1806 sig = mono_method_signature_checked (method, &error);
1807 if (!mono_error_ok (&error)) {
1808 mono_error_set_pending_exception (&error);
1812 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1813 if (!mono_error_ok (&error)) {
1814 mono_error_set_pending_exception (&error);
1818 MONO_STRUCT_SETREF (info, parent, rt);
1820 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1821 if (!mono_error_ok (&error)) {
1822 mono_error_set_pending_exception (&error);
1826 MONO_STRUCT_SETREF (info, ret, rt);
1828 info->attrs = method->flags;
1829 info->implattrs = method->iflags;
1830 if (sig->call_convention == MONO_CALL_DEFAULT)
1831 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1833 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1838 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1841 ICALL_EXPORT MonoArray*
1842 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1845 MonoDomain *domain = mono_domain_get ();
1847 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1848 mono_error_set_pending_exception (&error);
1852 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1853 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1856 MonoDomain *domain = mono_domain_get ();
1857 MonoReflectionMarshalAsAttribute* res = NULL;
1858 MonoMarshalSpec **mspecs;
1861 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1862 mono_method_get_marshal_info (method, mspecs);
1865 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1866 if (!mono_error_ok (&error)) {
1867 mono_error_set_pending_exception (&error);
1872 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1874 mono_metadata_free_marshal_spec (mspecs [i]);
1881 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1883 MonoClass *parent = field->field->parent;
1884 if (!parent->size_inited)
1885 mono_class_init (parent);
1886 mono_class_setup_fields_locking (parent);
1888 return field->field->offset - sizeof (MonoObject);
1891 ICALL_EXPORT MonoReflectionType*
1892 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1895 MonoReflectionType *ret;
1898 parent = declaring? field->field->parent: field->klass;
1900 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1901 mono_error_set_pending_exception (&error);
1907 ICALL_EXPORT MonoObject *
1908 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1911 MonoClass *fklass = field->klass;
1912 MonoClassField *cf = field->field;
1913 MonoDomain *domain = mono_object_domain (field);
1915 if (fklass->image->assembly->ref_only) {
1916 mono_set_pending_exception (mono_get_exception_invalid_operation (
1917 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1921 if (mono_security_core_clr_enabled () &&
1922 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1923 mono_error_set_pending_exception (&error);
1927 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1928 mono_error_set_pending_exception (&error);
1933 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1936 MonoClassField *cf = field->field;
1940 if (field->klass->image->assembly->ref_only) {
1941 mono_set_pending_exception (mono_get_exception_invalid_operation (
1942 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1946 if (mono_security_core_clr_enabled () &&
1947 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1948 mono_error_set_pending_exception (&error);
1952 type = mono_field_get_type_checked (cf, &error);
1953 if (!mono_error_ok (&error)) {
1954 mono_error_set_pending_exception (&error);
1958 v = (gchar *) value;
1960 switch (type->type) {
1963 case MONO_TYPE_BOOLEAN:
1966 case MONO_TYPE_CHAR:
1975 case MONO_TYPE_VALUETYPE:
1978 v += sizeof (MonoObject);
1980 case MONO_TYPE_STRING:
1981 case MONO_TYPE_OBJECT:
1982 case MONO_TYPE_CLASS:
1983 case MONO_TYPE_ARRAY:
1984 case MONO_TYPE_SZARRAY:
1987 case MONO_TYPE_GENERICINST: {
1988 MonoGenericClass *gclass = type->data.generic_class;
1989 g_assert (!gclass->context.class_inst->is_open);
1991 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1992 MonoClass *nklass = mono_class_from_mono_type (type);
1993 MonoObject *nullable;
1996 * Convert the boxed vtype into a Nullable structure.
1997 * This is complicated by the fact that Nullables have
1998 * a variable structure.
2000 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2001 if (!mono_error_ok (&error)) {
2002 mono_error_set_pending_exception (&error);
2006 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2008 v = (gchar *)mono_object_unbox (nullable);
2011 if (gclass->container_class->valuetype && (v != NULL))
2012 v += sizeof (MonoObject);
2016 g_error ("type 0x%x not handled in "
2017 "ves_icall_FieldInfo_SetValueInternal", type->type);
2022 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2023 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2024 if (!is_ok (&error)) {
2025 mono_error_set_pending_exception (&error);
2028 if (!vtable->initialized) {
2029 if (!mono_runtime_class_init_full (vtable, &error)) {
2030 mono_error_set_pending_exception (&error);
2034 mono_field_static_set_value (vtable, cf, v);
2036 mono_field_set_value (obj, cf, v);
2041 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2050 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2051 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2055 if (MONO_TYPE_IS_REFERENCE (f->type))
2056 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2058 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2061 ICALL_EXPORT MonoObject *
2062 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2064 MonoObject *o = NULL;
2065 MonoClassField *field = rfield->field;
2067 MonoDomain *domain = mono_object_domain (rfield);
2069 MonoTypeEnum def_type;
2070 const char *def_value;
2074 mono_class_init (field->parent);
2076 t = mono_field_get_type_checked (field, &error);
2077 if (!mono_error_ok (&error)) {
2078 mono_error_set_pending_exception (&error);
2082 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2083 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2087 if (image_is_dynamic (field->parent->image)) {
2088 MonoClass *klass = field->parent;
2089 int fidx = field - klass->fields;
2091 g_assert (fidx >= 0 && fidx < klass->field.count);
2092 g_assert (klass->ext);
2093 g_assert (klass->ext->field_def_values);
2094 def_type = klass->ext->field_def_values [fidx].def_type;
2095 def_value = klass->ext->field_def_values [fidx].data;
2096 if (def_type == MONO_TYPE_END) {
2097 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2101 def_value = mono_class_get_field_default_value (field, &def_type);
2102 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2104 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2109 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2113 case MONO_TYPE_BOOLEAN:
2116 case MONO_TYPE_CHAR:
2124 case MONO_TYPE_R8: {
2127 /* boxed value type */
2128 t = g_new0 (MonoType, 1);
2130 klass = mono_class_from_mono_type (t);
2132 o = mono_object_new_checked (domain, klass, &error);
2133 if (!mono_error_ok (&error)) {
2134 mono_error_set_pending_exception (&error);
2137 v = ((gchar *) o) + sizeof (MonoObject);
2138 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2139 if (mono_error_set_pending_exception (&error))
2143 case MONO_TYPE_STRING:
2144 case MONO_TYPE_CLASS:
2145 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2146 if (mono_error_set_pending_exception (&error))
2150 g_assert_not_reached ();
2156 ICALL_EXPORT MonoReflectionType*
2157 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2160 MonoReflectionType *ret;
2163 type = mono_field_get_type_checked (ref_field->field, &error);
2164 if (!mono_error_ok (&error)) {
2165 mono_error_set_pending_exception (&error);
2169 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2170 if (!mono_error_ok (&error)) {
2171 mono_error_set_pending_exception (&error);
2178 /* From MonoProperty.cs */
2180 PInfo_Attributes = 1,
2181 PInfo_GetMethod = 1 << 1,
2182 PInfo_SetMethod = 1 << 2,
2183 PInfo_ReflectedType = 1 << 3,
2184 PInfo_DeclaringType = 1 << 4,
2189 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2192 MonoReflectionType *rt;
2193 MonoReflectionMethod *rm;
2194 MonoDomain *domain = mono_object_domain (property);
2195 const MonoProperty *pproperty = property->property;
2197 if ((req_info & PInfo_ReflectedType) != 0) {
2198 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2199 if (mono_error_set_pending_exception (&error))
2202 MONO_STRUCT_SETREF (info, parent, rt);
2204 if ((req_info & PInfo_DeclaringType) != 0) {
2205 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2206 if (mono_error_set_pending_exception (&error))
2209 MONO_STRUCT_SETREF (info, declaring_type, rt);
2212 if ((req_info & PInfo_Name) != 0)
2213 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2215 if ((req_info & PInfo_Attributes) != 0)
2216 info->attrs = pproperty->attrs;
2218 if ((req_info & PInfo_GetMethod) != 0) {
2219 if (pproperty->get &&
2220 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2221 pproperty->get->klass == property->klass)) {
2222 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2223 if (mono_error_set_pending_exception (&error))
2229 MONO_STRUCT_SETREF (info, get, rm);
2231 if ((req_info & PInfo_SetMethod) != 0) {
2232 if (pproperty->set &&
2233 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2234 pproperty->set->klass == property->klass)) {
2235 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2236 if (mono_error_set_pending_exception (&error))
2242 MONO_STRUCT_SETREF (info, set, rm);
2245 * There may be other methods defined for properties, though, it seems they are not exposed
2246 * in the reflection API
2251 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2254 MonoReflectionType *rt;
2255 MonoReflectionMethod *rm;
2256 MonoDomain *domain = mono_object_domain (event);
2258 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2259 if (mono_error_set_pending_exception (&error))
2262 MONO_STRUCT_SETREF (info, reflected_type, rt);
2264 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2265 if (mono_error_set_pending_exception (&error))
2268 MONO_STRUCT_SETREF (info, declaring_type, rt);
2270 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2271 info->attrs = event->event->attrs;
2273 if (event->event->add) {
2274 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2275 if (mono_error_set_pending_exception (&error))
2281 MONO_STRUCT_SETREF (info, add_method, rm);
2283 if (event->event->remove) {
2284 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2285 if (mono_error_set_pending_exception (&error))
2291 MONO_STRUCT_SETREF (info, remove_method, rm);
2293 if (event->event->raise) {
2294 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2295 if (mono_error_set_pending_exception (&error))
2301 MONO_STRUCT_SETREF (info, raise_method, rm);
2303 #ifndef MONO_SMALL_CONFIG
2304 if (event->event->other) {
2306 while (event->event->other [n])
2308 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2309 if (mono_error_set_pending_exception (&error))
2311 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2313 for (i = 0; i < n; i++) {
2314 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2315 if (mono_error_set_pending_exception (&error))
2317 mono_array_setref (info->other_methods, i, rm);
2324 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2329 mono_class_setup_interfaces (klass, error);
2330 if (!mono_error_ok (error))
2333 for (i = 0; i < klass->interface_count; i++) {
2334 ic = klass->interfaces [i];
2335 g_hash_table_insert (ifaces, ic, ic);
2337 collect_interfaces (ic, ifaces, error);
2338 if (!mono_error_ok (error))
2344 MonoArray *iface_array;
2345 MonoGenericContext *context;
2349 } FillIfaceArrayData;
2352 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2354 MonoReflectionType *rt;
2355 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2356 MonoClass *ic = (MonoClass *)key;
2357 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2359 if (!mono_error_ok (data->error))
2362 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2363 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2364 if (!mono_error_ok (data->error))
2368 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2369 if (!mono_error_ok (data->error))
2372 mono_array_setref (data->iface_array, data->next_idx++, rt);
2375 mono_metadata_free_type (inflated);
2379 get_interfaces_hash (gconstpointer v1)
2381 MonoClass *k = (MonoClass*)v1;
2383 return k->type_token;
2386 ICALL_EXPORT MonoArray*
2387 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2390 MonoClass *klass = mono_class_from_mono_type (type->type);
2392 FillIfaceArrayData data = { 0 };
2395 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2397 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2398 data.context = mono_class_get_context (klass);
2399 klass = klass->generic_class->container_class;
2402 for (parent = klass; parent; parent = parent->parent) {
2403 mono_class_setup_interfaces (parent, &error);
2404 if (!mono_error_ok (&error))
2406 collect_interfaces (parent, iface_hash, &error);
2407 if (!mono_error_ok (&error))
2411 data.error = &error;
2412 data.domain = mono_object_domain (type);
2414 len = g_hash_table_size (iface_hash);
2416 g_hash_table_destroy (iface_hash);
2417 if (!data.domain->empty_types) {
2418 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2419 if (!is_ok (&error))
2422 return data.domain->empty_types;
2425 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2426 if (!is_ok (&error))
2428 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2429 if (!mono_error_ok (&error))
2432 g_hash_table_destroy (iface_hash);
2433 return data.iface_array;
2436 g_hash_table_destroy (iface_hash);
2437 mono_error_set_pending_exception (&error);
2442 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2444 gboolean variance_used;
2445 MonoClass *klass = mono_class_from_mono_type (type->type);
2446 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2447 MonoReflectionMethod *member;
2450 int i = 0, len, ioffset;
2454 mono_class_init_checked (klass, &error);
2455 if (mono_error_set_pending_exception (&error))
2457 mono_class_init_checked (iclass, &error);
2458 if (mono_error_set_pending_exception (&error))
2461 mono_class_setup_vtable (klass);
2463 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2467 len = mono_class_num_methods (iclass);
2468 domain = mono_object_domain (type);
2469 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2470 if (mono_error_set_pending_exception (&error))
2472 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2473 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2474 if (mono_error_set_pending_exception (&error))
2476 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2478 while ((method = mono_class_get_methods (iclass, &iter))) {
2479 member = mono_method_get_object_checked (domain, method, iclass, &error);
2480 if (mono_error_set_pending_exception (&error))
2482 mono_array_setref (*methods, i, member);
2483 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2484 if (mono_error_set_pending_exception (&error))
2486 mono_array_setref (*targets, i, member);
2493 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2496 MonoClass *klass = mono_class_from_mono_type (type->type);
2498 mono_class_init_checked (klass, &error);
2499 if (mono_error_set_pending_exception (&error))
2502 if (image_is_dynamic (klass->image)) {
2503 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2504 *packing = tb->packing_size;
2505 *size = tb->class_size;
2507 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2511 ICALL_EXPORT MonoReflectionType*
2512 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2515 MonoReflectionType *ret;
2518 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2519 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2520 mono_error_set_pending_exception (&error);
2524 klass = mono_class_from_mono_type (type->type);
2525 mono_class_init_checked (klass, &error);
2526 if (mono_error_set_pending_exception (&error))
2530 // GetElementType should only return a type for:
2531 // Array Pointer PassedByRef
2532 if (type->type->byref)
2533 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2534 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2535 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2536 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2537 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2541 mono_error_set_pending_exception (&error);
2546 ICALL_EXPORT MonoReflectionType*
2547 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2550 MonoReflectionType *ret;
2552 if (type->type->byref)
2555 MonoClass *klass = mono_class_from_mono_type (type->type);
2559 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2560 mono_error_set_pending_exception (&error);
2565 ICALL_EXPORT MonoBoolean
2566 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2568 return type->type->type == MONO_TYPE_PTR;
2571 ICALL_EXPORT MonoBoolean
2572 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2574 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)));
2577 ICALL_EXPORT MonoBoolean
2578 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2580 return type->type->byref;
2583 ICALL_EXPORT MonoBoolean
2584 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2587 MonoClass *klass = mono_class_from_mono_type (type->type);
2588 mono_class_init_checked (klass, &error);
2589 if (mono_error_set_pending_exception (&error))
2592 return mono_class_is_com_object (klass);
2595 ICALL_EXPORT guint32
2596 ves_icall_reflection_get_token (MonoObject* obj)
2599 guint32 result = mono_reflection_get_token_checked (obj, &error);
2600 mono_error_set_pending_exception (&error);
2604 ICALL_EXPORT MonoReflectionModule*
2605 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2608 MonoReflectionModule *result = NULL;
2609 MonoClass *klass = mono_class_from_mono_type (type->type);
2610 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2611 mono_error_set_pending_exception (&error);
2615 ICALL_EXPORT MonoReflectionAssembly*
2616 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2619 MonoDomain *domain = mono_domain_get ();
2620 MonoClass *klass = mono_class_from_mono_type (type->type);
2621 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2622 mono_error_set_pending_exception (&error);
2626 ICALL_EXPORT MonoReflectionType*
2627 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2630 MonoReflectionType *ret;
2631 MonoDomain *domain = mono_domain_get ();
2634 if (type->type->byref)
2636 if (type->type->type == MONO_TYPE_VAR) {
2637 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2638 klass = param ? param->owner.klass : NULL;
2639 } else if (type->type->type == MONO_TYPE_MVAR) {
2640 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2641 klass = param ? param->owner.method->klass : NULL;
2643 klass = mono_class_from_mono_type (type->type)->nested_in;
2649 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2650 mono_error_set_pending_exception (&error);
2655 ICALL_EXPORT MonoStringHandle
2656 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2658 MonoDomain *domain = mono_domain_get ();
2659 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2660 MonoClass *klass = mono_class_from_mono_type (type);
2663 char *n = g_strdup_printf ("%s&", klass->name);
2664 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2670 return mono_string_new_handle (domain, klass->name, error);
2674 ICALL_EXPORT MonoStringHandle
2675 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2677 MonoDomain *domain = mono_domain_get ();
2678 MonoClass *klass = mono_class_from_mono_type_handle (type);
2680 while (klass->nested_in)
2681 klass = klass->nested_in;
2683 if (klass->name_space [0] == '\0')
2684 return NULL_HANDLE_STRING;
2686 return mono_string_new_handle (domain, klass->name_space, error);
2690 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2694 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2695 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2699 klass = mono_class_from_mono_type (type->type);
2705 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2707 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2710 ICALL_EXPORT MonoArray*
2711 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2714 MonoReflectionType *rt;
2716 MonoClass *klass, *pklass;
2717 MonoDomain *domain = mono_object_domain (type);
2720 klass = mono_class_from_mono_type (type->type);
2722 if (klass->generic_container) {
2723 MonoGenericContainer *container = klass->generic_container;
2724 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2725 if (mono_error_set_pending_exception (&error))
2727 for (i = 0; i < container->type_argc; ++i) {
2728 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2730 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2731 if (mono_error_set_pending_exception (&error))
2734 mono_array_setref (res, i, rt);
2736 } else if (klass->generic_class) {
2737 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2738 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2739 if (mono_error_set_pending_exception (&error))
2741 for (i = 0; i < inst->type_argc; ++i) {
2742 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2743 if (mono_error_set_pending_exception (&error))
2746 mono_array_setref (res, i, rt);
2754 ICALL_EXPORT gboolean
2755 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2759 if (!IS_MONOTYPE (type))
2762 if (type->type->byref)
2765 klass = mono_class_from_mono_type (type->type);
2766 return klass->generic_container != NULL;
2769 ICALL_EXPORT MonoReflectionType*
2770 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2773 MonoReflectionType *ret;
2776 if (type->type->byref)
2779 klass = mono_class_from_mono_type (type->type);
2781 if (klass->generic_container) {
2782 return type; /* check this one */
2784 if (klass->generic_class) {
2785 MonoClass *generic_class = klass->generic_class->container_class;
2788 tb = mono_class_get_ref_info (generic_class);
2790 if (generic_class->wastypebuilder && tb)
2791 return (MonoReflectionType *)tb;
2793 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2794 mono_error_set_pending_exception (&error);
2802 ICALL_EXPORT MonoReflectionType*
2803 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2806 MonoReflectionType *ret;
2808 MonoType *geninst, **types;
2811 g_assert (IS_MONOTYPE (type));
2812 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2813 if (mono_error_set_pending_exception (&error))
2816 count = mono_array_length (type_array);
2817 types = g_new0 (MonoType *, count);
2819 for (i = 0; i < count; i++) {
2820 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2821 types [i] = t->type;
2824 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2827 mono_error_set_pending_exception (&error);
2831 klass = mono_class_from_mono_type (geninst);
2833 /*we might inflate to the GTD*/
2834 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2835 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2839 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2840 mono_error_set_pending_exception (&error);
2845 ICALL_EXPORT gboolean
2846 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2850 if (!IS_MONOTYPE (type))
2853 if (type->type->byref)
2856 klass = mono_class_from_mono_type (type->type);
2857 return klass->generic_class != NULL || klass->generic_container != NULL;
2861 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2863 if (!IS_MONOTYPE (type))
2866 if (is_generic_parameter (type->type))
2867 return mono_type_get_generic_param_num (type->type);
2871 ICALL_EXPORT MonoGenericParamInfo *
2872 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2874 return mono_generic_param_info (type->type->data.generic_param);
2877 ICALL_EXPORT MonoBoolean
2878 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2880 return is_generic_parameter (type->type);
2883 ICALL_EXPORT MonoReflectionMethod*
2884 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2885 MonoReflectionMethod* generic)
2892 MonoReflectionMethod *ret = NULL;
2894 domain = ((MonoObject *)type)->vtable->domain;
2896 klass = mono_class_from_mono_type (type->type);
2897 mono_class_init_checked (klass, &error);
2898 if (mono_error_set_pending_exception (&error))
2902 while ((method = mono_class_get_methods (klass, &iter))) {
2903 if (method->token == generic->method->token) {
2904 ret = mono_method_get_object_checked (domain, method, klass, &error);
2905 if (mono_error_set_pending_exception (&error))
2913 ICALL_EXPORT MonoReflectionMethod *
2914 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2917 MonoType *type = ref_type->type;
2919 MonoReflectionMethod *ret = NULL;
2921 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2922 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2925 if (type->type == MONO_TYPE_VAR)
2928 method = mono_type_get_generic_param_owner (type)->owner.method;
2931 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2932 if (!mono_error_ok (&error))
2933 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2937 ICALL_EXPORT MonoBoolean
2938 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2940 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2944 ICALL_EXPORT MonoBoolean
2945 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2947 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2952 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2954 MonoDomain *domain = mono_domain_get ();
2955 MonoImage *image = method->method->klass->image;
2956 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2957 MonoTableInfo *tables = image->tables;
2958 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2959 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2960 guint32 im_cols [MONO_IMPLMAP_SIZE];
2961 guint32 scope_token;
2962 const char *import = NULL;
2963 const char *scope = NULL;
2965 if (image_is_dynamic (image)) {
2966 MonoReflectionMethodAux *method_aux =
2967 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2969 import = method_aux->dllentry;
2970 scope = method_aux->dll;
2973 if (!import || !scope) {
2974 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2979 if (piinfo->implmap_idx) {
2980 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2982 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2983 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2984 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2985 scope = mono_metadata_string_heap (image, scope_token);
2989 *flags = piinfo->piflags;
2990 *entry_point = mono_string_new (domain, import);
2991 *dll_name = mono_string_new (domain, scope);
2994 ICALL_EXPORT MonoReflectionMethod *
2995 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2997 MonoMethodInflated *imethod;
2999 MonoReflectionMethod *ret = NULL;
3002 if (method->method->is_generic)
3005 if (!method->method->is_inflated)
3008 imethod = (MonoMethodInflated *) method->method;
3010 result = imethod->declaring;
3011 /* Not a generic method. */
3012 if (!result->is_generic)
3015 if (image_is_dynamic (method->method->klass->image)) {
3016 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3017 MonoReflectionMethod *res;
3020 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3021 * the dynamic case as well ?
3023 mono_image_lock ((MonoImage*)image);
3024 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3025 mono_image_unlock ((MonoImage*)image);
3031 if (imethod->context.class_inst) {
3032 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3033 /*Generic methods gets the context of the GTD.*/
3034 if (mono_class_get_context (klass)) {
3035 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3036 if (!mono_error_ok (&error))
3041 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3043 if (!mono_error_ok (&error))
3044 mono_error_set_pending_exception (&error);
3048 ICALL_EXPORT gboolean
3049 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3051 return mono_method_signature (method->method)->generic_param_count != 0;
3054 ICALL_EXPORT gboolean
3055 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3057 return method->method->is_generic;
3060 ICALL_EXPORT MonoArray*
3061 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3064 MonoReflectionType *rt;
3069 domain = mono_object_domain (method);
3071 if (method->method->is_inflated) {
3072 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3075 count = inst->type_argc;
3076 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3077 if (mono_error_set_pending_exception (&error))
3080 for (i = 0; i < count; i++) {
3081 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3082 if (mono_error_set_pending_exception (&error))
3085 mono_array_setref (res, i, rt);
3092 count = mono_method_signature (method->method)->generic_param_count;
3093 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3094 if (mono_error_set_pending_exception (&error))
3097 for (i = 0; i < count; i++) {
3098 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3099 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3100 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3102 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3103 if (mono_error_set_pending_exception (&error))
3106 mono_array_setref (res, i, rt);
3112 ICALL_EXPORT MonoObject *
3113 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3117 * Invoke from reflection is supposed to always be a virtual call (the API
3118 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3119 * greater flexibility.
3121 MonoMethod *m = method->method;
3122 MonoMethodSignature *sig = mono_method_signature (m);
3125 void *obj = this_arg;
3129 if (mono_security_core_clr_enabled () &&
3130 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3131 mono_error_set_pending_exception (&error);
3135 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3136 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3137 mono_error_cleanup (&error); /* FIXME does this make sense? */
3138 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3143 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3144 if (!is_ok (&error)) {
3145 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3148 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3149 char *target_name = mono_type_get_full_name (m->klass);
3150 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3151 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3153 g_free (target_name);
3157 m = mono_object_get_virtual_method (this_arg, m);
3158 /* must pass the pointer to the value for valuetype methods */
3159 if (m->klass->valuetype)
3160 obj = mono_object_unbox (this_arg);
3161 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3162 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3167 if (sig->ret->byref) {
3168 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"));
3172 pcount = params? mono_array_length (params): 0;
3173 if (pcount != sig->param_count) {
3174 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3178 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3179 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."));
3183 image = m->klass->image;
3184 if (image->assembly->ref_only) {
3185 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."));
3189 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3190 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3194 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3198 intptr_t *lower_bounds;
3199 pcount = mono_array_length (params);
3200 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3201 /* Note: the synthetized array .ctors have int32 as argument type */
3202 for (i = 0; i < pcount; ++i)
3203 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3205 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3206 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3207 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3208 if (!mono_error_ok (&error)) {
3209 mono_error_set_pending_exception (&error);
3213 for (i = 0; i < mono_array_length (arr); ++i) {
3214 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3215 if (!mono_error_ok (&error)) {
3216 mono_error_set_pending_exception (&error);
3219 mono_array_setref_fast (arr, i, subarray);
3221 return (MonoObject*)arr;
3224 if (m->klass->rank == pcount) {
3225 /* Only lengths provided. */
3226 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3227 if (!mono_error_ok (&error)) {
3228 mono_error_set_pending_exception (&error);
3232 return (MonoObject*)arr;
3234 g_assert (pcount == (m->klass->rank * 2));
3235 /* The arguments are lower-bound-length pairs */
3236 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3238 for (i = 0; i < pcount / 2; ++i) {
3239 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3240 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3243 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3244 if (!mono_error_ok (&error)) {
3245 mono_error_set_pending_exception (&error);
3249 return (MonoObject*)arr;
3252 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3253 mono_error_set_pending_exception (&error);
3257 #ifndef DISABLE_REMOTING
3258 ICALL_EXPORT MonoObject *
3259 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3262 MonoDomain *domain = mono_object_domain (method);
3263 MonoMethod *m = method->method;
3264 MonoMethodSignature *sig = mono_method_signature (m);
3265 MonoArray *out_args;
3267 int i, j, outarg_count = 0;
3269 if (m->klass == mono_defaults.object_class) {
3270 if (!strcmp (m->name, "FieldGetter")) {
3271 MonoClass *k = this_arg->vtable->klass;
3275 /* If this is a proxy, then it must be a CBO */
3276 if (k == mono_defaults.transparent_proxy_class) {
3277 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3278 this_arg = tp->rp->unwrapped_server;
3279 g_assert (this_arg);
3280 k = this_arg->vtable->klass;
3283 name = mono_array_get (params, MonoString *, 1);
3284 str = mono_string_to_utf8_checked (name, &error);
3285 if (mono_error_set_pending_exception (&error))
3289 MonoClassField* field = mono_class_get_field_from_name (k, str);
3292 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3293 if (field_klass->valuetype) {
3294 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3295 if (mono_error_set_pending_exception (&error))
3298 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3300 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3301 if (mono_error_set_pending_exception (&error))
3303 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3304 mono_array_setref (out_args, 0, result);
3311 g_assert_not_reached ();
3313 } else if (!strcmp (m->name, "FieldSetter")) {
3314 MonoClass *k = this_arg->vtable->klass;
3320 /* If this is a proxy, then it must be a CBO */
3321 if (k == mono_defaults.transparent_proxy_class) {
3322 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3323 this_arg = tp->rp->unwrapped_server;
3324 g_assert (this_arg);
3325 k = this_arg->vtable->klass;
3328 name = mono_array_get (params, MonoString *, 1);
3329 str = mono_string_to_utf8_checked (name, &error);
3330 if (mono_error_set_pending_exception (&error))
3334 MonoClassField* field = mono_class_get_field_from_name (k, str);
3337 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3338 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3340 if (field_klass->valuetype) {
3341 size = mono_type_size (field->type, &align);
3342 g_assert (size == mono_class_value_size (field_klass, NULL));
3343 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3345 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3348 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3349 if (mono_error_set_pending_exception (&error))
3351 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3360 g_assert_not_reached ();
3365 for (i = 0; i < mono_array_length (params); i++) {
3366 if (sig->params [i]->byref)
3370 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3371 if (mono_error_set_pending_exception (&error))
3374 /* handle constructors only for objects already allocated */
3375 if (!strcmp (method->method->name, ".ctor"))
3376 g_assert (this_arg);
3378 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3379 g_assert (!method->method->klass->valuetype);
3380 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3381 if (mono_error_set_pending_exception (&error))
3384 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3385 if (sig->params [i]->byref) {
3387 arg = mono_array_get (params, gpointer, i);
3388 mono_array_setref (out_args, j, arg);
3393 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3400 read_enum_value (const char *mem, int type)
3403 case MONO_TYPE_BOOLEAN:
3405 return *(guint8*)mem;
3407 return *(gint8*)mem;
3408 case MONO_TYPE_CHAR:
3410 return read16 (mem);
3412 return (gint16) read16 (mem);
3414 return read32 (mem);
3416 return (gint32) read32 (mem);
3419 return read64 (mem);
3421 g_assert_not_reached ();
3427 write_enum_value (char *mem, int type, guint64 value)
3431 case MONO_TYPE_I1: {
3432 guint8 *p = (guint8*)mem;
3438 case MONO_TYPE_CHAR: {
3439 guint16 *p = (guint16 *)mem;
3444 case MONO_TYPE_I4: {
3445 guint32 *p = (guint32 *)mem;
3450 case MONO_TYPE_I8: {
3451 guint64 *p = (guint64 *)mem;
3456 g_assert_not_reached ();
3461 ICALL_EXPORT MonoObject *
3462 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3470 domain = mono_object_domain (enumType);
3471 enumc = mono_class_from_mono_type (enumType->type);
3473 mono_class_init_checked (enumc, &error);
3474 if (mono_error_set_pending_exception (&error))
3477 etype = mono_class_enum_basetype (enumc);
3479 res = mono_object_new_checked (domain, enumc, &error);
3480 if (mono_error_set_pending_exception (&error))
3482 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3487 ICALL_EXPORT MonoBoolean
3488 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3490 int size = mono_class_value_size (a->vtable->klass, NULL);
3491 guint64 a_val = 0, b_val = 0;
3493 memcpy (&a_val, mono_object_unbox (a), size);
3494 memcpy (&b_val, mono_object_unbox (b), size);
3496 return (a_val & b_val) == b_val;
3499 ICALL_EXPORT MonoObject *
3500 ves_icall_System_Enum_get_value (MonoObject *eobj)
3512 g_assert (eobj->vtable->klass->enumtype);
3514 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3515 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3516 if (mono_error_set_pending_exception (&error))
3518 dst = (char *)res + sizeof (MonoObject);
3519 src = (char *)eobj + sizeof (MonoObject);
3520 size = mono_class_value_size (enumc, NULL);
3522 memcpy (dst, src, size);
3527 ICALL_EXPORT MonoReflectionType *
3528 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3531 MonoReflectionType *ret;
3535 klass = mono_class_from_mono_type (type->type);
3536 mono_class_init_checked (klass, &error);
3537 if (mono_error_set_pending_exception (&error))
3540 etype = mono_class_enum_basetype (klass);
3542 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3546 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3547 mono_error_set_pending_exception (&error);
3553 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3555 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3556 gpointer odata = (char *)other + sizeof (MonoObject);
3557 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3558 g_assert (basetype);
3563 if (eobj->vtable->klass != other->vtable->klass)
3566 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3567 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3568 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3571 return me > other ? 1 : -1; \
3574 switch (basetype->type) {
3576 COMPARE_ENUM_VALUES (guint8);
3578 COMPARE_ENUM_VALUES (gint8);
3579 case MONO_TYPE_CHAR:
3581 COMPARE_ENUM_VALUES (guint16);
3583 COMPARE_ENUM_VALUES (gint16);
3585 COMPARE_ENUM_VALUES (guint32);
3587 COMPARE_ENUM_VALUES (gint32);
3589 COMPARE_ENUM_VALUES (guint64);
3591 COMPARE_ENUM_VALUES (gint64);
3595 #undef COMPARE_ENUM_VALUES
3596 /* indicates that the enum was of an unsupported unerlying type */
3601 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3603 gpointer data = (char *)eobj + sizeof (MonoObject);
3604 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3605 g_assert (basetype);
3607 switch (basetype->type) {
3608 case MONO_TYPE_I1: {
3609 gint8 value = *((gint8*)data);
3610 return ((int)value ^ (int)value << 8);
3613 return *((guint8*)data);
3614 case MONO_TYPE_CHAR:
3616 return *((guint16*)data);
3618 case MONO_TYPE_I2: {
3619 gint16 value = *((gint16*)data);
3620 return ((int)(guint16)value | (((int)value) << 16));
3623 return *((guint32*)data);
3625 return *((gint32*)data);
3627 case MONO_TYPE_I8: {
3628 gint64 value = *((gint64*)data);
3629 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3632 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3637 ICALL_EXPORT MonoBoolean
3638 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3641 MonoDomain *domain = mono_object_domain (type);
3642 MonoClass *enumc = mono_class_from_mono_type (type->type);
3643 guint j = 0, nvalues;
3645 MonoClassField *field;
3647 guint64 field_value, previous_value = 0;
3648 gboolean sorted = TRUE;
3650 mono_class_init_checked (enumc, &error);
3651 if (mono_error_set_pending_exception (&error))
3655 if (!enumc->enumtype) {
3656 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3660 base_type = mono_class_enum_basetype (enumc)->type;
3662 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3663 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3664 if (mono_error_set_pending_exception (&error))
3666 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3667 if (mono_error_set_pending_exception (&error))
3671 while ((field = mono_class_get_fields (enumc, &iter))) {
3673 MonoTypeEnum def_type;
3675 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3677 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3679 if (mono_field_is_deleted (field))
3681 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3683 p = mono_class_get_field_default_value (field, &def_type);
3684 /* len = */ mono_metadata_decode_blob_size (p, &p);
3686 field_value = read_enum_value (p, base_type);
3687 mono_array_set (*values, guint64, j, field_value);
3689 if (previous_value > field_value)
3692 previous_value = field_value;
3700 BFLAGS_IgnoreCase = 1,
3701 BFLAGS_DeclaredOnly = 2,
3702 BFLAGS_Instance = 4,
3704 BFLAGS_Public = 0x10,
3705 BFLAGS_NonPublic = 0x20,
3706 BFLAGS_FlattenHierarchy = 0x40,
3707 BFLAGS_InvokeMethod = 0x100,
3708 BFLAGS_CreateInstance = 0x200,
3709 BFLAGS_GetField = 0x400,
3710 BFLAGS_SetField = 0x800,
3711 BFLAGS_GetProperty = 0x1000,
3712 BFLAGS_SetProperty = 0x2000,
3713 BFLAGS_ExactBinding = 0x10000,
3714 BFLAGS_SuppressChangeType = 0x20000,
3715 BFLAGS_OptionalParamBinding = 0x40000
3718 ICALL_EXPORT GPtrArray*
3719 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3722 MonoClass *startklass, *klass;
3725 int (*compare_func) (const char *s1, const char *s2) = NULL;
3726 MonoClassField *field;
3728 if (type->type->byref) {
3729 return g_ptr_array_new ();
3732 mono_error_init (&error);
3734 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3736 klass = startklass = mono_class_from_mono_type (type->type);
3738 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3741 if (mono_class_has_failure (klass)) {
3742 mono_error_set_for_class_failure (&error, klass);
3747 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3748 guint32 flags = mono_field_get_flags (field);
3750 if (mono_field_is_deleted_with_flags (field, flags))
3752 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3753 if (bflags & BFLAGS_Public)
3755 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3756 if (bflags & BFLAGS_NonPublic) {
3763 if (flags & FIELD_ATTRIBUTE_STATIC) {
3764 if (bflags & BFLAGS_Static)
3765 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3768 if (bflags & BFLAGS_Instance)
3775 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3778 g_ptr_array_add (ptr_array, field);
3780 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3786 g_ptr_array_free (ptr_array, TRUE);
3787 mono_error_set_pending_exception (&error);
3792 method_nonpublic (MonoMethod* method, gboolean start_klass)
3794 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3795 case METHOD_ATTRIBUTE_ASSEM:
3796 return (start_klass || mono_defaults.generic_ilist_class);
3797 case METHOD_ATTRIBUTE_PRIVATE:
3799 case METHOD_ATTRIBUTE_PUBLIC:
3807 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3810 MonoClass *startklass;
3814 /*FIXME, use MonoBitSet*/
3815 guint32 method_slots_default [8];
3816 guint32 *method_slots = NULL;
3817 int (*compare_func) (const char *s1, const char *s2) = NULL;
3819 array = g_ptr_array_new ();
3821 mono_error_init (error);
3824 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3826 /* An optimization for calls made from Delegate:CreateDelegate () */
3827 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3828 method = mono_get_delegate_invoke (klass);
3831 g_ptr_array_add (array, method);
3835 mono_class_setup_methods (klass);
3836 mono_class_setup_vtable (klass);
3837 if (mono_class_has_failure (klass))
3840 if (is_generic_parameter (&klass->byval_arg))
3841 nslots = mono_class_get_vtable_size (klass->parent);
3843 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3844 if (nslots >= sizeof (method_slots_default) * 8) {
3845 method_slots = g_new0 (guint32, nslots / 32 + 1);
3847 method_slots = method_slots_default;
3848 memset (method_slots, 0, sizeof (method_slots_default));
3851 mono_class_setup_methods (klass);
3852 mono_class_setup_vtable (klass);
3853 if (mono_class_has_failure (klass))
3857 while ((method = mono_class_get_methods (klass, &iter))) {
3859 if (method->slot != -1) {
3860 g_assert (method->slot < nslots);
3861 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3863 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3864 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3867 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3869 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3870 if (bflags & BFLAGS_Public)
3872 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3878 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3879 if (bflags & BFLAGS_Static)
3880 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3883 if (bflags & BFLAGS_Instance)
3891 if (compare_func (name, method->name))
3896 g_ptr_array_add (array, method);
3898 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3900 if (method_slots != method_slots_default)
3901 g_free (method_slots);
3906 if (method_slots != method_slots_default)
3907 g_free (method_slots);
3908 g_ptr_array_free (array, TRUE);
3910 g_assert (mono_class_has_failure (klass));
3911 mono_error_set_for_class_failure (error, klass);
3915 ICALL_EXPORT GPtrArray*
3916 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3919 GPtrArray *method_array;
3922 klass = mono_class_from_mono_type (type->type);
3923 if (type->type->byref) {
3924 return g_ptr_array_new ();
3927 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3928 mono_error_set_pending_exception (&error);
3929 return method_array;
3932 ICALL_EXPORT GPtrArray*
3933 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3935 MonoClass *startklass, *klass;
3938 gpointer iter = NULL;
3939 GPtrArray *res_array;
3942 if (type->type->byref) {
3943 return g_ptr_array_new ();
3946 klass = startklass = mono_class_from_mono_type (type->type);
3948 mono_class_setup_methods (klass);
3949 if (mono_class_has_failure (klass)) {
3950 mono_error_init (&error);
3951 mono_error_set_for_class_failure (&error, klass);
3952 mono_error_set_pending_exception (&error);
3956 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3959 while ((method = mono_class_get_methods (klass, &iter))) {
3961 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3963 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3964 if (bflags & BFLAGS_Public)
3967 if (bflags & BFLAGS_NonPublic)
3973 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3974 if (bflags & BFLAGS_Static)
3975 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3978 if (bflags & BFLAGS_Instance)
3984 g_ptr_array_add (res_array, method);
3991 property_hash (gconstpointer data)
3993 MonoProperty *prop = (MonoProperty*)data;
3995 return g_str_hash (prop->name);
3999 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4001 if (method1->slot != -1 && method1->slot == method2->slot)
4004 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4005 if (method1->is_inflated)
4006 method1 = ((MonoMethodInflated*) method1)->declaring;
4007 if (method2->is_inflated)
4008 method2 = ((MonoMethodInflated*) method2)->declaring;
4011 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4015 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4017 // Properties are hide-by-name-and-signature
4018 if (!g_str_equal (prop1->name, prop2->name))
4021 /* If we see a property in a generic method, we want to
4022 compare the generic signatures, not the inflated signatures
4023 because we might conflate two properties that were
4027 public T this[T t] { getter { return t; } } // method 1
4028 public U this[U u] { getter { return u; } } // method 2
4031 If we see int Foo<int,int>::Item[int] we need to know if
4032 the indexer came from method 1 or from method 2, and we
4033 shouldn't conflate them. (Bugzilla 36283)
4035 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4038 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4045 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4050 return method_nonpublic (accessor, start_klass);
4053 ICALL_EXPORT GPtrArray*
4054 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4057 MonoClass *startklass, *klass;
4062 int (*compare_func) (const char *s1, const char *s2) = NULL;
4064 GHashTable *properties = NULL;
4065 GPtrArray *res_array;
4067 if (type->type->byref) {
4068 return g_ptr_array_new ();
4071 mono_error_init (&error);
4073 klass = startklass = mono_class_from_mono_type (type->type);
4075 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4077 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4079 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4081 mono_class_setup_methods (klass);
4082 mono_class_setup_vtable (klass);
4083 if (mono_class_has_failure (klass)) {
4084 mono_error_set_for_class_failure (&error, klass);
4089 while ((prop = mono_class_get_properties (klass, &iter))) {
4095 flags = method->flags;
4098 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4099 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4100 if (bflags & BFLAGS_Public)
4102 } else if (bflags & BFLAGS_NonPublic) {
4103 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4104 property_accessor_nonpublic(prop->set, startklass == klass)) {
4111 if (flags & METHOD_ATTRIBUTE_STATIC) {
4112 if (bflags & BFLAGS_Static)
4113 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4116 if (bflags & BFLAGS_Instance)
4124 if (propname != NULL && compare_func (propname, prop->name))
4127 if (g_hash_table_lookup (properties, prop))
4130 g_ptr_array_add (res_array, prop);
4132 g_hash_table_insert (properties, prop, prop);
4134 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4137 g_hash_table_destroy (properties);
4144 g_hash_table_destroy (properties);
4145 g_ptr_array_free (res_array, TRUE);
4147 mono_error_set_pending_exception (&error);
4153 event_hash (gconstpointer data)
4155 MonoEvent *event = (MonoEvent*)data;
4157 return g_str_hash (event->name);
4161 event_equal (MonoEvent *event1, MonoEvent *event2)
4163 // Events are hide-by-name
4164 return g_str_equal (event1->name, event2->name);
4167 ICALL_EXPORT GPtrArray*
4168 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4171 MonoClass *startklass, *klass;
4176 int (*compare_func) (const char *s1, const char *s2) = NULL;
4177 GHashTable *events = NULL;
4178 GPtrArray *res_array;
4180 if (type->type->byref) {
4181 return g_ptr_array_new ();
4184 mono_error_init (&error);
4186 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4188 res_array = g_ptr_array_sized_new (4);
4190 klass = startklass = mono_class_from_mono_type (type->type);
4192 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4194 mono_class_setup_methods (klass);
4195 mono_class_setup_vtable (klass);
4196 if (mono_class_has_failure (klass)) {
4197 mono_error_set_for_class_failure (&error, klass);
4202 while ((event = mono_class_get_events (klass, &iter))) {
4204 method = event->add;
4206 method = event->remove;
4208 method = event->raise;
4210 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4211 if (bflags & BFLAGS_Public)
4213 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4214 if (bflags & BFLAGS_NonPublic)
4219 if (bflags & BFLAGS_NonPublic)
4225 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4226 if (bflags & BFLAGS_Static)
4227 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4230 if (bflags & BFLAGS_Instance)
4235 if (bflags & BFLAGS_Instance)
4240 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4243 if (g_hash_table_lookup (events, event))
4246 g_ptr_array_add (res_array, event);
4248 g_hash_table_insert (events, event, event);
4250 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4253 g_hash_table_destroy (events);
4259 g_hash_table_destroy (events);
4261 g_ptr_array_free (res_array, TRUE);
4263 mono_error_set_pending_exception (&error);
4267 ICALL_EXPORT GPtrArray *
4268 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4274 GPtrArray *res_array;
4276 if (type->type->byref) {
4277 return g_ptr_array_new ();
4280 klass = mono_class_from_mono_type (type->type);
4283 * If a nested type is generic, return its generic type definition.
4284 * Note that this means that the return value is essentially the set
4285 * of nested types of the generic type definition of @klass.
4287 * A note in MSDN claims that a generic type definition can have
4288 * nested types that aren't generic. In any case, the container of that
4289 * nested type would be the generic type definition.
4291 if (klass->generic_class)
4292 klass = klass->generic_class->container_class;
4294 res_array = g_ptr_array_new ();
4297 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4299 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4300 if (bflags & BFLAGS_Public)
4303 if (bflags & BFLAGS_NonPublic)
4309 if (str != NULL && strcmp (nested->name, str))
4312 g_ptr_array_add (res_array, &nested->byval_arg);
4318 ICALL_EXPORT MonoReflectionType*
4319 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4322 MonoReflectionType *ret;
4324 MonoType *type = NULL;
4325 MonoTypeNameParse info;
4326 gboolean type_resolve;
4328 /* On MS.NET, this does not fire a TypeResolve event */
4329 type_resolve = TRUE;
4330 str = mono_string_to_utf8_checked (name, &error);
4331 if (mono_error_set_pending_exception (&error))
4333 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4334 if (!mono_reflection_parse_type (str, &info)) {
4336 mono_reflection_free_type_info (&info);
4338 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4341 /*g_print ("failed parse\n");*/
4345 if (info.assembly.name) {
4347 mono_reflection_free_type_info (&info);
4349 /* 1.0 and 2.0 throw different exceptions */
4350 if (mono_defaults.generic_ilist_class)
4351 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4353 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4359 if (module != NULL) {
4360 if (module->image) {
4361 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4362 if (!is_ok (&error)) {
4364 mono_reflection_free_type_info (&info);
4365 mono_error_set_pending_exception (&error);
4372 if (assembly_is_dynamic (assembly->assembly)) {
4373 /* Enumerate all modules */
4374 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4378 if (abuilder->modules) {
4379 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4380 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4381 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4382 if (!is_ok (&error)) {
4384 mono_reflection_free_type_info (&info);
4385 mono_error_set_pending_exception (&error);
4393 if (!type && abuilder->loaded_modules) {
4394 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4395 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4396 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4397 if (!is_ok (&error)) {
4399 mono_reflection_free_type_info (&info);
4400 mono_error_set_pending_exception (&error);
4409 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4410 if (!is_ok (&error)) {
4412 mono_reflection_free_type_info (&info);
4413 mono_error_set_pending_exception (&error);
4418 mono_reflection_free_type_info (&info);
4420 MonoException *e = NULL;
4423 e = mono_get_exception_type_load (name, NULL);
4426 mono_set_pending_exception (e);
4430 if (type->type == MONO_TYPE_CLASS) {
4431 MonoClass *klass = mono_type_get_class (type);
4433 /* need to report exceptions ? */
4434 if (throwOnError && mono_class_has_failure (klass)) {
4435 /* report SecurityException (or others) that occured when loading the assembly */
4436 mono_error_set_for_class_failure (&error, klass);
4437 mono_error_set_pending_exception (&error);
4442 /* g_print ("got it\n"); */
4443 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4444 mono_error_set_pending_exception (&error);
4450 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4453 gchar *shadow_ini_file;
4456 /* Check for shadow-copied assembly */
4457 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4458 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4460 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4461 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4467 g_free (shadow_ini_file);
4468 if (content != NULL) {
4471 *filename = content;
4478 ICALL_EXPORT MonoString *
4479 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4481 MonoDomain *domain = mono_object_domain (assembly);
4482 MonoAssembly *mass = assembly->assembly;
4483 MonoString *res = NULL;
4488 if (g_path_is_absolute (mass->image->name)) {
4489 absolute = g_strdup (mass->image->name);
4490 dirname = g_path_get_dirname (absolute);
4492 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4493 dirname = g_strdup (mass->basedir);
4496 replace_shadow_path (domain, dirname, &absolute);
4501 for (i = strlen (absolute) - 1; i >= 0; i--)
4502 if (absolute [i] == '\\')
4507 uri = g_filename_to_uri (absolute, NULL, NULL);
4509 const char *prepend = "file://";
4511 if (*absolute == '/' && *(absolute + 1) == '/') {
4514 prepend = "file:///";
4517 uri = g_strconcat (prepend, absolute, NULL);
4521 res = mono_string_new (domain, uri);
4528 ICALL_EXPORT MonoBoolean
4529 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4531 MonoAssembly *mass = assembly->assembly;
4533 return mass->in_gac;
4536 ICALL_EXPORT MonoReflectionAssembly*
4537 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4542 MonoImageOpenStatus status;
4543 MonoReflectionAssembly* result = NULL;
4545 name = mono_string_to_utf8_checked (mname, &error);
4546 if (mono_error_set_pending_exception (&error))
4548 res = mono_assembly_load_with_partial_name (name, &status);
4554 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4556 mono_error_set_pending_exception (&error);
4560 ICALL_EXPORT MonoStringHandle
4561 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4563 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4564 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4565 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4568 ICALL_EXPORT MonoBoolean
4569 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4571 return assembly->assembly->ref_only;
4574 ICALL_EXPORT MonoStringHandle
4575 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4577 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4578 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4580 return mono_string_new_handle (domain, assembly->image->version, error);
4583 ICALL_EXPORT MonoReflectionMethod*
4584 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4587 MonoReflectionMethod *res = NULL;
4590 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4594 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4595 if (!mono_error_ok (&error))
4598 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4601 if (!mono_error_ok (&error))
4602 mono_error_set_pending_exception (&error);
4606 ICALL_EXPORT MonoReflectionModule*
4607 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4610 MonoReflectionModule *result = NULL;
4611 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4612 if (!mono_error_ok (&error))
4613 mono_error_set_pending_exception (&error);
4617 ICALL_EXPORT MonoArray*
4618 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4621 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4622 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4623 if (mono_error_set_pending_exception (&error))
4628 for (i = 0; i < table->rows; ++i) {
4629 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4630 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4635 ICALL_EXPORT MonoStringHandle
4636 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4639 guint8 aotid_sum = 0;
4640 MonoDomain* domain = mono_domain_get ();
4642 if (!domain->entry_assembly || !domain->entry_assembly->image)
4645 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4647 for (i = 0; i < 16; ++i)
4648 aotid_sum |= (*aotid)[i];
4653 gchar *guid = mono_guid_to_string((guint8*) aotid);
4654 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4660 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4662 static MonoMethod *create_version = NULL;
4666 mono_error_init (error);
4669 if (!create_version) {
4670 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4671 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4672 g_assert (create_version);
4673 mono_method_desc_free (desc);
4679 args [3] = &revision;
4680 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4681 return_val_if_nok (error, NULL);
4683 mono_runtime_invoke_checked (create_version, result, args, error);
4684 return_val_if_nok (error, NULL);
4689 ICALL_EXPORT MonoArray*
4690 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4694 MonoDomain *domain = mono_object_domain (assembly);
4696 static MonoMethod *create_culture = NULL;
4697 MonoImage *image = assembly->assembly->image;
4701 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4704 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4705 if (mono_error_set_pending_exception (&error))
4709 if (count > 0 && !create_culture) {
4710 MonoMethodDesc *desc = mono_method_desc_new (
4711 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4712 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4713 g_assert (create_culture);
4714 mono_method_desc_free (desc);
4717 for (i = 0; i < count; i++) {
4718 MonoObject *version;
4719 MonoReflectionAssemblyName *aname;
4720 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4722 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4724 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4725 domain, mono_class_get_assembly_name_class (), &error);
4726 if (mono_error_set_pending_exception (&error))
4729 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4731 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4732 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4733 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4734 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4735 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4736 aname->versioncompat = 1; /* SameMachine (default) */
4737 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4739 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4740 if (mono_error_set_pending_exception (&error))
4743 MONO_OBJECT_SETREF (aname, version, version);
4745 if (create_culture) {
4747 MonoBoolean assembly_ref = 1;
4748 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4749 args [1] = &assembly_ref;
4751 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4752 if (mono_error_set_pending_exception (&error))
4755 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4758 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4759 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4760 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4762 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4763 /* public key token isn't copied - the class library will
4764 automatically generate it from the public key if required */
4765 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4766 if (mono_error_set_pending_exception (&error))
4769 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4770 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4772 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4773 if (mono_error_set_pending_exception (&error))
4776 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4777 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4780 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4781 if (mono_error_set_pending_exception (&error))
4784 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4787 /* note: this function doesn't return the codebase on purpose (i.e. it can
4788 be used under partial trust as path information isn't present). */
4790 mono_array_setref (result, i, aname);
4795 /* move this in some file in mono/util/ */
4797 g_concat_dir_and_file (const char *dir, const char *file)
4799 g_return_val_if_fail (dir != NULL, NULL);
4800 g_return_val_if_fail (file != NULL, NULL);
4803 * If the directory name doesn't have a / on the end, we need
4804 * to add one so we get a proper path to the file
4806 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4807 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4809 return g_strconcat (dir, file, NULL);
4813 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4816 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4818 guint32 cols [MONO_MANIFEST_SIZE];
4819 guint32 impl, file_idx;
4823 char *n = mono_string_to_utf8_checked (name, &error);
4824 if (mono_error_set_pending_exception (&error))
4827 for (i = 0; i < table->rows; ++i) {
4828 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4829 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4830 if (strcmp (val, n) == 0)
4834 if (i == table->rows)
4837 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4840 * this code should only be called after obtaining the
4841 * ResourceInfo and handling the other cases.
4843 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4844 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4846 module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
4847 if (mono_error_set_pending_exception (&error) || !module)
4851 module = assembly->assembly->image;
4854 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4855 if (mono_error_set_pending_exception (&error))
4857 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4859 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4862 ICALL_EXPORT gboolean
4863 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4866 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4868 guint32 cols [MONO_MANIFEST_SIZE];
4869 guint32 file_cols [MONO_FILE_SIZE];
4873 n = mono_string_to_utf8_checked (name, &error);
4874 if (mono_error_set_pending_exception (&error))
4876 for (i = 0; i < table->rows; ++i) {
4877 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4878 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4879 if (strcmp (val, n) == 0)
4883 if (i == table->rows)
4886 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4887 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4890 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4891 case MONO_IMPLEMENTATION_FILE:
4892 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4893 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4894 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4895 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4896 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4897 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4900 info->location = RESOURCE_LOCATION_EMBEDDED;
4903 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4904 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4905 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4906 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4907 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4908 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4910 mono_set_pending_exception (ex);
4913 MonoReflectionAssembly *assm_obj;
4914 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4916 mono_error_set_pending_exception (&error);
4919 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4921 /* Obtain info recursively */
4922 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4923 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4926 case MONO_IMPLEMENTATION_EXP_TYPE:
4927 g_assert_not_reached ();
4935 ICALL_EXPORT MonoObject*
4936 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4939 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4940 MonoArray *result = NULL;
4945 /* check hash if needed */
4947 n = mono_string_to_utf8_checked (name, &error);
4948 if (mono_error_set_pending_exception (&error))
4951 for (i = 0; i < table->rows; ++i) {
4952 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4953 if (strcmp (val, n) == 0) {
4956 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4957 fn = mono_string_new (mono_object_domain (assembly), n);
4959 return (MonoObject*)fn;
4967 for (i = 0; i < table->rows; ++i) {
4968 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4972 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4973 if (mono_error_set_pending_exception (&error))
4978 for (i = 0; i < table->rows; ++i) {
4979 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4980 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4981 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4982 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4987 return (MonoObject*)result;
4990 ICALL_EXPORT MonoArray*
4991 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4994 MonoDomain *domain = mono_domain_get();
4997 int i, j, file_count = 0;
4998 MonoImage **modules;
4999 guint32 module_count, real_module_count;
5000 MonoTableInfo *table;
5001 guint32 cols [MONO_FILE_SIZE];
5002 MonoImage *image = assembly->assembly->image;
5004 g_assert (image != NULL);
5005 g_assert (!assembly_is_dynamic (assembly->assembly));
5007 table = &image->tables [MONO_TABLE_FILE];
5008 file_count = table->rows;
5010 modules = image->modules;
5011 module_count = image->module_count;
5013 real_module_count = 0;
5014 for (i = 0; i < module_count; ++i)
5016 real_module_count ++;
5018 klass = mono_class_get_module_class ();
5019 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5020 if (mono_error_set_pending_exception (&error))
5023 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5024 if (mono_error_set_pending_exception (&error))
5027 mono_array_setref (res, 0, image_obj);
5029 for (i = 0; i < module_count; ++i)
5031 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5032 if (mono_error_set_pending_exception (&error))
5034 mono_array_setref (res, j, rm);
5038 for (i = 0; i < file_count; ++i, ++j) {
5039 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5040 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5041 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5042 if (mono_error_set_pending_exception (&error))
5044 mono_array_setref (res, j, rm);
5047 MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
5048 if (mono_error_set_pending_exception (&error))
5051 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5052 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5055 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5056 if (mono_error_set_pending_exception (&error))
5058 mono_array_setref (res, j, rm);
5065 ICALL_EXPORT MonoReflectionMethod*
5066 ves_icall_GetCurrentMethod (void)
5068 MonoReflectionMethod *res = NULL;
5071 MonoMethod *m = mono_method_get_last_managed ();
5074 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5078 while (m->is_inflated)
5079 m = ((MonoMethodInflated*)m)->declaring;
5081 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5082 mono_error_set_pending_exception (&error);
5088 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5091 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5094 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5095 //method is inflated, we should inflate it on the other class
5096 MonoGenericContext ctx;
5097 ctx.method_inst = inflated->context.method_inst;
5098 ctx.class_inst = inflated->context.class_inst;
5099 if (klass->generic_class)
5100 ctx.class_inst = klass->generic_class->context.class_inst;
5101 else if (klass->generic_container)
5102 ctx.class_inst = klass->generic_container->context.class_inst;
5103 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5104 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5108 mono_class_setup_methods (method->klass);
5109 if (mono_class_has_failure (method->klass))
5111 for (i = 0; i < method->klass->method.count; ++i) {
5112 if (method->klass->methods [i] == method) {
5117 mono_class_setup_methods (klass);
5118 if (mono_class_has_failure (klass))
5120 g_assert (offset >= 0 && offset < klass->method.count);
5121 return klass->methods [offset];
5124 ICALL_EXPORT MonoReflectionMethod*
5125 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5127 MonoReflectionMethod *res = NULL;
5130 if (type && generic_check) {
5131 klass = mono_class_from_mono_type (type);
5132 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5135 if (method->klass != klass) {
5136 method = mono_method_get_equivalent_method (method, klass);
5141 klass = mono_class_from_mono_type (type);
5143 klass = method->klass;
5144 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5145 mono_error_set_pending_exception (&error);
5149 ICALL_EXPORT MonoReflectionMethodBody*
5150 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5153 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5154 mono_error_set_pending_exception (&error);
5158 ICALL_EXPORT MonoReflectionAssembly*
5159 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5162 MonoReflectionAssembly *result;
5163 MonoMethod *dest = NULL;
5165 mono_stack_walk_no_il (get_executing, &dest);
5167 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5169 mono_error_set_pending_exception (&error);
5174 ICALL_EXPORT MonoReflectionAssembly*
5175 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5178 MonoReflectionAssembly *result;
5179 MonoDomain* domain = mono_domain_get ();
5181 if (!domain->entry_assembly)
5184 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5186 mono_error_set_pending_exception (&error);
5190 ICALL_EXPORT MonoReflectionAssembly*
5191 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5196 MonoReflectionAssembly *result;
5199 mono_stack_walk_no_il (get_executing, &dest);
5201 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5205 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5208 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5210 mono_error_set_pending_exception (&error);
5214 ICALL_EXPORT MonoStringHandle
5215 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5216 gboolean assembly_qualified, MonoError *error)
5218 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5219 MonoType *type = MONO_HANDLE_RAW (object)->type;
5220 MonoTypeNameFormat format;
5221 MonoStringHandle res;
5225 format = assembly_qualified ?
5226 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5227 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5229 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5231 name = mono_type_get_name_full (type, format);
5233 return NULL_HANDLE_STRING;
5235 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5237 return NULL_HANDLE_STRING;
5240 res = mono_string_new_handle (domain, name, error);
5247 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5250 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5252 mono_class_init_checked (klass, &error);
5253 mono_error_set_pending_exception (&error);
5254 return mono_security_core_clr_class_level (klass);
5258 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5260 MonoClassField *field = rfield->field;
5261 return mono_security_core_clr_field_level (field, TRUE);
5265 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5267 MonoMethod *method = rfield->method;
5268 return mono_security_core_clr_method_level (method, TRUE);
5272 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token, MonoError *error)
5274 static MonoMethod *create_culture = NULL;
5278 const char *pkey_ptr;
5280 MonoBoolean assembly_ref = 0;
5282 mono_error_init (error);
5284 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5285 aname->major = name->major;
5286 aname->minor = name->minor;
5287 aname->build = name->build;
5288 aname->flags = name->flags;
5289 aname->revision = name->revision;
5290 aname->hashalg = name->hash_alg;
5291 aname->versioncompat = 1; /* SameMachine (default) */
5292 aname->processor_architecture = name->arch;
5294 if (by_default_version) {
5295 MonoObject *version;
5297 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5298 return_if_nok (error);
5300 MONO_OBJECT_SETREF (aname, version, version);
5304 if (absolute != NULL && *absolute != '\0') {
5305 const gchar *prepend = "file://";
5308 codebase = g_strdup (absolute);
5313 for (i = strlen (codebase) - 1; i >= 0; i--)
5314 if (codebase [i] == '\\')
5317 if (*codebase == '/' && *(codebase + 1) == '/') {
5320 prepend = "file:///";
5324 result = g_strconcat (prepend, codebase, NULL);
5330 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5334 if (!create_culture) {
5335 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5336 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5337 g_assert (create_culture);
5338 mono_method_desc_free (desc);
5341 if (name->culture) {
5342 args [0] = mono_string_new (domain, name->culture);
5343 args [1] = &assembly_ref;
5345 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5346 return_if_nok (error);
5348 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5351 if (name->public_key) {
5352 pkey_ptr = (char*)name->public_key;
5353 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5355 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5356 return_if_nok (error);
5357 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5358 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5359 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5360 } else if (default_publickey) {
5361 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5362 return_if_nok (error);
5363 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5364 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5367 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5368 if (name->public_key_token [0]) {
5372 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5373 return_if_nok (error);
5375 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5376 p = mono_array_addr (keyToken, char, 0);
5378 for (i = 0, j = 0; i < 8; i++) {
5379 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5380 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5383 } else if (default_token) {
5384 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5385 return_if_nok (error);
5386 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5390 ICALL_EXPORT MonoString *
5391 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5393 MonoDomain *domain = mono_object_domain (assembly);
5394 MonoAssembly *mass = assembly->assembly;
5398 name = mono_stringify_assembly_name (&mass->aname);
5399 res = mono_string_new (domain, name);
5405 ICALL_EXPORT MonoAssemblyName *
5406 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5408 return &mass->aname;
5412 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5416 MonoImageOpenStatus status = MONO_IMAGE_OK;
5419 MonoAssemblyName name;
5422 filename = mono_string_to_utf8_checked (fname, &error);
5423 if (mono_error_set_pending_exception (&error))
5426 dirname = g_path_get_dirname (filename);
5427 replace_shadow_path (mono_domain_get (), dirname, &filename);
5430 image = mono_image_open (filename, &status);
5436 if (status == MONO_IMAGE_IMAGE_INVALID)
5437 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5439 exc = mono_get_exception_file_not_found2 (NULL, fname);
5440 mono_set_pending_exception (exc);
5444 res = mono_assembly_fill_assembly_name (image, &name);
5446 mono_image_close (image);
5448 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5452 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5453 mono_error_set_pending_exception (&error);
5455 mono_image_close (image);
5459 ICALL_EXPORT MonoBoolean
5460 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5461 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5463 MonoBoolean result = FALSE;
5464 MonoDeclSecurityEntry entry;
5466 /* SecurityAction.RequestMinimum */
5467 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5468 *minimum = entry.blob;
5469 *minLength = entry.size;
5472 /* SecurityAction.RequestOptional */
5473 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5474 *optional = entry.blob;
5475 *optLength = entry.size;
5478 /* SecurityAction.RequestRefuse */
5479 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5480 *refused = entry.blob;
5481 *refLength = entry.size;
5489 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5491 guint32 attrs, visibility;
5493 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5494 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5495 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5498 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5504 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5506 MonoReflectionType *rt;
5509 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5512 mono_error_init (error);
5514 /* we start the count from 1 because we skip the special type <Module> */
5517 for (i = 1; i < tdef->rows; ++i) {
5518 if (mono_module_type_is_visible (tdef, image, i + 1))
5522 count = tdef->rows - 1;
5524 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5525 return_val_if_nok (error, NULL);
5526 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5527 return_val_if_nok (error, NULL);
5529 for (i = 1; i < tdef->rows; ++i) {
5530 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5531 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5534 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5535 return_val_if_nok (error, NULL);
5537 mono_array_setref (res, count, rt);
5539 MonoException *ex = mono_error_convert_to_exception (error);
5540 mono_array_setref (*exceptions, count, ex);
5549 ICALL_EXPORT MonoArray*
5550 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5553 MonoArray *res = NULL;
5554 MonoArray *exceptions = NULL;
5555 MonoImage *image = NULL;
5556 MonoTableInfo *table = NULL;
5559 int i, len, ex_count;
5561 domain = mono_object_domain (assembly);
5563 g_assert (!assembly_is_dynamic (assembly->assembly));
5564 image = assembly->assembly->image;
5565 table = &image->tables [MONO_TABLE_FILE];
5566 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5567 if (mono_error_set_pending_exception (&error))
5570 /* Append data from all modules in the assembly */
5571 for (i = 0; i < table->rows; ++i) {
5572 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5573 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5574 if (mono_error_set_pending_exception (&error))
5580 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5581 if (mono_error_set_pending_exception (&error))
5585 /* Append the new types to the end of the array */
5586 if (mono_array_length (res2) > 0) {
5588 MonoArray *res3, *ex3;
5590 len1 = mono_array_length (res);
5591 len2 = mono_array_length (res2);
5593 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5594 if (mono_error_set_pending_exception (&error))
5596 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5597 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5600 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5601 if (mono_error_set_pending_exception (&error))
5603 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5604 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5611 /* the ReflectionTypeLoadException must have all the types (Types property),
5612 * NULL replacing types which throws an exception. The LoaderException must
5613 * contain all exceptions for NULL items.
5616 len = mono_array_length (res);
5619 for (i = 0; i < len; i++) {
5620 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5624 klass = mono_type_get_class (t->type);
5625 if ((klass != NULL) && mono_class_has_failure (klass)) {
5626 /* keep the class in the list */
5627 list = g_list_append (list, klass);
5628 /* and replace Type with NULL */
5629 mono_array_setref (res, i, NULL);
5636 if (list || ex_count) {
5638 MonoException *exc = NULL;
5639 MonoArray *exl = NULL;
5640 int j, length = g_list_length (list) + ex_count;
5642 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5643 if (mono_error_set_pending_exception (&error)) {
5647 /* Types for which mono_class_get_checked () succeeded */
5648 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5649 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5650 mono_array_setref (exl, i, exc);
5652 /* Types for which it don't */
5653 for (j = 0; j < mono_array_length (exceptions); ++j) {
5654 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5656 g_assert (i < length);
5657 mono_array_setref (exl, i, exc);
5664 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5665 if (!is_ok (&error)) {
5666 mono_error_set_pending_exception (&error);
5669 mono_set_pending_exception (exc);
5677 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5679 mono_assembly_name_free (aname);
5682 ICALL_EXPORT gboolean
5683 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5685 *is_version_definited = *is_token_defined = FALSE;
5687 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5690 ICALL_EXPORT MonoReflectionType*
5691 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5694 MonoReflectionType *ret;
5695 MonoDomain *domain = mono_object_domain (module);
5698 g_assert (module->image);
5700 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5701 /* These images do not have a global type */
5704 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5705 if (!mono_error_ok (&error)) {
5706 mono_error_set_pending_exception (&error);
5710 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5711 if (!mono_error_ok (&error)) {
5712 mono_error_set_pending_exception (&error);
5720 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5722 /*if (module->image)
5723 mono_image_close (module->image);*/
5726 ICALL_EXPORT MonoStringHandle
5727 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5729 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5730 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5733 return mono_string_new_handle (domain, image->guid, error);
5736 ICALL_EXPORT gpointer
5737 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5740 if (module->image && module->image->is_module_handle)
5741 return module->image->raw_data;
5744 return (gpointer) (-1);
5748 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5750 if (image_is_dynamic (image)) {
5751 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5752 *pe_kind = dyn->pe_kind;
5753 *machine = dyn->machine;
5756 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5757 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5762 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5764 return (image->md_version_major << 16) | (image->md_version_minor);
5767 ICALL_EXPORT MonoArray*
5768 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5771 MonoArray *exceptions;
5774 if (!module->image) {
5775 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5776 mono_error_set_pending_exception (&error);
5781 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5782 if (mono_error_set_pending_exception (&error))
5785 for (i = 0; i < mono_array_length (exceptions); ++i) {
5786 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5788 mono_set_pending_exception (ex);
5797 mono_memberref_is_method (MonoImage *image, guint32 token)
5799 if (!image_is_dynamic (image)) {
5800 guint32 cols [MONO_MEMBERREF_SIZE];
5802 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5803 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5804 mono_metadata_decode_blob_size (sig, &sig);
5805 return (*sig != 0x6);
5808 MonoClass *handle_class;
5810 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5811 mono_error_cleanup (&error); /* just probing, ignore error */
5815 return mono_defaults.methodhandle_class == handle_class;
5820 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5823 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5824 mono_array_addr (type_args, MonoType*, 0));
5826 context->class_inst = NULL;
5828 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5829 mono_array_addr (method_args, MonoType*, 0));
5831 context->method_inst = NULL;
5834 ICALL_EXPORT MonoType*
5835 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5838 int table = mono_metadata_token_table (token);
5839 int index = mono_metadata_token_index (token);
5840 MonoGenericContext context;
5843 *resolve_error = ResolveTokenError_Other;
5845 /* Validate token */
5846 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5847 (table != MONO_TABLE_TYPESPEC)) {
5848 *resolve_error = ResolveTokenError_BadTable;
5852 if (image_is_dynamic (image)) {
5853 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5854 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5855 mono_error_cleanup (&error);
5856 return klass ? &klass->byval_arg : NULL;
5859 init_generic_context_from_args (&context, type_args, method_args);
5860 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5861 mono_error_cleanup (&error);
5862 return klass ? &klass->byval_arg : NULL;
5865 if ((index <= 0) || (index > image->tables [table].rows)) {
5866 *resolve_error = ResolveTokenError_OutOfRange;
5870 init_generic_context_from_args (&context, type_args, method_args);
5871 klass = mono_class_get_checked (image, token, &error);
5873 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5874 if (!mono_error_ok (&error)) {
5875 mono_error_set_pending_exception (&error);
5880 return &klass->byval_arg;
5885 ICALL_EXPORT MonoMethod*
5886 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5889 int table = mono_metadata_token_table (token);
5890 int index = mono_metadata_token_index (token);
5891 MonoGenericContext context;
5894 *resolve_error = ResolveTokenError_Other;
5896 /* Validate token */
5897 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5898 (table != MONO_TABLE_MEMBERREF)) {
5899 *resolve_error = ResolveTokenError_BadTable;
5903 if (image_is_dynamic (image)) {
5904 if (table == MONO_TABLE_METHOD) {
5905 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5906 mono_error_cleanup (&error);
5910 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5911 *resolve_error = ResolveTokenError_BadTable;
5915 init_generic_context_from_args (&context, type_args, method_args);
5916 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5917 mono_error_cleanup (&error);
5921 if ((index <= 0) || (index > image->tables [table].rows)) {
5922 *resolve_error = ResolveTokenError_OutOfRange;
5925 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5926 *resolve_error = ResolveTokenError_BadTable;
5930 init_generic_context_from_args (&context, type_args, method_args);
5931 method = mono_get_method_checked (image, token, NULL, &context, &error);
5932 mono_error_set_pending_exception (&error);
5937 ICALL_EXPORT MonoString*
5938 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5941 int index = mono_metadata_token_index (token);
5943 *resolve_error = ResolveTokenError_Other;
5945 /* Validate token */
5946 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5947 *resolve_error = ResolveTokenError_BadTable;
5951 if (image_is_dynamic (image)) {
5952 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5953 mono_error_cleanup (&error);
5957 if ((index <= 0) || (index >= image->heap_us.size)) {
5958 *resolve_error = ResolveTokenError_OutOfRange;
5962 /* FIXME: What to do if the index points into the middle of a string ? */
5964 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5965 mono_error_set_pending_exception (&error);
5969 ICALL_EXPORT MonoClassField*
5970 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5974 int table = mono_metadata_token_table (token);
5975 int index = mono_metadata_token_index (token);
5976 MonoGenericContext context;
5977 MonoClassField *field;
5979 *resolve_error = ResolveTokenError_Other;
5981 /* Validate token */
5982 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5983 *resolve_error = ResolveTokenError_BadTable;
5987 if (image_is_dynamic (image)) {
5988 if (table == MONO_TABLE_FIELD) {
5989 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5990 mono_error_cleanup (&error);
5994 if (mono_memberref_is_method (image, token)) {
5995 *resolve_error = ResolveTokenError_BadTable;
5999 init_generic_context_from_args (&context, type_args, method_args);
6000 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6001 mono_error_cleanup (&error);
6005 if ((index <= 0) || (index > image->tables [table].rows)) {
6006 *resolve_error = ResolveTokenError_OutOfRange;
6009 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6010 *resolve_error = ResolveTokenError_BadTable;
6014 init_generic_context_from_args (&context, type_args, method_args);
6015 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6016 mono_error_set_pending_exception (&error);
6022 ICALL_EXPORT MonoObject*
6023 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6027 int table = mono_metadata_token_table (token);
6029 *error = ResolveTokenError_Other;
6032 case MONO_TABLE_TYPEDEF:
6033 case MONO_TABLE_TYPEREF:
6034 case MONO_TABLE_TYPESPEC: {
6035 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6037 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6038 mono_error_set_pending_exception (&merror);
6045 case MONO_TABLE_METHOD:
6046 case MONO_TABLE_METHODSPEC: {
6047 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6049 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6050 mono_error_set_pending_exception (&merror);
6056 case MONO_TABLE_FIELD: {
6057 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6059 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6060 mono_error_set_pending_exception (&merror);
6066 case MONO_TABLE_MEMBERREF:
6067 if (mono_memberref_is_method (image, token)) {
6068 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6070 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6071 mono_error_set_pending_exception (&merror);
6078 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6080 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6081 mono_error_set_pending_exception (&merror);
6090 *error = ResolveTokenError_BadTable;
6096 ICALL_EXPORT MonoArray*
6097 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6100 int table = mono_metadata_token_table (token);
6101 int idx = mono_metadata_token_index (token);
6102 MonoTableInfo *tables = image->tables;
6107 *resolve_error = ResolveTokenError_OutOfRange;
6109 /* FIXME: Support other tables ? */
6110 if (table != MONO_TABLE_STANDALONESIG)
6113 if (image_is_dynamic (image))
6116 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6119 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6121 ptr = mono_metadata_blob_heap (image, sig);
6122 len = mono_metadata_decode_blob_size (ptr, &ptr);
6124 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6125 if (mono_error_set_pending_exception (&error))
6127 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6131 ICALL_EXPORT MonoBoolean
6132 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6138 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6144 check_for_invalid_type (MonoClass *klass, MonoError *error)
6148 mono_error_init (error);
6150 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6153 name = mono_type_get_full_name (klass);
6154 mono_error_set_type_load_name (error, name, g_strdup (""), "");
6156 ICALL_EXPORT MonoReflectionType *
6157 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6160 MonoReflectionType *ret;
6161 MonoClass *klass, *aklass;
6163 klass = mono_class_from_mono_type (type->type);
6164 check_for_invalid_type (klass, &error);
6165 if (mono_error_set_pending_exception (&error))
6168 if (rank == 0) //single dimentional array
6169 aklass = mono_array_class_get (klass, 1);
6171 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6173 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6174 mono_error_set_pending_exception (&error);
6179 ICALL_EXPORT MonoReflectionType *
6180 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6183 MonoReflectionType *ret;
6186 klass = mono_class_from_mono_type (type->type);
6187 mono_class_init_checked (klass, &error);
6188 if (mono_error_set_pending_exception (&error))
6191 check_for_invalid_type (klass, &error);
6192 if (mono_error_set_pending_exception (&error))
6195 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6196 mono_error_set_pending_exception (&error);
6201 ICALL_EXPORT MonoReflectionType *
6202 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6205 MonoReflectionType *ret;
6206 MonoClass *klass, *pklass;
6208 klass = mono_class_from_mono_type (type->type);
6209 mono_class_init_checked (klass, &error);
6210 if (mono_error_set_pending_exception (&error))
6212 check_for_invalid_type (klass, &error);
6213 if (mono_error_set_pending_exception (&error))
6216 pklass = mono_ptr_class_get (type->type);
6218 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6219 mono_error_set_pending_exception (&error);
6224 ICALL_EXPORT MonoObject *
6225 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6226 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6229 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6230 MonoObject *delegate;
6232 MonoMethod *method = info->method;
6233 MonoMethodSignature *sig = mono_method_signature(method);
6235 mono_class_init_checked (delegate_class, &error);
6236 if (mono_error_set_pending_exception (&error))
6239 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6240 /* FIXME improve this exception message */
6241 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6243 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6244 mono_error_set_pending_exception (&error);
6248 if (mono_security_core_clr_enabled ()) {
6249 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6250 if (throwOnBindFailure)
6251 mono_error_set_pending_exception (&error);
6253 mono_error_cleanup (&error);
6258 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6259 if (!method->is_inflated) {
6260 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"));
6265 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6266 if (mono_error_set_pending_exception (&error))
6269 if (method_is_dynamic (method)) {
6270 /* Creating a trampoline would leak memory */
6271 func = mono_compile_method_checked (method, &error);
6272 if (mono_error_set_pending_exception (&error))
6275 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6276 method = mono_object_get_virtual_method (target, method);
6277 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6278 if (mono_error_set_pending_exception (&error))
6280 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6283 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6284 if (mono_error_set_pending_exception (&error))
6289 ICALL_EXPORT MonoMulticastDelegate *
6290 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6293 MonoMulticastDelegate *ret;
6295 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6297 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6298 if (mono_error_set_pending_exception (&error))
6301 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6306 ICALL_EXPORT MonoReflectionMethod*
6307 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6309 MonoReflectionMethod *ret = NULL;
6311 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6312 mono_error_set_pending_exception (&error);
6318 static inline gint32
6319 mono_array_get_byte_length (MonoArray *array)
6325 klass = array->obj.vtable->klass;
6327 if (array->bounds == NULL)
6328 length = array->max_length;
6331 for (i = 0; i < klass->rank; ++ i)
6332 length *= array->bounds [i].length;
6335 switch (klass->element_class->byval_arg.type) {
6338 case MONO_TYPE_BOOLEAN:
6342 case MONO_TYPE_CHAR:
6350 return length * sizeof (gpointer);
6361 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6363 return mono_array_get_byte_length (array);
6367 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6369 return mono_array_get (array, gint8, idx);
6373 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6375 mono_array_set (array, gint8, idx, value);
6378 ICALL_EXPORT MonoBoolean
6379 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6381 guint8 *src_buf, *dest_buf;
6384 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6388 g_assert (count >= 0);
6390 /* This is called directly from the class libraries without going through the managed wrapper */
6391 MONO_CHECK_ARG_NULL (src, FALSE);
6392 MONO_CHECK_ARG_NULL (dest, FALSE);
6394 /* watch out for integer overflow */
6395 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6398 src_buf = (guint8 *)src->vector + src_offset;
6399 dest_buf = (guint8 *)dest->vector + dest_offset;
6402 memcpy (dest_buf, src_buf, count);
6404 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6409 #ifndef DISABLE_REMOTING
6410 ICALL_EXPORT MonoObject *
6411 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6414 MonoDomain *domain = mono_object_domain (this_obj);
6416 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6417 MonoTransparentProxy *tp;
6421 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6422 if (mono_error_set_pending_exception (&error))
6425 tp = (MonoTransparentProxy*) res;
6427 MONO_OBJECT_SETREF (tp, rp, rp);
6428 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6429 klass = mono_class_from_mono_type (type);
6431 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6432 mono_class_setup_vtable (klass);
6433 if (mono_class_has_failure (klass)) {
6434 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6438 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6439 if (mono_error_set_pending_exception (&error))
6441 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6442 if (mono_error_set_pending_exception (&error))
6445 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6446 if (mono_error_set_pending_exception (&error))
6451 ICALL_EXPORT MonoReflectionType *
6452 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6455 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6456 mono_error_set_pending_exception (&error);
6462 /* System.Environment */
6465 ves_icall_System_Environment_get_UserName (void)
6467 /* using glib is more portable */
6468 return mono_string_new (mono_domain_get (), g_get_user_name ());
6472 ICALL_EXPORT MonoString *
6473 ves_icall_System_Environment_get_MachineName (void)
6475 #if defined (HOST_WIN32)
6480 len = MAX_COMPUTERNAME_LENGTH + 1;
6481 buf = g_new (gunichar2, len);
6484 if (GetComputerName (buf, (PDWORD) &len)) {
6486 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6487 mono_error_set_pending_exception (&error);
6492 #elif !defined(DISABLE_SOCKETS)
6496 #if defined _SC_HOST_NAME_MAX
6497 n = sysconf (_SC_HOST_NAME_MAX);
6501 buf = g_malloc (n+1);
6503 if (gethostname (buf, n) == 0){
6505 result = mono_string_new (mono_domain_get (), buf);
6512 return mono_string_new (mono_domain_get (), "mono");
6517 ves_icall_System_Environment_get_Platform (void)
6519 #if defined (TARGET_WIN32)
6522 #elif defined(__MACH__)
6525 // Notice that the value is hidden from user code, and only exposed
6526 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6527 // define and making assumptions based on Unix/128/4 values before there
6528 // was a MacOS define. Lots of code would assume that not-Unix meant
6529 // Windows, but in this case, it would be OSX.
6538 ICALL_EXPORT MonoString *
6539 ves_icall_System_Environment_get_NewLine (void)
6541 #if defined (HOST_WIN32)
6542 return mono_string_new (mono_domain_get (), "\r\n");
6544 return mono_string_new (mono_domain_get (), "\n");
6548 ICALL_EXPORT MonoBoolean
6549 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6551 #if SIZEOF_VOID_P == 8
6555 gboolean isWow64Process = FALSE;
6556 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6557 return (MonoBoolean)isWow64Process;
6559 #elif defined(HAVE_SYS_UTSNAME_H)
6560 struct utsname name;
6562 if (uname (&name) >= 0) {
6563 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6570 ICALL_EXPORT MonoStringHandle
6571 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6575 if (utf8_name == NULL)
6576 return NULL_HANDLE_STRING;
6578 value = g_getenv (utf8_name);
6581 return NULL_HANDLE_STRING;
6583 return mono_string_new_handle (mono_domain_get (), value, error);
6587 * There is no standard way to get at environ.
6590 #ifndef __MINGW32_VERSION
6591 #if defined(__APPLE__)
6592 #if defined (TARGET_OSX)
6593 /* Apple defines this in crt_externs.h but doesn't provide that header for
6594 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6595 * in fact exist on all implementations (so far)
6597 gchar ***_NSGetEnviron(void);
6598 #define environ (*_NSGetEnviron())
6600 static char *mono_environ[1] = { NULL };
6601 #define environ mono_environ
6602 #endif /* defined (TARGET_OSX) */
6610 ICALL_EXPORT MonoArray *
6611 ves_icall_System_Environment_GetCoomandLineArgs (void)
6614 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6615 mono_error_set_pending_exception (&error);
6619 ICALL_EXPORT MonoArray *
6620 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6632 env_strings = GetEnvironmentStrings();
6635 env_string = env_strings;
6636 while (*env_string != '\0') {
6637 /* weird case that MS seems to skip */
6638 if (*env_string != '=')
6640 while (*env_string != '\0')
6646 domain = mono_domain_get ();
6647 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6648 if (mono_error_set_pending_exception (&error))
6653 env_string = env_strings;
6654 while (*env_string != '\0') {
6655 /* weird case that MS seems to skip */
6656 if (*env_string != '=') {
6657 equal_str = wcschr(env_string, '=');
6658 g_assert(equal_str);
6660 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6661 if (mono_error_set_pending_exception (&error))
6664 mono_array_setref (names, n, str);
6667 while (*env_string != '\0')
6672 FreeEnvironmentStrings (env_strings);
6686 for (e = environ; *e != 0; ++ e)
6689 domain = mono_domain_get ();
6690 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6691 if (mono_error_set_pending_exception (&error))
6695 for (e = environ; *e != 0; ++ e) {
6696 parts = g_strsplit (*e, "=", 2);
6698 str = mono_string_new (domain, *parts);
6699 mono_array_setref (names, n, str);
6712 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6715 gunichar2 *utf16_name, *utf16_value;
6717 gchar *utf8_name, *utf8_value;
6722 utf16_name = mono_string_to_utf16 (name);
6723 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6724 SetEnvironmentVariable (utf16_name, NULL);
6725 g_free (utf16_name);
6729 utf16_value = mono_string_to_utf16 (value);
6731 SetEnvironmentVariable (utf16_name, utf16_value);
6733 g_free (utf16_name);
6734 g_free (utf16_value);
6736 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6737 if (mono_error_set_pending_exception (&error))
6740 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6741 g_unsetenv (utf8_name);
6746 utf8_value = mono_string_to_utf8_checked (value, &error);
6747 if (!mono_error_ok (&error)) {
6749 mono_error_set_pending_exception (&error);
6752 g_setenv (utf8_name, utf8_value, TRUE);
6755 g_free (utf8_value);
6760 ves_icall_System_Environment_Exit (int result)
6762 mono_environment_exitcode_set (result);
6764 /* FIXME: There are some cleanup hangs that should be worked out, but
6765 * if the program is going to exit, everything will be cleaned up when
6766 * NaCl exits anyway.
6768 #ifndef __native_client__
6769 if (!mono_runtime_try_shutdown ())
6770 mono_thread_exit ();
6772 /* Suspend all managed threads since the runtime is going away */
6773 mono_thread_suspend_all_other_threads ();
6775 mono_runtime_quit ();
6778 /* we may need to do some cleanup here... */
6782 ICALL_EXPORT MonoStringHandle
6783 ves_icall_System_Environment_GetGacPath (MonoError *error)
6785 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6788 ICALL_EXPORT MonoString*
6789 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6791 #if defined (HOST_WIN32)
6792 #ifndef CSIDL_FLAG_CREATE
6793 #define CSIDL_FLAG_CREATE 0x8000
6796 WCHAR path [MAX_PATH];
6797 /* Create directory if no existing */
6798 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6803 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6804 mono_error_set_pending_exception (&error);
6808 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6810 return mono_string_new (mono_domain_get (), "");
6813 ICALL_EXPORT MonoArray *
6814 ves_icall_System_Environment_GetLogicalDrives (void)
6817 gunichar2 buf [256], *ptr, *dname;
6819 guint initial_size = 127, size = 128;
6822 MonoString *drivestr;
6823 MonoDomain *domain = mono_domain_get ();
6829 while (size > initial_size) {
6830 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6831 if (size > initial_size) {
6834 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6835 initial_size = size;
6849 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6850 if (mono_error_set_pending_exception (&error))
6857 while (*u16) { u16++; len ++; }
6858 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6859 if (mono_error_set_pending_exception (&error))
6862 mono_array_setref (result, ndrives++, drivestr);
6873 ICALL_EXPORT MonoString *
6874 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6877 gunichar2 volume_name [MAX_PATH + 1];
6879 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6881 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6882 mono_error_set_pending_exception (&error);
6886 ICALL_EXPORT MonoStringHandle
6887 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6889 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6892 static const char *encodings [] = {
6894 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6895 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6896 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6898 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6899 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6900 "x_unicode_2_0_utf_7",
6902 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6903 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6905 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6908 "unicodefffe", "utf_16be",
6915 * Returns the internal codepage, if the value of "int_code_page" is
6916 * 1 at entry, and we can not compute a suitable code page number,
6917 * returns the code page as a string
6919 ICALL_EXPORT MonoString*
6920 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6925 char *codepage = NULL;
6927 int want_name = *int_code_page;
6930 *int_code_page = -1;
6932 g_get_charset (&cset);
6933 c = codepage = strdup (cset);
6934 for (c = codepage; *c; c++){
6935 if (isascii (*c) && isalpha (*c))
6940 /* g_print ("charset: %s\n", cset); */
6942 /* handle some common aliases */
6945 for (i = 0; p != 0; ){
6948 p = encodings [++i];
6951 if (strcmp (p, codepage) == 0){
6952 *int_code_page = code;
6955 p = encodings [++i];
6958 if (strstr (codepage, "utf_8") != NULL)
6959 *int_code_page |= 0x10000000;
6962 if (want_name && *int_code_page == -1)
6963 return mono_string_new (mono_domain_get (), cset);
6968 ICALL_EXPORT MonoBoolean
6969 ves_icall_System_Environment_get_HasShutdownStarted (void)
6971 if (mono_runtime_is_shutting_down ())
6974 if (mono_domain_is_unloading (mono_domain_get ()))
6981 ves_icall_System_Environment_BroadcastSettingChange (void)
6984 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6990 ves_icall_System_Environment_get_TickCount (void)
6992 /* this will overflow after ~24 days */
6993 return (gint32) (mono_msec_boottime () & 0xffffffff);
6997 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7002 #ifndef DISABLE_REMOTING
7003 ICALL_EXPORT MonoBoolean
7004 ves_icall_IsTransparentProxy (MonoObject *proxy)
7009 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7015 ICALL_EXPORT MonoReflectionMethod *
7016 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7017 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7019 MonoReflectionMethod *ret = NULL;
7024 MonoMethod **vtable;
7025 MonoMethod *res = NULL;
7027 MONO_CHECK_ARG_NULL (rtype, NULL);
7028 MONO_CHECK_ARG_NULL (rmethod, NULL);
7030 method = rmethod->method;
7031 klass = mono_class_from_mono_type (rtype->type);
7032 mono_class_init_checked (klass, &error);
7033 if (mono_error_set_pending_exception (&error))
7036 if (MONO_CLASS_IS_INTERFACE (klass))
7039 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7042 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7043 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7049 mono_class_setup_vtable (klass);
7050 vtable = klass->vtable;
7052 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7053 gboolean variance_used = FALSE;
7054 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7055 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7057 res = vtable [offs + method->slot];
7059 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7062 if (method->slot != -1)
7063 res = vtable [method->slot];
7069 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7070 mono_error_set_pending_exception (&error);
7075 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7081 klass = mono_class_from_mono_type (type->type);
7082 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7083 if (!is_ok (&error)) {
7084 mono_error_set_pending_exception (&error);
7088 mono_vtable_set_is_remote (vtable, enable);
7091 #else /* DISABLE_REMOTING */
7094 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7096 g_assert_not_reached ();
7101 ICALL_EXPORT MonoObject *
7102 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7109 domain = mono_object_domain (type);
7110 klass = mono_class_from_mono_type (type->type);
7111 mono_class_init_checked (klass, &error);
7112 if (mono_error_set_pending_exception (&error))
7115 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7116 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7120 if (klass->rank >= 1) {
7121 g_assert (klass->rank == 1);
7122 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7123 mono_error_set_pending_exception (&error);
7126 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7127 if (!is_ok (&error)) {
7128 mono_error_set_pending_exception (&error);
7131 /* Bypass remoting object creation check */
7132 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7133 mono_error_set_pending_exception (&error);
7139 ICALL_EXPORT MonoStringHandle
7140 ves_icall_System_IO_get_temp_path (MonoError *error)
7142 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7145 #ifndef PLATFORM_NO_DRIVEINFO
7146 ICALL_EXPORT MonoBoolean
7147 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7148 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7152 ULARGE_INTEGER wapi_free_bytes_avail;
7153 ULARGE_INTEGER wapi_total_number_of_bytes;
7154 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7156 *error = ERROR_SUCCESS;
7157 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7158 &wapi_total_number_of_free_bytes);
7161 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7162 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7163 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7165 *free_bytes_avail = 0;
7166 *total_number_of_bytes = 0;
7167 *total_number_of_free_bytes = 0;
7168 *error = GetLastError ();
7174 ICALL_EXPORT guint32
7175 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7177 return GetDriveType (mono_string_chars (root_path_name));
7181 ICALL_EXPORT gpointer
7182 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7185 gpointer result = mono_compile_method_checked (method, &error);
7186 mono_error_set_pending_exception (&error);
7190 ICALL_EXPORT MonoString *
7191 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7196 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7198 #if defined (HOST_WIN32)
7199 /* Avoid mixing '/' and '\\' */
7202 for (i = strlen (path) - 1; i >= 0; i--)
7203 if (path [i] == '/')
7207 mcpath = mono_string_new (mono_domain_get (), path);
7213 /* this is an icall */
7215 get_bundled_app_config (void)
7218 const gchar *app_config;
7221 gchar *config_file_name, *config_file_path;
7222 gsize len, config_file_path_length, config_ext_length;
7225 domain = mono_domain_get ();
7226 file = domain->setup->configuration_file;
7227 if (!file || file->length == 0)
7230 // Retrieve config file and remove the extension
7231 config_file_name = mono_string_to_utf8_checked (file, &error);
7232 if (mono_error_set_pending_exception (&error))
7234 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7235 if (!config_file_path)
7236 config_file_path = config_file_name;
7238 config_file_path_length = strlen (config_file_path);
7239 config_ext_length = strlen (".config");
7240 if (config_file_path_length <= config_ext_length)
7243 len = config_file_path_length - config_ext_length;
7244 module = (gchar *)g_malloc0 (len + 1);
7245 memcpy (module, config_file_path, len);
7246 // Get the config file from the module name
7247 app_config = mono_config_string_for_assembly_file (module);
7250 if (config_file_name != config_file_path)
7251 g_free (config_file_name);
7252 g_free (config_file_path);
7257 return mono_string_new (mono_domain_get (), app_config);
7260 /* this is an icall */
7261 static MonoStringHandle
7262 get_bundled_machine_config (MonoError *error)
7264 const gchar *machine_config;
7266 machine_config = mono_get_machine_config ();
7268 if (!machine_config)
7269 return NULL_HANDLE_STRING;
7271 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7274 ICALL_EXPORT MonoString *
7275 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7280 path = g_path_get_dirname (mono_get_config_dir ());
7282 #if defined (HOST_WIN32)
7283 /* Avoid mixing '/' and '\\' */
7286 for (i = strlen (path) - 1; i >= 0; i--)
7287 if (path [i] == '/')
7291 ipath = mono_string_new (mono_domain_get (), path);
7297 ICALL_EXPORT gboolean
7298 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7300 MonoPEResourceDataEntry *entry;
7303 if (!assembly || !result || !size)
7308 image = assembly->assembly->image;
7309 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7313 *result = mono_image_rva_map (image, entry->rde_data_offset);
7318 *size = entry->rde_size;
7323 ICALL_EXPORT MonoBoolean
7324 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7326 return mono_is_debugger_attached ();
7329 ICALL_EXPORT MonoBoolean
7330 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7332 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7333 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7339 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7341 if (mono_get_runtime_callbacks ()->debug_log)
7342 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7346 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7348 #if defined (HOST_WIN32)
7349 OutputDebugString (mono_string_chars (message));
7351 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7355 /* Only used for value types */
7356 ICALL_EXPORT MonoObject *
7357 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7364 domain = mono_object_domain (type);
7365 klass = mono_class_from_mono_type (type->type);
7366 mono_class_init_checked (klass, &error);
7367 if (mono_error_set_pending_exception (&error))
7370 if (mono_class_is_nullable (klass))
7371 /* No arguments -> null */
7374 result = mono_object_new_checked (domain, klass, &error);
7375 mono_error_set_pending_exception (&error);
7379 ICALL_EXPORT MonoReflectionMethod *
7380 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7382 MonoReflectionMethod *ret = NULL;
7385 MonoClass *klass, *parent;
7386 MonoGenericContext *generic_inst = NULL;
7387 MonoMethod *method = m->method;
7388 MonoMethod *result = NULL;
7391 if (method->klass == NULL)
7394 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7395 MONO_CLASS_IS_INTERFACE (method->klass) ||
7396 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7399 slot = mono_method_get_vtable_slot (method);
7403 klass = method->klass;
7404 if (klass->generic_class) {
7405 generic_inst = mono_class_get_context (klass);
7406 klass = klass->generic_class->container_class;
7411 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7412 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7413 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7414 or klass is the generic container class and generic_inst is the instantiation.
7416 when we go to the parent, if the parent is an open constructed type, we need to
7417 replace the type parameters by the definitions from the generic_inst, and then take it
7418 apart again into the klass and the generic_inst.
7420 For cases like this:
7421 class C<T> : B<T, int> {
7422 public override void Foo () { ... }
7424 class B<U,V> : A<HashMap<U,V>> {
7425 public override void Foo () { ... }
7428 public virtual void Foo () { ... }
7431 if at each iteration the parent isn't open, we can skip inflating it. if at some
7432 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7435 MonoGenericContext *parent_inst = NULL;
7436 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7437 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7438 if (!mono_error_ok (&error)) {
7439 mono_error_set_pending_exception (&error);
7443 if (parent->generic_class) {
7444 parent_inst = mono_class_get_context (parent);
7445 parent = parent->generic_class->container_class;
7448 mono_class_setup_vtable (parent);
7449 if (parent->vtable_size <= slot)
7452 generic_inst = parent_inst;
7455 klass = klass->parent;
7458 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7459 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7460 if (!mono_error_ok (&error)) {
7461 mono_error_set_pending_exception (&error);
7465 generic_inst = NULL;
7467 if (klass->generic_class) {
7468 generic_inst = mono_class_get_context (klass);
7469 klass = klass->generic_class->container_class;
7475 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7476 if (!mono_error_ok (&error)) {
7477 mono_error_set_pending_exception (&error);
7482 if (klass == method->klass)
7485 /*This is possible if definition == FALSE.
7486 * Do it here to be really sure we don't read invalid memory.
7488 if (slot >= klass->vtable_size)
7491 mono_class_setup_vtable (klass);
7493 result = klass->vtable [slot];
7494 if (result == NULL) {
7495 /* It is an abstract method */
7496 gboolean found = FALSE;
7497 gpointer iter = NULL;
7498 while ((result = mono_class_get_methods (klass, &iter))) {
7499 if (result->slot == slot) {
7504 /* found might be FALSE if we looked in an abstract class
7505 * that doesn't override an abstract method of its
7507 * abstract class Base {
7508 * public abstract void Foo ();
7510 * abstract class Derived : Base { }
7511 * class Child : Derived {
7512 * public override void Foo () { }
7515 * if m was Child.Foo and we ask for the base method,
7516 * then we get here with klass == Derived and found == FALSE
7518 /* but it shouldn't be the case that if we're looking
7519 * for the definition and didn't find a result; the
7520 * loop above should've taken us as far as we could
7522 g_assert (!(definition && !found));
7527 g_assert (result != NULL);
7529 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7530 mono_error_set_pending_exception (&error);
7534 ICALL_EXPORT MonoString*
7535 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7537 MonoMethod *method = m->method;
7539 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7544 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7546 iter->sig = *(MonoMethodSignature**)argsp;
7548 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7549 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7552 /* FIXME: it's not documented what start is exactly... */
7556 iter->args = argsp + sizeof (gpointer);
7558 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7560 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7563 ICALL_EXPORT MonoTypedRef
7564 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7566 guint32 i, arg_size;
7570 i = iter->sig->sentinelpos + iter->next_arg;
7572 g_assert (i < iter->sig->param_count);
7574 res.type = iter->sig->params [i];
7575 res.klass = mono_class_from_mono_type (res.type);
7576 arg_size = mono_type_stack_size (res.type, &align);
7577 #if defined(__arm__) || defined(__mips__)
7578 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7580 res.value = iter->args;
7581 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7582 /* Values are stored as 8 byte register sized objects, but 'value'
7583 * is dereferenced as a pointer in other routines.
7585 res.value = (char*)res.value + 4;
7587 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7588 if (arg_size <= sizeof (gpointer)) {
7590 int padding = arg_size - mono_type_size (res.type, &dummy);
7591 res.value = (guint8*)res.value + padding;
7594 iter->args = (char*)iter->args + arg_size;
7597 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7602 ICALL_EXPORT MonoTypedRef
7603 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7605 guint32 i, arg_size;
7609 i = iter->sig->sentinelpos + iter->next_arg;
7611 g_assert (i < iter->sig->param_count);
7613 while (i < iter->sig->param_count) {
7614 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7616 res.type = iter->sig->params [i];
7617 res.klass = mono_class_from_mono_type (res.type);
7618 /* FIXME: endianess issue... */
7619 arg_size = mono_type_stack_size (res.type, &align);
7620 #if defined(__arm__) || defined(__mips__)
7621 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7623 res.value = iter->args;
7624 iter->args = (char*)iter->args + arg_size;
7626 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7629 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7637 ICALL_EXPORT MonoType*
7638 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7642 i = iter->sig->sentinelpos + iter->next_arg;
7644 g_assert (i < iter->sig->param_count);
7646 return iter->sig->params [i];
7649 ICALL_EXPORT MonoObject*
7650 mono_TypedReference_ToObject (MonoTypedRef* tref)
7653 MonoObject *result = NULL;
7654 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7655 MonoObject** objp = (MonoObject **)tref->value;
7659 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7660 mono_error_set_pending_exception (&error);
7664 ICALL_EXPORT MonoTypedRef
7665 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7668 MonoReflectionField *f;
7670 MonoType *ftype = NULL;
7674 memset (&res, 0, sizeof (res));
7677 g_assert (mono_array_length (fields) > 0);
7679 klass = target->vtable->klass;
7681 for (i = 0; i < mono_array_length (fields); ++i) {
7682 f = mono_array_get (fields, MonoReflectionField*, i);
7684 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7687 if (f->field->parent != klass) {
7688 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7692 p = (guint8*)target + f->field->offset;
7694 p += f->field->offset - sizeof (MonoObject);
7695 klass = mono_class_from_mono_type (f->field->type);
7696 ftype = f->field->type;
7700 res.klass = mono_class_from_mono_type (ftype);
7707 prelink_method (MonoMethod *method, MonoError *error)
7709 const char *exc_class, *exc_arg;
7711 mono_error_init (error);
7712 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7714 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7716 mono_error_set_exception_instance (error,
7717 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7720 /* create the wrapper, too? */
7724 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7728 prelink_method (method->method, &error);
7729 mono_error_set_pending_exception (&error);
7733 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7736 MonoClass *klass = mono_class_from_mono_type (type->type);
7738 gpointer iter = NULL;
7740 mono_class_init_checked (klass, &error);
7741 if (mono_error_set_pending_exception (&error))
7744 while ((m = mono_class_get_methods (klass, &iter))) {
7745 prelink_method (m, &error);
7746 if (mono_error_set_pending_exception (&error))
7751 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7753 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7754 gint32 const **exponents,
7755 gunichar2 const **digitLowerTable,
7756 gunichar2 const **digitUpperTable,
7757 gint64 const **tenPowersList,
7758 gint32 const **decHexDigits)
7760 *mantissas = Formatter_MantissaBitsTable;
7761 *exponents = Formatter_TensExponentTable;
7762 *digitLowerTable = Formatter_DigitLowerTable;
7763 *digitUpperTable = Formatter_DigitUpperTable;
7764 *tenPowersList = Formatter_TenPowersList;
7765 *decHexDigits = Formatter_DecHexDigits;
7769 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7770 * and avoid useless allocations.
7773 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7775 MonoReflectionType *rt;
7779 mono_error_init (error);
7780 for (i = 0; i < type->num_mods; ++i) {
7781 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7786 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7787 return_val_if_nok (error, NULL);
7789 for (i = 0; i < type->num_mods; ++i) {
7790 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7791 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7792 return_val_if_nok (error, NULL);
7794 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7795 return_val_if_nok (error, NULL);
7797 mono_array_setref (res, count, rt);
7804 ICALL_EXPORT MonoArray*
7805 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7808 MonoType *type = param->ClassImpl->type;
7809 MonoClass *member_class = mono_object_class (param->MemberImpl);
7810 MonoMethod *method = NULL;
7813 MonoMethodSignature *sig;
7816 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7817 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7818 method = rmethod->method;
7819 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7820 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7821 if (!(method = prop->property->get))
7822 method = prop->property->set;
7825 char *type_name = mono_type_get_full_name (member_class);
7826 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7827 MonoException *ex = mono_get_exception_not_supported (msg);
7830 mono_set_pending_exception (ex);
7834 image = method->klass->image;
7835 pos = param->PositionImpl;
7836 sig = mono_method_signature (method);
7840 type = sig->params [pos];
7842 res = type_array_from_modifiers (image, type, optional, &error);
7843 mono_error_set_pending_exception (&error);
7848 get_property_type (MonoProperty *prop)
7850 MonoMethodSignature *sig;
7852 sig = mono_method_signature (prop->get);
7854 } else if (prop->set) {
7855 sig = mono_method_signature (prop->set);
7856 return sig->params [sig->param_count - 1];
7861 ICALL_EXPORT MonoArray*
7862 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7865 MonoType *type = get_property_type (property->property);
7866 MonoImage *image = property->klass->image;
7871 res = type_array_from_modifiers (image, type, optional, &error);
7872 mono_error_set_pending_exception (&error);
7877 *Construct a MonoType suited to be used to decode a constant blob object.
7879 * @type is the target type which will be constructed
7880 * @blob_type is the blob type, for example, that comes from the constant table
7881 * @real_type is the expected constructed type.
7884 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7886 type->type = blob_type;
7887 type->data.klass = NULL;
7888 if (blob_type == MONO_TYPE_CLASS)
7889 type->data.klass = mono_defaults.object_class;
7890 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7891 /* For enums, we need to use the base type */
7892 type->type = MONO_TYPE_VALUETYPE;
7893 type->data.klass = mono_class_from_mono_type (real_type);
7895 type->data.klass = mono_class_from_mono_type (real_type);
7898 ICALL_EXPORT MonoObject*
7899 property_info_get_default_value (MonoReflectionProperty *property)
7903 MonoProperty *prop = property->property;
7904 MonoType *type = get_property_type (prop);
7905 MonoDomain *domain = mono_object_domain (property);
7906 MonoTypeEnum def_type;
7907 const char *def_value;
7910 mono_class_init (prop->parent);
7912 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7913 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7917 def_value = mono_class_get_property_default_value (prop, &def_type);
7919 mono_type_from_blob_type (&blob_type, def_type, type);
7920 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7922 mono_error_set_pending_exception (&error);
7926 ICALL_EXPORT MonoBoolean
7927 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7930 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7931 MonoCustomAttrInfo *cinfo;
7934 mono_class_init_checked (attr_class, &error);
7935 if (mono_error_set_pending_exception (&error))
7938 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7939 if (!is_ok (&error)) {
7940 mono_error_set_pending_exception (&error);
7945 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7947 mono_custom_attrs_free (cinfo);
7951 ICALL_EXPORT MonoArray*
7952 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7954 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7959 mono_class_init_checked (attr_class, &error);
7960 if (mono_error_set_pending_exception (&error))
7964 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7965 if (!mono_error_ok (&error)) {
7966 mono_error_set_pending_exception (&error);
7973 ICALL_EXPORT MonoArray*
7974 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7978 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7979 mono_error_set_pending_exception (&error);
7984 ICALL_EXPORT MonoString*
7985 ves_icall_Mono_Runtime_GetDisplayName (void)
7988 MonoString *display_name;
7990 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7991 display_name = mono_string_new (mono_domain_get (), info);
7993 return display_name;
7996 ICALL_EXPORT MonoString*
7997 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8000 MonoString *message;
8004 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8005 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8008 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8010 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8011 if (mono_error_set_pending_exception (&error))
8018 ICALL_EXPORT gpointer
8019 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8021 return GetCurrentProcess ();
8024 ICALL_EXPORT MonoBoolean
8025 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8027 return GetExitCodeProcess (handle, (guint32*) exitcode);
8030 ICALL_EXPORT MonoBoolean
8031 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8033 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8034 return CloseHandle (handle);
8036 return CloseProcess (handle);
8040 ICALL_EXPORT MonoBoolean
8041 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8043 return TerminateProcess (handle, exitcode);
8047 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8050 return WaitForInputIdle (handle, milliseconds);
8052 /*TODO: Not implemented*/
8053 return WAIT_TIMEOUT;
8057 ICALL_EXPORT MonoBoolean
8058 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8060 return GetProcessWorkingSetSize (handle, min, max);
8063 ICALL_EXPORT MonoBoolean
8064 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8066 return SetProcessWorkingSetSize (handle, min, max);
8069 ICALL_EXPORT MonoBoolean
8070 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8072 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8076 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8078 return mono_process_current_pid ();
8082 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8084 return GetPriorityClass (handle);
8087 ICALL_EXPORT MonoBoolean
8088 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8090 return SetPriorityClass (handle, priorityClass);
8093 ICALL_EXPORT MonoBoolean
8094 ves_icall_Mono_Btls_Provider_IsSupported (void)
8103 #ifndef DISABLE_ICALL_TABLES
8105 #define ICALL_TYPE(id,name,first)
8106 #define ICALL(id,name,func) Icall_ ## id,
8107 #define HANDLES(inner) inner
8110 #include "metadata/icall-def.h"
8116 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8117 #define ICALL(id,name,func)
8119 #define HANDLES(inner) inner
8121 #include "metadata/icall-def.h"
8127 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8128 #define ICALL(id,name,func)
8130 #define HANDLES(inner) inner
8132 guint16 first_icall;
8135 static const IcallTypeDesc
8136 icall_type_descs [] = {
8137 #include "metadata/icall-def.h"
8141 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8144 #define HANDLES(inner) inner
8146 #define ICALL_TYPE(id,name,first)
8149 #ifdef HAVE_ARRAY_ELEM_INIT
8150 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8151 #define MSGSTRFIELD1(line) str##line
8153 static const struct msgstrtn_t {
8154 #define ICALL(id,name,func)
8156 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8157 #include "metadata/icall-def.h"
8159 } icall_type_names_str = {
8160 #define ICALL_TYPE(id,name,first) (name),
8161 #include "metadata/icall-def.h"
8164 static const guint16 icall_type_names_idx [] = {
8165 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8166 #include "metadata/icall-def.h"
8169 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8171 static const struct msgstr_t {
8173 #define ICALL_TYPE(id,name,first)
8174 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8175 #include "metadata/icall-def.h"
8177 } icall_names_str = {
8178 #define ICALL(id,name,func) (name),
8179 #include "metadata/icall-def.h"
8182 static const guint16 icall_names_idx [] = {
8183 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8184 #include "metadata/icall-def.h"
8187 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8193 #define ICALL_TYPE(id,name,first) name,
8194 #define ICALL(id,name,func)
8195 static const char* const
8196 icall_type_names [] = {
8197 #include "metadata/icall-def.h"
8201 #define icall_type_name_get(id) (icall_type_names [(id)])
8205 #define ICALL_TYPE(id,name,first)
8206 #define ICALL(id,name,func) name,
8207 static const char* const
8209 #include "metadata/icall-def.h"
8212 #define icall_name_get(id) icall_names [(id)]
8214 #endif /* !HAVE_ARRAY_ELEM_INIT */
8217 #define HANDLES(inner) inner
8220 #define ICALL_TYPE(id,name,first)
8221 #define ICALL(id,name,func) func,
8222 static const gconstpointer
8223 icall_functions [] = {
8224 #include "metadata/icall-def.h"
8228 #ifdef ENABLE_ICALL_SYMBOL_MAP
8230 #define HANDLES(inner) inner
8233 #define ICALL_TYPE(id,name,first)
8234 #define ICALL(id,name,func) #func,
8235 static const gconstpointer
8236 icall_symbols [] = {
8237 #include "metadata/icall-def.h"
8244 #define ICALL_TYPE(id,name,first)
8245 #define ICALL(id,name,func) 0,
8247 #define HANDLES(inner) 1,
8249 icall_uses_handles [] = {
8250 #include "metadata/icall-def.h"
8255 #endif /* DISABLE_ICALL_TABLES */
8257 static mono_mutex_t icall_mutex;
8258 static GHashTable *icall_hash = NULL;
8259 static GHashTable *jit_icall_hash_name = NULL;
8260 static GHashTable *jit_icall_hash_addr = NULL;
8263 mono_icall_init (void)
8265 #ifndef DISABLE_ICALL_TABLES
8268 /* check that tables are sorted: disable in release */
8271 const char *prev_class = NULL;
8272 const char *prev_method;
8274 for (i = 0; i < Icall_type_num; ++i) {
8275 const IcallTypeDesc *desc;
8278 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8279 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8280 prev_class = icall_type_name_get (i);
8281 desc = &icall_type_descs [i];
8282 num_icalls = icall_desc_num_icalls (desc);
8283 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8284 for (j = 0; j < num_icalls; ++j) {
8285 const char *methodn = icall_name_get (desc->first_icall + j);
8286 if (prev_method && strcmp (prev_method, methodn) >= 0)
8287 g_print ("method %s should come before method %s\n", methodn, prev_method);
8288 prev_method = methodn;
8294 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8295 mono_os_mutex_init (&icall_mutex);
8299 mono_icall_lock (void)
8301 mono_locks_os_acquire (&icall_mutex, IcallLock);
8305 mono_icall_unlock (void)
8307 mono_locks_os_release (&icall_mutex, IcallLock);
8311 mono_icall_cleanup (void)
8313 g_hash_table_destroy (icall_hash);
8314 g_hash_table_destroy (jit_icall_hash_name);
8315 g_hash_table_destroy (jit_icall_hash_addr);
8316 mono_os_mutex_destroy (&icall_mutex);
8320 * mono_add_internal_call:
8321 * @name: method specification to surface to the managed world
8322 * @method: pointer to a C method to invoke when the method is called
8324 * This method surfaces the C function pointed by @method as a method
8325 * that has been surfaced in managed code with the method specified in
8326 * @name as an internal call.
8328 * Internal calls are surfaced to all app domains loaded and they are
8329 * accessibly by a type with the specified name.
8331 * You must provide a fully qualified type name, that is namespaces
8332 * and type name, followed by a colon and the method name, with an
8333 * optional signature to bind.
8335 * For example, the following are all valid declarations:
8337 * "MyApp.Services.ScriptService:Accelerate"
8338 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8340 * You use method parameters in cases where there might be more than
8341 * one surface method to managed code. That way you can register different
8342 * internal calls for different method overloads.
8344 * The internal calls are invoked with no marshalling. This means that .NET
8345 * types like System.String are exposed as `MonoString *` parameters. This is
8346 * different than the way that strings are surfaced in P/Invoke.
8348 * For more information on how the parameters are marshalled, see the
8349 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8352 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8353 * reference for more information on the format of method descriptions.
8356 mono_add_internal_call (const char *name, gconstpointer method)
8360 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8362 mono_icall_unlock ();
8365 #ifndef DISABLE_ICALL_TABLES
8367 #ifdef HAVE_ARRAY_ELEM_INIT
8369 compare_method_imap (const void *key, const void *elem)
8371 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8372 return strcmp (key, method_name);
8376 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8378 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);
8381 return (nameslot - &icall_names_idx [0]);
8385 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8387 gsize slotnum = find_slot_icall (imap, name);
8390 return (gboolean)icall_uses_handles [slotnum];
8394 find_method_icall (const IcallTypeDesc *imap, const char *name)
8396 gsize slotnum = find_slot_icall (imap, name);
8399 return (gpointer)icall_functions [slotnum];
8403 compare_class_imap (const void *key, const void *elem)
8405 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8406 return strcmp (key, class_name);
8409 static const IcallTypeDesc*
8410 find_class_icalls (const char *name)
8412 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);
8415 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8418 #else /* HAVE_ARRAY_ELEM_INIT */
8421 compare_method_imap (const void *key, const void *elem)
8423 const char** method_name = (const char**)elem;
8424 return strcmp (key, *method_name);
8428 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8430 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8433 return nameslot - icall_names;
8437 find_method_icall (const IcallTypeDesc *imap, const char *name)
8439 gsize slotnum = find_slot_icall (imap, name);
8442 return (gpointer)icall_functions [slotnum];
8446 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8448 gsize slotnum = find_slot_icall (imap, name);
8451 return (gboolean)icall_uses_handles [slotnum];
8455 compare_class_imap (const void *key, const void *elem)
8457 const char** class_name = (const char**)elem;
8458 return strcmp (key, *class_name);
8461 static const IcallTypeDesc*
8462 find_class_icalls (const char *name)
8464 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8467 return &icall_type_descs [nameslot - icall_type_names];
8470 #endif /* HAVE_ARRAY_ELEM_INIT */
8472 #endif /* DISABLE_ICALL_TABLES */
8475 * we should probably export this as an helper (handle nested types).
8476 * Returns the number of chars written in buf.
8479 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8481 int nspacelen, cnamelen;
8482 nspacelen = strlen (klass->name_space);
8483 cnamelen = strlen (klass->name);
8484 if (nspacelen + cnamelen + 2 > bufsize)
8487 memcpy (buf, klass->name_space, nspacelen);
8488 buf [nspacelen ++] = '.';
8490 memcpy (buf + nspacelen, klass->name, cnamelen);
8491 buf [nspacelen + cnamelen] = 0;
8492 return nspacelen + cnamelen;
8495 #ifdef DISABLE_ICALL_TABLES
8497 no_icall_table (void)
8499 g_assert_not_reached ();
8504 * mono_lookup_internal_call_full:
8505 * @method: the method to look up
8506 * @uses_handles: out argument if method needs handles around managed objects.
8508 * Returns a pointer to the icall code for the given method. If
8509 * uses_handles is not NULL, it will be set to TRUE if the method
8510 * needs managed objects wrapped using the infrastructure in handle.h
8512 * If the method is not found, warns and returns NULL.
8515 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8520 int typelen = 0, mlen, siglen;
8522 #ifndef DISABLE_ICALL_TABLES
8523 const IcallTypeDesc *imap = NULL;
8526 g_assert (method != NULL);
8528 if (method->is_inflated)
8529 method = ((MonoMethodInflated *) method)->declaring;
8531 if (method->klass->nested_in) {
8532 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8536 mname [pos++] = '/';
8539 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8545 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8550 #ifndef DISABLE_ICALL_TABLES
8551 imap = find_class_icalls (mname);
8554 mname [typelen] = ':';
8555 mname [typelen + 1] = ':';
8557 mlen = strlen (method->name);
8558 memcpy (mname + typelen + 2, method->name, mlen);
8559 sigstart = mname + typelen + 2 + mlen;
8562 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8563 siglen = strlen (tmpsig);
8564 if (typelen + mlen + siglen + 6 > sizeof (mname))
8567 memcpy (sigstart + 1, tmpsig, siglen);
8568 sigstart [siglen + 1] = ')';
8569 sigstart [siglen + 2] = 0;
8574 res = g_hash_table_lookup (icall_hash, mname);
8577 *uses_handles = FALSE;
8578 mono_icall_unlock ();;
8581 /* try without signature */
8583 res = g_hash_table_lookup (icall_hash, mname);
8586 *uses_handles = FALSE;
8587 mono_icall_unlock ();
8591 #ifdef DISABLE_ICALL_TABLES
8592 mono_icall_unlock ();
8593 /* Fail only when the result is actually used */
8594 /* mono_marshal_get_native_wrapper () depends on this */
8595 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8596 return ves_icall_System_String_ctor_RedirectToCreateString;
8598 return no_icall_table;
8600 /* it wasn't found in the static call tables */
8603 *uses_handles = FALSE;
8604 mono_icall_unlock ();
8607 res = find_method_icall (imap, sigstart - mlen);
8610 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8611 mono_icall_unlock ();
8614 /* try _with_ signature */
8616 res = find_method_icall (imap, sigstart - mlen);
8619 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8620 mono_icall_unlock ();
8624 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8625 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8626 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8627 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8628 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");
8629 g_print ("If you see other errors or faults after this message they are probably related\n");
8630 g_print ("and you need to fix your mono install first.\n");
8632 mono_icall_unlock ();
8639 mono_lookup_internal_call (MonoMethod *method)
8641 return mono_lookup_internal_call_full (method, NULL);
8644 #ifdef ENABLE_ICALL_SYMBOL_MAP
8646 func_cmp (gconstpointer key, gconstpointer p)
8648 return (gsize)key - (gsize)*(gsize*)p;
8653 * mono_lookup_icall_symbol:
8655 * Given the icall METHOD, returns its C symbol.
8658 mono_lookup_icall_symbol (MonoMethod *m)
8660 #ifdef DISABLE_ICALL_TABLES
8661 g_assert_not_reached ();
8664 #ifdef ENABLE_ICALL_SYMBOL_MAP
8668 static gconstpointer *functions_sorted;
8669 static const char**symbols_sorted;
8670 static gboolean inited;
8675 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8676 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8677 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8678 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8679 /* Bubble sort the two arrays */
8683 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8684 if (functions_sorted [i] > functions_sorted [i + 1]) {
8687 tmp = functions_sorted [i];
8688 functions_sorted [i] = functions_sorted [i + 1];
8689 functions_sorted [i + 1] = tmp;
8690 tmp = symbols_sorted [i];
8691 symbols_sorted [i] = symbols_sorted [i + 1];
8692 symbols_sorted [i + 1] = tmp;
8699 func = mono_lookup_internal_call (m);
8702 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8706 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8708 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8709 g_assert_not_reached ();
8716 type_from_typename (char *type_name)
8718 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8720 if (!strcmp (type_name, "int"))
8721 klass = mono_defaults.int_class;
8722 else if (!strcmp (type_name, "ptr"))
8723 klass = mono_defaults.int_class;
8724 else if (!strcmp (type_name, "void"))
8725 klass = mono_defaults.void_class;
8726 else if (!strcmp (type_name, "int32"))
8727 klass = mono_defaults.int32_class;
8728 else if (!strcmp (type_name, "uint32"))
8729 klass = mono_defaults.uint32_class;
8730 else if (!strcmp (type_name, "int8"))
8731 klass = mono_defaults.sbyte_class;
8732 else if (!strcmp (type_name, "uint8"))
8733 klass = mono_defaults.byte_class;
8734 else if (!strcmp (type_name, "int16"))
8735 klass = mono_defaults.int16_class;
8736 else if (!strcmp (type_name, "uint16"))
8737 klass = mono_defaults.uint16_class;
8738 else if (!strcmp (type_name, "long"))
8739 klass = mono_defaults.int64_class;
8740 else if (!strcmp (type_name, "ulong"))
8741 klass = mono_defaults.uint64_class;
8742 else if (!strcmp (type_name, "float"))
8743 klass = mono_defaults.single_class;
8744 else if (!strcmp (type_name, "double"))
8745 klass = mono_defaults.double_class;
8746 else if (!strcmp (type_name, "object"))
8747 klass = mono_defaults.object_class;
8748 else if (!strcmp (type_name, "obj"))
8749 klass = mono_defaults.object_class;
8750 else if (!strcmp (type_name, "string"))
8751 klass = mono_defaults.string_class;
8752 else if (!strcmp (type_name, "bool"))
8753 klass = mono_defaults.boolean_class;
8754 else if (!strcmp (type_name, "boolean"))
8755 klass = mono_defaults.boolean_class;
8757 g_error ("%s", type_name);
8758 g_assert_not_reached ();
8760 return &klass->byval_arg;
8764 * LOCKING: Take the corlib image lock.
8766 MonoMethodSignature*
8767 mono_create_icall_signature (const char *sigstr)
8772 MonoMethodSignature *res, *res2;
8773 MonoImage *corlib = mono_defaults.corlib;
8775 mono_image_lock (corlib);
8776 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8777 mono_image_unlock (corlib);
8782 parts = g_strsplit (sigstr, " ", 256);
8791 res = mono_metadata_signature_alloc (corlib, len - 1);
8796 * Under windows, the default pinvoke calling convention is STDCALL but
8799 res->call_convention = MONO_CALL_C;
8802 res->ret = type_from_typename (parts [0]);
8803 for (i = 1; i < len; ++i) {
8804 res->params [i - 1] = type_from_typename (parts [i]);
8809 mono_image_lock (corlib);
8810 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8812 res = res2; /*Value is allocated in the image pool*/
8814 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8815 mono_image_unlock (corlib);
8821 mono_find_jit_icall_by_name (const char *name)
8823 MonoJitICallInfo *info;
8824 g_assert (jit_icall_hash_name);
8827 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8828 mono_icall_unlock ();
8833 mono_find_jit_icall_by_addr (gconstpointer addr)
8835 MonoJitICallInfo *info;
8836 g_assert (jit_icall_hash_addr);
8839 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8840 mono_icall_unlock ();
8846 * mono_get_jit_icall_info:
8848 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8849 * caller should access it while holding the icall lock.
8852 mono_get_jit_icall_info (void)
8854 return jit_icall_hash_name;
8858 * mono_lookup_jit_icall_symbol:
8860 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8863 mono_lookup_jit_icall_symbol (const char *name)
8865 MonoJitICallInfo *info;
8866 const char *res = NULL;
8869 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8871 res = info->c_symbol;
8872 mono_icall_unlock ();
8877 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8880 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8881 mono_icall_unlock ();
8885 * 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
8886 * icalls without wrappers in some cases.
8889 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8891 MonoJitICallInfo *info;
8898 if (!jit_icall_hash_name) {
8899 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8900 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8903 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8904 g_warning ("jit icall already defined \"%s\"\n", name);
8905 g_assert_not_reached ();
8908 info = g_new0 (MonoJitICallInfo, 1);
8913 info->c_symbol = c_symbol;
8914 info->no_raise = no_raise;
8917 info->wrapper = func;
8919 info->wrapper = NULL;
8922 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8923 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8925 mono_icall_unlock ();
8930 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8932 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);