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), NULL, "");
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 MonoException *exc = mono_class_get_exception_for_failure (klass);
4437 mono_set_pending_exception (exc);
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)
6149 mono_error_init (error);
6151 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6154 name = mono_type_get_full_name (klass);
6155 str = mono_string_new (mono_domain_get (), name);
6157 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6160 ICALL_EXPORT MonoReflectionType *
6161 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6164 MonoReflectionType *ret;
6165 MonoClass *klass, *aklass;
6167 klass = mono_class_from_mono_type (type->type);
6168 check_for_invalid_type (klass, &error);
6169 mono_error_set_pending_exception (&error);
6171 if (rank == 0) //single dimentional array
6172 aklass = mono_array_class_get (klass, 1);
6174 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6176 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6177 mono_error_set_pending_exception (&error);
6182 ICALL_EXPORT MonoReflectionType *
6183 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6186 MonoReflectionType *ret;
6189 klass = mono_class_from_mono_type (type->type);
6190 mono_class_init_checked (klass, &error);
6191 if (mono_error_set_pending_exception (&error))
6194 check_for_invalid_type (klass, &error);
6195 if (mono_error_set_pending_exception (&error))
6198 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6199 mono_error_set_pending_exception (&error);
6204 ICALL_EXPORT MonoReflectionType *
6205 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6208 MonoReflectionType *ret;
6209 MonoClass *klass, *pklass;
6211 klass = mono_class_from_mono_type (type->type);
6212 mono_class_init_checked (klass, &error);
6213 if (mono_error_set_pending_exception (&error))
6215 check_for_invalid_type (klass, &error);
6216 if (mono_error_set_pending_exception (&error))
6219 pklass = mono_ptr_class_get (type->type);
6221 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6222 mono_error_set_pending_exception (&error);
6227 ICALL_EXPORT MonoObject *
6228 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6229 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6232 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6233 MonoObject *delegate;
6235 MonoMethod *method = info->method;
6236 MonoMethodSignature *sig = mono_method_signature(method);
6238 mono_class_init_checked (delegate_class, &error);
6239 if (mono_error_set_pending_exception (&error))
6242 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6243 /* FIXME improve this exception message */
6244 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6246 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6247 mono_error_set_pending_exception (&error);
6251 if (mono_security_core_clr_enabled ()) {
6252 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6253 if (throwOnBindFailure)
6254 mono_error_set_pending_exception (&error);
6256 mono_error_cleanup (&error);
6261 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6262 if (!method->is_inflated) {
6263 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"));
6268 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6269 if (mono_error_set_pending_exception (&error))
6272 if (method_is_dynamic (method)) {
6273 /* Creating a trampoline would leak memory */
6274 func = mono_compile_method_checked (method, &error);
6275 if (mono_error_set_pending_exception (&error))
6278 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6279 method = mono_object_get_virtual_method (target, method);
6280 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6281 if (mono_error_set_pending_exception (&error))
6283 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6286 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6287 if (mono_error_set_pending_exception (&error))
6292 ICALL_EXPORT MonoMulticastDelegate *
6293 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6296 MonoMulticastDelegate *ret;
6298 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6300 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6301 if (mono_error_set_pending_exception (&error))
6304 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6309 ICALL_EXPORT MonoReflectionMethod*
6310 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6312 MonoReflectionMethod *ret = NULL;
6314 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6315 mono_error_set_pending_exception (&error);
6321 static inline gint32
6322 mono_array_get_byte_length (MonoArray *array)
6328 klass = array->obj.vtable->klass;
6330 if (array->bounds == NULL)
6331 length = array->max_length;
6334 for (i = 0; i < klass->rank; ++ i)
6335 length *= array->bounds [i].length;
6338 switch (klass->element_class->byval_arg.type) {
6341 case MONO_TYPE_BOOLEAN:
6345 case MONO_TYPE_CHAR:
6353 return length * sizeof (gpointer);
6364 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6366 return mono_array_get_byte_length (array);
6370 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6372 return mono_array_get (array, gint8, idx);
6376 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6378 mono_array_set (array, gint8, idx, value);
6381 ICALL_EXPORT MonoBoolean
6382 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6384 guint8 *src_buf, *dest_buf;
6387 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6391 g_assert (count >= 0);
6393 /* This is called directly from the class libraries without going through the managed wrapper */
6394 MONO_CHECK_ARG_NULL (src, FALSE);
6395 MONO_CHECK_ARG_NULL (dest, FALSE);
6397 /* watch out for integer overflow */
6398 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6401 src_buf = (guint8 *)src->vector + src_offset;
6402 dest_buf = (guint8 *)dest->vector + dest_offset;
6405 memcpy (dest_buf, src_buf, count);
6407 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6412 #ifndef DISABLE_REMOTING
6413 ICALL_EXPORT MonoObject *
6414 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6417 MonoDomain *domain = mono_object_domain (this_obj);
6419 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6420 MonoTransparentProxy *tp;
6424 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6425 if (mono_error_set_pending_exception (&error))
6428 tp = (MonoTransparentProxy*) res;
6430 MONO_OBJECT_SETREF (tp, rp, rp);
6431 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6432 klass = mono_class_from_mono_type (type);
6434 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6435 mono_class_setup_vtable (klass);
6436 if (mono_class_has_failure (klass)) {
6437 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6441 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6442 if (mono_error_set_pending_exception (&error))
6444 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6445 if (mono_error_set_pending_exception (&error))
6448 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6449 if (mono_error_set_pending_exception (&error))
6454 ICALL_EXPORT MonoReflectionType *
6455 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6458 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6459 mono_error_set_pending_exception (&error);
6465 /* System.Environment */
6468 ves_icall_System_Environment_get_UserName (void)
6470 /* using glib is more portable */
6471 return mono_string_new (mono_domain_get (), g_get_user_name ());
6475 ICALL_EXPORT MonoString *
6476 ves_icall_System_Environment_get_MachineName (void)
6478 #if defined (HOST_WIN32)
6483 len = MAX_COMPUTERNAME_LENGTH + 1;
6484 buf = g_new (gunichar2, len);
6487 if (GetComputerName (buf, (PDWORD) &len)) {
6489 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6490 mono_error_set_pending_exception (&error);
6495 #elif !defined(DISABLE_SOCKETS)
6499 #if defined _SC_HOST_NAME_MAX
6500 n = sysconf (_SC_HOST_NAME_MAX);
6504 buf = g_malloc (n+1);
6506 if (gethostname (buf, n) == 0){
6508 result = mono_string_new (mono_domain_get (), buf);
6515 return mono_string_new (mono_domain_get (), "mono");
6520 ves_icall_System_Environment_get_Platform (void)
6522 #if defined (TARGET_WIN32)
6525 #elif defined(__MACH__)
6528 // Notice that the value is hidden from user code, and only exposed
6529 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6530 // define and making assumptions based on Unix/128/4 values before there
6531 // was a MacOS define. Lots of code would assume that not-Unix meant
6532 // Windows, but in this case, it would be OSX.
6541 ICALL_EXPORT MonoString *
6542 ves_icall_System_Environment_get_NewLine (void)
6544 #if defined (HOST_WIN32)
6545 return mono_string_new (mono_domain_get (), "\r\n");
6547 return mono_string_new (mono_domain_get (), "\n");
6551 ICALL_EXPORT MonoBoolean
6552 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6554 #if SIZEOF_VOID_P == 8
6558 gboolean isWow64Process = FALSE;
6559 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6560 return (MonoBoolean)isWow64Process;
6562 #elif defined(HAVE_SYS_UTSNAME_H)
6563 struct utsname name;
6565 if (uname (&name) >= 0) {
6566 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6573 ICALL_EXPORT MonoStringHandle
6574 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6578 if (utf8_name == NULL)
6579 return NULL_HANDLE_STRING;
6581 value = g_getenv (utf8_name);
6584 return NULL_HANDLE_STRING;
6586 return mono_string_new_handle (mono_domain_get (), value, error);
6590 * There is no standard way to get at environ.
6593 #ifndef __MINGW32_VERSION
6594 #if defined(__APPLE__)
6595 #if defined (TARGET_OSX)
6596 /* Apple defines this in crt_externs.h but doesn't provide that header for
6597 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6598 * in fact exist on all implementations (so far)
6600 gchar ***_NSGetEnviron(void);
6601 #define environ (*_NSGetEnviron())
6603 static char *mono_environ[1] = { NULL };
6604 #define environ mono_environ
6605 #endif /* defined (TARGET_OSX) */
6613 ICALL_EXPORT MonoArray *
6614 ves_icall_System_Environment_GetCoomandLineArgs (void)
6617 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6618 mono_error_set_pending_exception (&error);
6622 ICALL_EXPORT MonoArray *
6623 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6635 env_strings = GetEnvironmentStrings();
6638 env_string = env_strings;
6639 while (*env_string != '\0') {
6640 /* weird case that MS seems to skip */
6641 if (*env_string != '=')
6643 while (*env_string != '\0')
6649 domain = mono_domain_get ();
6650 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6651 if (mono_error_set_pending_exception (&error))
6656 env_string = env_strings;
6657 while (*env_string != '\0') {
6658 /* weird case that MS seems to skip */
6659 if (*env_string != '=') {
6660 equal_str = wcschr(env_string, '=');
6661 g_assert(equal_str);
6663 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6664 if (mono_error_set_pending_exception (&error))
6667 mono_array_setref (names, n, str);
6670 while (*env_string != '\0')
6675 FreeEnvironmentStrings (env_strings);
6689 for (e = environ; *e != 0; ++ e)
6692 domain = mono_domain_get ();
6693 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6694 if (mono_error_set_pending_exception (&error))
6698 for (e = environ; *e != 0; ++ e) {
6699 parts = g_strsplit (*e, "=", 2);
6701 str = mono_string_new (domain, *parts);
6702 mono_array_setref (names, n, str);
6715 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6718 gunichar2 *utf16_name, *utf16_value;
6720 gchar *utf8_name, *utf8_value;
6725 utf16_name = mono_string_to_utf16 (name);
6726 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6727 SetEnvironmentVariable (utf16_name, NULL);
6728 g_free (utf16_name);
6732 utf16_value = mono_string_to_utf16 (value);
6734 SetEnvironmentVariable (utf16_name, utf16_value);
6736 g_free (utf16_name);
6737 g_free (utf16_value);
6739 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6740 if (mono_error_set_pending_exception (&error))
6743 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6744 g_unsetenv (utf8_name);
6749 utf8_value = mono_string_to_utf8_checked (value, &error);
6750 if (!mono_error_ok (&error)) {
6752 mono_error_set_pending_exception (&error);
6755 g_setenv (utf8_name, utf8_value, TRUE);
6758 g_free (utf8_value);
6763 ves_icall_System_Environment_Exit (int result)
6765 mono_environment_exitcode_set (result);
6767 /* FIXME: There are some cleanup hangs that should be worked out, but
6768 * if the program is going to exit, everything will be cleaned up when
6769 * NaCl exits anyway.
6771 #ifndef __native_client__
6772 if (!mono_runtime_try_shutdown ())
6773 mono_thread_exit ();
6775 /* Suspend all managed threads since the runtime is going away */
6776 mono_thread_suspend_all_other_threads ();
6778 mono_runtime_quit ();
6781 /* we may need to do some cleanup here... */
6785 ICALL_EXPORT MonoStringHandle
6786 ves_icall_System_Environment_GetGacPath (MonoError *error)
6788 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6791 ICALL_EXPORT MonoString*
6792 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6794 #if defined (HOST_WIN32)
6795 #ifndef CSIDL_FLAG_CREATE
6796 #define CSIDL_FLAG_CREATE 0x8000
6799 WCHAR path [MAX_PATH];
6800 /* Create directory if no existing */
6801 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6806 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6807 mono_error_set_pending_exception (&error);
6811 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6813 return mono_string_new (mono_domain_get (), "");
6816 ICALL_EXPORT MonoArray *
6817 ves_icall_System_Environment_GetLogicalDrives (void)
6820 gunichar2 buf [256], *ptr, *dname;
6822 guint initial_size = 127, size = 128;
6825 MonoString *drivestr;
6826 MonoDomain *domain = mono_domain_get ();
6832 while (size > initial_size) {
6833 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6834 if (size > initial_size) {
6837 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6838 initial_size = size;
6852 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6853 if (mono_error_set_pending_exception (&error))
6860 while (*u16) { u16++; len ++; }
6861 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6862 if (mono_error_set_pending_exception (&error))
6865 mono_array_setref (result, ndrives++, drivestr);
6876 ICALL_EXPORT MonoString *
6877 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6880 gunichar2 volume_name [MAX_PATH + 1];
6882 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6884 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6885 mono_error_set_pending_exception (&error);
6889 ICALL_EXPORT MonoStringHandle
6890 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6892 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6895 static const char *encodings [] = {
6897 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6898 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6899 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6901 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6902 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6903 "x_unicode_2_0_utf_7",
6905 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6906 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6908 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6911 "unicodefffe", "utf_16be",
6918 * Returns the internal codepage, if the value of "int_code_page" is
6919 * 1 at entry, and we can not compute a suitable code page number,
6920 * returns the code page as a string
6922 ICALL_EXPORT MonoString*
6923 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6928 char *codepage = NULL;
6930 int want_name = *int_code_page;
6933 *int_code_page = -1;
6935 g_get_charset (&cset);
6936 c = codepage = strdup (cset);
6937 for (c = codepage; *c; c++){
6938 if (isascii (*c) && isalpha (*c))
6943 /* g_print ("charset: %s\n", cset); */
6945 /* handle some common aliases */
6948 for (i = 0; p != 0; ){
6951 p = encodings [++i];
6954 if (strcmp (p, codepage) == 0){
6955 *int_code_page = code;
6958 p = encodings [++i];
6961 if (strstr (codepage, "utf_8") != NULL)
6962 *int_code_page |= 0x10000000;
6965 if (want_name && *int_code_page == -1)
6966 return mono_string_new (mono_domain_get (), cset);
6971 ICALL_EXPORT MonoBoolean
6972 ves_icall_System_Environment_get_HasShutdownStarted (void)
6974 if (mono_runtime_is_shutting_down ())
6977 if (mono_domain_is_unloading (mono_domain_get ()))
6984 ves_icall_System_Environment_BroadcastSettingChange (void)
6987 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6993 ves_icall_System_Environment_get_TickCount (void)
6995 /* this will overflow after ~24 days */
6996 return (gint32) (mono_msec_boottime () & 0xffffffff);
7000 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7005 #ifndef DISABLE_REMOTING
7006 ICALL_EXPORT MonoBoolean
7007 ves_icall_IsTransparentProxy (MonoObject *proxy)
7012 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7018 ICALL_EXPORT MonoReflectionMethod *
7019 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7020 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7022 MonoReflectionMethod *ret = NULL;
7027 MonoMethod **vtable;
7028 MonoMethod *res = NULL;
7030 MONO_CHECK_ARG_NULL (rtype, NULL);
7031 MONO_CHECK_ARG_NULL (rmethod, NULL);
7033 method = rmethod->method;
7034 klass = mono_class_from_mono_type (rtype->type);
7035 mono_class_init_checked (klass, &error);
7036 if (mono_error_set_pending_exception (&error))
7039 if (MONO_CLASS_IS_INTERFACE (klass))
7042 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7045 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7046 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7052 mono_class_setup_vtable (klass);
7053 vtable = klass->vtable;
7055 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7056 gboolean variance_used = FALSE;
7057 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7058 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7060 res = vtable [offs + method->slot];
7062 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7065 if (method->slot != -1)
7066 res = vtable [method->slot];
7072 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7073 mono_error_set_pending_exception (&error);
7078 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7084 klass = mono_class_from_mono_type (type->type);
7085 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7086 if (!is_ok (&error)) {
7087 mono_error_set_pending_exception (&error);
7091 mono_vtable_set_is_remote (vtable, enable);
7094 #else /* DISABLE_REMOTING */
7097 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7099 g_assert_not_reached ();
7104 ICALL_EXPORT MonoObject *
7105 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7112 domain = mono_object_domain (type);
7113 klass = mono_class_from_mono_type (type->type);
7114 mono_class_init_checked (klass, &error);
7115 if (mono_error_set_pending_exception (&error))
7118 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7119 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7123 if (klass->rank >= 1) {
7124 g_assert (klass->rank == 1);
7125 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7126 mono_error_set_pending_exception (&error);
7129 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7130 if (!is_ok (&error)) {
7131 mono_error_set_pending_exception (&error);
7134 /* Bypass remoting object creation check */
7135 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7136 mono_error_set_pending_exception (&error);
7142 ICALL_EXPORT MonoStringHandle
7143 ves_icall_System_IO_get_temp_path (MonoError *error)
7145 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7148 #ifndef PLATFORM_NO_DRIVEINFO
7149 ICALL_EXPORT MonoBoolean
7150 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7151 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7155 ULARGE_INTEGER wapi_free_bytes_avail;
7156 ULARGE_INTEGER wapi_total_number_of_bytes;
7157 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7159 *error = ERROR_SUCCESS;
7160 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7161 &wapi_total_number_of_free_bytes);
7164 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7165 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7166 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7168 *free_bytes_avail = 0;
7169 *total_number_of_bytes = 0;
7170 *total_number_of_free_bytes = 0;
7171 *error = GetLastError ();
7177 ICALL_EXPORT guint32
7178 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7180 return GetDriveType (mono_string_chars (root_path_name));
7184 ICALL_EXPORT gpointer
7185 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7188 gpointer result = mono_compile_method_checked (method, &error);
7189 mono_error_set_pending_exception (&error);
7193 ICALL_EXPORT MonoString *
7194 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7199 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7201 #if defined (HOST_WIN32)
7202 /* Avoid mixing '/' and '\\' */
7205 for (i = strlen (path) - 1; i >= 0; i--)
7206 if (path [i] == '/')
7210 mcpath = mono_string_new (mono_domain_get (), path);
7216 /* this is an icall */
7218 get_bundled_app_config (void)
7221 const gchar *app_config;
7224 gchar *config_file_name, *config_file_path;
7225 gsize len, config_file_path_length, config_ext_length;
7228 domain = mono_domain_get ();
7229 file = domain->setup->configuration_file;
7230 if (!file || file->length == 0)
7233 // Retrieve config file and remove the extension
7234 config_file_name = mono_string_to_utf8_checked (file, &error);
7235 if (mono_error_set_pending_exception (&error))
7237 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7238 if (!config_file_path)
7239 config_file_path = config_file_name;
7241 config_file_path_length = strlen (config_file_path);
7242 config_ext_length = strlen (".config");
7243 if (config_file_path_length <= config_ext_length)
7246 len = config_file_path_length - config_ext_length;
7247 module = (gchar *)g_malloc0 (len + 1);
7248 memcpy (module, config_file_path, len);
7249 // Get the config file from the module name
7250 app_config = mono_config_string_for_assembly_file (module);
7253 if (config_file_name != config_file_path)
7254 g_free (config_file_name);
7255 g_free (config_file_path);
7260 return mono_string_new (mono_domain_get (), app_config);
7263 /* this is an icall */
7264 static MonoStringHandle
7265 get_bundled_machine_config (MonoError *error)
7267 const gchar *machine_config;
7269 machine_config = mono_get_machine_config ();
7271 if (!machine_config)
7272 return NULL_HANDLE_STRING;
7274 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7277 ICALL_EXPORT MonoString *
7278 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7283 path = g_path_get_dirname (mono_get_config_dir ());
7285 #if defined (HOST_WIN32)
7286 /* Avoid mixing '/' and '\\' */
7289 for (i = strlen (path) - 1; i >= 0; i--)
7290 if (path [i] == '/')
7294 ipath = mono_string_new (mono_domain_get (), path);
7300 ICALL_EXPORT gboolean
7301 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7303 MonoPEResourceDataEntry *entry;
7306 if (!assembly || !result || !size)
7311 image = assembly->assembly->image;
7312 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7316 *result = mono_image_rva_map (image, entry->rde_data_offset);
7321 *size = entry->rde_size;
7326 ICALL_EXPORT MonoBoolean
7327 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7329 return mono_is_debugger_attached ();
7332 ICALL_EXPORT MonoBoolean
7333 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7335 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7336 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7342 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7344 if (mono_get_runtime_callbacks ()->debug_log)
7345 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7349 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7351 #if defined (HOST_WIN32)
7352 OutputDebugString (mono_string_chars (message));
7354 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7358 /* Only used for value types */
7359 ICALL_EXPORT MonoObject *
7360 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7367 domain = mono_object_domain (type);
7368 klass = mono_class_from_mono_type (type->type);
7369 mono_class_init_checked (klass, &error);
7370 if (mono_error_set_pending_exception (&error))
7373 if (mono_class_is_nullable (klass))
7374 /* No arguments -> null */
7377 result = mono_object_new_checked (domain, klass, &error);
7378 mono_error_set_pending_exception (&error);
7382 ICALL_EXPORT MonoReflectionMethod *
7383 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7385 MonoReflectionMethod *ret = NULL;
7388 MonoClass *klass, *parent;
7389 MonoGenericContext *generic_inst = NULL;
7390 MonoMethod *method = m->method;
7391 MonoMethod *result = NULL;
7394 if (method->klass == NULL)
7397 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7398 MONO_CLASS_IS_INTERFACE (method->klass) ||
7399 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7402 slot = mono_method_get_vtable_slot (method);
7406 klass = method->klass;
7407 if (klass->generic_class) {
7408 generic_inst = mono_class_get_context (klass);
7409 klass = klass->generic_class->container_class;
7414 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7415 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7416 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7417 or klass is the generic container class and generic_inst is the instantiation.
7419 when we go to the parent, if the parent is an open constructed type, we need to
7420 replace the type parameters by the definitions from the generic_inst, and then take it
7421 apart again into the klass and the generic_inst.
7423 For cases like this:
7424 class C<T> : B<T, int> {
7425 public override void Foo () { ... }
7427 class B<U,V> : A<HashMap<U,V>> {
7428 public override void Foo () { ... }
7431 public virtual void Foo () { ... }
7434 if at each iteration the parent isn't open, we can skip inflating it. if at some
7435 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7438 MonoGenericContext *parent_inst = NULL;
7439 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7440 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7441 if (!mono_error_ok (&error)) {
7442 mono_error_set_pending_exception (&error);
7446 if (parent->generic_class) {
7447 parent_inst = mono_class_get_context (parent);
7448 parent = parent->generic_class->container_class;
7451 mono_class_setup_vtable (parent);
7452 if (parent->vtable_size <= slot)
7455 generic_inst = parent_inst;
7458 klass = klass->parent;
7461 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7462 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7463 if (!mono_error_ok (&error)) {
7464 mono_error_set_pending_exception (&error);
7468 generic_inst = NULL;
7470 if (klass->generic_class) {
7471 generic_inst = mono_class_get_context (klass);
7472 klass = klass->generic_class->container_class;
7478 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7479 if (!mono_error_ok (&error)) {
7480 mono_error_set_pending_exception (&error);
7485 if (klass == method->klass)
7488 /*This is possible if definition == FALSE.
7489 * Do it here to be really sure we don't read invalid memory.
7491 if (slot >= klass->vtable_size)
7494 mono_class_setup_vtable (klass);
7496 result = klass->vtable [slot];
7497 if (result == NULL) {
7498 /* It is an abstract method */
7499 gboolean found = FALSE;
7500 gpointer iter = NULL;
7501 while ((result = mono_class_get_methods (klass, &iter))) {
7502 if (result->slot == slot) {
7507 /* found might be FALSE if we looked in an abstract class
7508 * that doesn't override an abstract method of its
7510 * abstract class Base {
7511 * public abstract void Foo ();
7513 * abstract class Derived : Base { }
7514 * class Child : Derived {
7515 * public override void Foo () { }
7518 * if m was Child.Foo and we ask for the base method,
7519 * then we get here with klass == Derived and found == FALSE
7521 /* but it shouldn't be the case that if we're looking
7522 * for the definition and didn't find a result; the
7523 * loop above should've taken us as far as we could
7525 g_assert (!(definition && !found));
7530 g_assert (result != NULL);
7532 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7533 mono_error_set_pending_exception (&error);
7537 ICALL_EXPORT MonoString*
7538 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7540 MonoMethod *method = m->method;
7542 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7547 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7549 iter->sig = *(MonoMethodSignature**)argsp;
7551 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7552 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7555 /* FIXME: it's not documented what start is exactly... */
7559 iter->args = argsp + sizeof (gpointer);
7561 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7563 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7566 ICALL_EXPORT MonoTypedRef
7567 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7569 guint32 i, arg_size;
7573 i = iter->sig->sentinelpos + iter->next_arg;
7575 g_assert (i < iter->sig->param_count);
7577 res.type = iter->sig->params [i];
7578 res.klass = mono_class_from_mono_type (res.type);
7579 arg_size = mono_type_stack_size (res.type, &align);
7580 #if defined(__arm__) || defined(__mips__)
7581 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7583 res.value = iter->args;
7584 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7585 /* Values are stored as 8 byte register sized objects, but 'value'
7586 * is dereferenced as a pointer in other routines.
7588 res.value = (char*)res.value + 4;
7590 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7591 if (arg_size <= sizeof (gpointer)) {
7593 int padding = arg_size - mono_type_size (res.type, &dummy);
7594 res.value = (guint8*)res.value + padding;
7597 iter->args = (char*)iter->args + arg_size;
7600 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7605 ICALL_EXPORT MonoTypedRef
7606 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7608 guint32 i, arg_size;
7612 i = iter->sig->sentinelpos + iter->next_arg;
7614 g_assert (i < iter->sig->param_count);
7616 while (i < iter->sig->param_count) {
7617 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7619 res.type = iter->sig->params [i];
7620 res.klass = mono_class_from_mono_type (res.type);
7621 /* FIXME: endianess issue... */
7622 arg_size = mono_type_stack_size (res.type, &align);
7623 #if defined(__arm__) || defined(__mips__)
7624 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7626 res.value = iter->args;
7627 iter->args = (char*)iter->args + arg_size;
7629 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7632 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7640 ICALL_EXPORT MonoType*
7641 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7645 i = iter->sig->sentinelpos + iter->next_arg;
7647 g_assert (i < iter->sig->param_count);
7649 return iter->sig->params [i];
7652 ICALL_EXPORT MonoObject*
7653 mono_TypedReference_ToObject (MonoTypedRef* tref)
7656 MonoObject *result = NULL;
7657 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7658 MonoObject** objp = (MonoObject **)tref->value;
7662 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7663 mono_error_set_pending_exception (&error);
7667 ICALL_EXPORT MonoTypedRef
7668 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7671 MonoReflectionField *f;
7673 MonoType *ftype = NULL;
7677 memset (&res, 0, sizeof (res));
7680 g_assert (mono_array_length (fields) > 0);
7682 klass = target->vtable->klass;
7684 for (i = 0; i < mono_array_length (fields); ++i) {
7685 f = mono_array_get (fields, MonoReflectionField*, i);
7687 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7690 if (f->field->parent != klass) {
7691 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7695 p = (guint8*)target + f->field->offset;
7697 p += f->field->offset - sizeof (MonoObject);
7698 klass = mono_class_from_mono_type (f->field->type);
7699 ftype = f->field->type;
7703 res.klass = mono_class_from_mono_type (ftype);
7710 prelink_method (MonoMethod *method, MonoError *error)
7712 const char *exc_class, *exc_arg;
7714 mono_error_init (error);
7715 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7717 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7719 mono_error_set_exception_instance (error,
7720 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7723 /* create the wrapper, too? */
7727 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7731 prelink_method (method->method, &error);
7732 mono_error_set_pending_exception (&error);
7736 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7739 MonoClass *klass = mono_class_from_mono_type (type->type);
7741 gpointer iter = NULL;
7743 mono_class_init_checked (klass, &error);
7744 if (mono_error_set_pending_exception (&error))
7747 while ((m = mono_class_get_methods (klass, &iter))) {
7748 prelink_method (m, &error);
7749 if (mono_error_set_pending_exception (&error))
7754 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7756 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7757 gint32 const **exponents,
7758 gunichar2 const **digitLowerTable,
7759 gunichar2 const **digitUpperTable,
7760 gint64 const **tenPowersList,
7761 gint32 const **decHexDigits)
7763 *mantissas = Formatter_MantissaBitsTable;
7764 *exponents = Formatter_TensExponentTable;
7765 *digitLowerTable = Formatter_DigitLowerTable;
7766 *digitUpperTable = Formatter_DigitUpperTable;
7767 *tenPowersList = Formatter_TenPowersList;
7768 *decHexDigits = Formatter_DecHexDigits;
7772 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7773 * and avoid useless allocations.
7776 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7778 MonoReflectionType *rt;
7782 mono_error_init (error);
7783 for (i = 0; i < type->num_mods; ++i) {
7784 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7789 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7790 return_val_if_nok (error, NULL);
7792 for (i = 0; i < type->num_mods; ++i) {
7793 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7794 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7795 return_val_if_nok (error, NULL);
7797 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7798 return_val_if_nok (error, NULL);
7800 mono_array_setref (res, count, rt);
7807 ICALL_EXPORT MonoArray*
7808 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7811 MonoType *type = param->ClassImpl->type;
7812 MonoClass *member_class = mono_object_class (param->MemberImpl);
7813 MonoMethod *method = NULL;
7816 MonoMethodSignature *sig;
7819 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7820 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7821 method = rmethod->method;
7822 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7823 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7824 if (!(method = prop->property->get))
7825 method = prop->property->set;
7828 char *type_name = mono_type_get_full_name (member_class);
7829 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7830 MonoException *ex = mono_get_exception_not_supported (msg);
7833 mono_set_pending_exception (ex);
7837 image = method->klass->image;
7838 pos = param->PositionImpl;
7839 sig = mono_method_signature (method);
7843 type = sig->params [pos];
7845 res = type_array_from_modifiers (image, type, optional, &error);
7846 mono_error_set_pending_exception (&error);
7851 get_property_type (MonoProperty *prop)
7853 MonoMethodSignature *sig;
7855 sig = mono_method_signature (prop->get);
7857 } else if (prop->set) {
7858 sig = mono_method_signature (prop->set);
7859 return sig->params [sig->param_count - 1];
7864 ICALL_EXPORT MonoArray*
7865 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7868 MonoType *type = get_property_type (property->property);
7869 MonoImage *image = property->klass->image;
7874 res = type_array_from_modifiers (image, type, optional, &error);
7875 mono_error_set_pending_exception (&error);
7880 *Construct a MonoType suited to be used to decode a constant blob object.
7882 * @type is the target type which will be constructed
7883 * @blob_type is the blob type, for example, that comes from the constant table
7884 * @real_type is the expected constructed type.
7887 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7889 type->type = blob_type;
7890 type->data.klass = NULL;
7891 if (blob_type == MONO_TYPE_CLASS)
7892 type->data.klass = mono_defaults.object_class;
7893 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7894 /* For enums, we need to use the base type */
7895 type->type = MONO_TYPE_VALUETYPE;
7896 type->data.klass = mono_class_from_mono_type (real_type);
7898 type->data.klass = mono_class_from_mono_type (real_type);
7901 ICALL_EXPORT MonoObject*
7902 property_info_get_default_value (MonoReflectionProperty *property)
7906 MonoProperty *prop = property->property;
7907 MonoType *type = get_property_type (prop);
7908 MonoDomain *domain = mono_object_domain (property);
7909 MonoTypeEnum def_type;
7910 const char *def_value;
7913 mono_class_init (prop->parent);
7915 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7916 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7920 def_value = mono_class_get_property_default_value (prop, &def_type);
7922 mono_type_from_blob_type (&blob_type, def_type, type);
7923 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7925 mono_error_set_pending_exception (&error);
7929 ICALL_EXPORT MonoBoolean
7930 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7933 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7934 MonoCustomAttrInfo *cinfo;
7937 mono_class_init_checked (attr_class, &error);
7938 if (mono_error_set_pending_exception (&error))
7941 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7942 if (!is_ok (&error)) {
7943 mono_error_set_pending_exception (&error);
7948 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7950 mono_custom_attrs_free (cinfo);
7954 ICALL_EXPORT MonoArray*
7955 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7957 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7962 mono_class_init_checked (attr_class, &error);
7963 if (mono_error_set_pending_exception (&error))
7967 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7968 if (!mono_error_ok (&error)) {
7969 mono_error_set_pending_exception (&error);
7976 ICALL_EXPORT MonoArray*
7977 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7981 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7982 mono_error_set_pending_exception (&error);
7987 ICALL_EXPORT MonoString*
7988 ves_icall_Mono_Runtime_GetDisplayName (void)
7991 MonoString *display_name;
7993 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7994 display_name = mono_string_new (mono_domain_get (), info);
7996 return display_name;
7999 ICALL_EXPORT MonoString*
8000 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8003 MonoString *message;
8007 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8008 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8011 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8013 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8014 if (mono_error_set_pending_exception (&error))
8021 ICALL_EXPORT gpointer
8022 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8024 return GetCurrentProcess ();
8027 ICALL_EXPORT MonoBoolean
8028 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8030 return GetExitCodeProcess (handle, (guint32*) exitcode);
8033 ICALL_EXPORT MonoBoolean
8034 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8036 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8037 return CloseHandle (handle);
8039 return CloseProcess (handle);
8043 ICALL_EXPORT MonoBoolean
8044 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8046 return TerminateProcess (handle, exitcode);
8050 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8053 return WaitForInputIdle (handle, milliseconds);
8055 /*TODO: Not implemented*/
8056 return WAIT_TIMEOUT;
8060 ICALL_EXPORT MonoBoolean
8061 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8063 return GetProcessWorkingSetSize (handle, min, max);
8066 ICALL_EXPORT MonoBoolean
8067 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8069 return SetProcessWorkingSetSize (handle, min, max);
8072 ICALL_EXPORT MonoBoolean
8073 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8075 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8079 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8081 return mono_process_current_pid ();
8085 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8087 return GetPriorityClass (handle);
8090 ICALL_EXPORT MonoBoolean
8091 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8093 return SetPriorityClass (handle, priorityClass);
8096 ICALL_EXPORT MonoBoolean
8097 ves_icall_Mono_Btls_Provider_IsSupported (void)
8106 #ifndef DISABLE_ICALL_TABLES
8108 #define ICALL_TYPE(id,name,first)
8109 #define ICALL(id,name,func) Icall_ ## id,
8110 #define HANDLES(inner) inner
8113 #include "metadata/icall-def.h"
8119 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8120 #define ICALL(id,name,func)
8122 #define HANDLES(inner) inner
8124 #include "metadata/icall-def.h"
8130 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8131 #define ICALL(id,name,func)
8133 #define HANDLES(inner) inner
8135 guint16 first_icall;
8138 static const IcallTypeDesc
8139 icall_type_descs [] = {
8140 #include "metadata/icall-def.h"
8144 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8147 #define HANDLES(inner) inner
8149 #define ICALL_TYPE(id,name,first)
8152 #ifdef HAVE_ARRAY_ELEM_INIT
8153 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8154 #define MSGSTRFIELD1(line) str##line
8156 static const struct msgstrtn_t {
8157 #define ICALL(id,name,func)
8159 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8160 #include "metadata/icall-def.h"
8162 } icall_type_names_str = {
8163 #define ICALL_TYPE(id,name,first) (name),
8164 #include "metadata/icall-def.h"
8167 static const guint16 icall_type_names_idx [] = {
8168 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8169 #include "metadata/icall-def.h"
8172 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8174 static const struct msgstr_t {
8176 #define ICALL_TYPE(id,name,first)
8177 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8178 #include "metadata/icall-def.h"
8180 } icall_names_str = {
8181 #define ICALL(id,name,func) (name),
8182 #include "metadata/icall-def.h"
8185 static const guint16 icall_names_idx [] = {
8186 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8187 #include "metadata/icall-def.h"
8190 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8196 #define ICALL_TYPE(id,name,first) name,
8197 #define ICALL(id,name,func)
8198 static const char* const
8199 icall_type_names [] = {
8200 #include "metadata/icall-def.h"
8204 #define icall_type_name_get(id) (icall_type_names [(id)])
8208 #define ICALL_TYPE(id,name,first)
8209 #define ICALL(id,name,func) name,
8210 static const char* const
8212 #include "metadata/icall-def.h"
8215 #define icall_name_get(id) icall_names [(id)]
8217 #endif /* !HAVE_ARRAY_ELEM_INIT */
8220 #define HANDLES(inner) inner
8223 #define ICALL_TYPE(id,name,first)
8224 #define ICALL(id,name,func) func,
8225 static const gconstpointer
8226 icall_functions [] = {
8227 #include "metadata/icall-def.h"
8231 #ifdef ENABLE_ICALL_SYMBOL_MAP
8233 #define HANDLES(inner) inner
8236 #define ICALL_TYPE(id,name,first)
8237 #define ICALL(id,name,func) #func,
8238 static const gconstpointer
8239 icall_symbols [] = {
8240 #include "metadata/icall-def.h"
8247 #define ICALL_TYPE(id,name,first)
8248 #define ICALL(id,name,func) 0,
8250 #define HANDLES(inner) 1,
8252 icall_uses_handles [] = {
8253 #include "metadata/icall-def.h"
8258 #endif /* DISABLE_ICALL_TABLES */
8260 static mono_mutex_t icall_mutex;
8261 static GHashTable *icall_hash = NULL;
8262 static GHashTable *jit_icall_hash_name = NULL;
8263 static GHashTable *jit_icall_hash_addr = NULL;
8266 mono_icall_init (void)
8268 #ifndef DISABLE_ICALL_TABLES
8271 /* check that tables are sorted: disable in release */
8274 const char *prev_class = NULL;
8275 const char *prev_method;
8277 for (i = 0; i < Icall_type_num; ++i) {
8278 const IcallTypeDesc *desc;
8281 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8282 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8283 prev_class = icall_type_name_get (i);
8284 desc = &icall_type_descs [i];
8285 num_icalls = icall_desc_num_icalls (desc);
8286 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8287 for (j = 0; j < num_icalls; ++j) {
8288 const char *methodn = icall_name_get (desc->first_icall + j);
8289 if (prev_method && strcmp (prev_method, methodn) >= 0)
8290 g_print ("method %s should come before method %s\n", methodn, prev_method);
8291 prev_method = methodn;
8297 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8298 mono_os_mutex_init (&icall_mutex);
8302 mono_icall_lock (void)
8304 mono_locks_os_acquire (&icall_mutex, IcallLock);
8308 mono_icall_unlock (void)
8310 mono_locks_os_release (&icall_mutex, IcallLock);
8314 mono_icall_cleanup (void)
8316 g_hash_table_destroy (icall_hash);
8317 g_hash_table_destroy (jit_icall_hash_name);
8318 g_hash_table_destroy (jit_icall_hash_addr);
8319 mono_os_mutex_destroy (&icall_mutex);
8323 * mono_add_internal_call:
8324 * @name: method specification to surface to the managed world
8325 * @method: pointer to a C method to invoke when the method is called
8327 * This method surfaces the C function pointed by @method as a method
8328 * that has been surfaced in managed code with the method specified in
8329 * @name as an internal call.
8331 * Internal calls are surfaced to all app domains loaded and they are
8332 * accessibly by a type with the specified name.
8334 * You must provide a fully qualified type name, that is namespaces
8335 * and type name, followed by a colon and the method name, with an
8336 * optional signature to bind.
8338 * For example, the following are all valid declarations:
8340 * "MyApp.Services.ScriptService:Accelerate"
8341 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8343 * You use method parameters in cases where there might be more than
8344 * one surface method to managed code. That way you can register different
8345 * internal calls for different method overloads.
8347 * The internal calls are invoked with no marshalling. This means that .NET
8348 * types like System.String are exposed as `MonoString *` parameters. This is
8349 * different than the way that strings are surfaced in P/Invoke.
8351 * For more information on how the parameters are marshalled, see the
8352 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8355 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8356 * reference for more information on the format of method descriptions.
8359 mono_add_internal_call (const char *name, gconstpointer method)
8363 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8365 mono_icall_unlock ();
8368 #ifndef DISABLE_ICALL_TABLES
8370 #ifdef HAVE_ARRAY_ELEM_INIT
8372 compare_method_imap (const void *key, const void *elem)
8374 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8375 return strcmp (key, method_name);
8379 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8381 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);
8384 return (nameslot - &icall_names_idx [0]);
8388 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8390 gsize slotnum = find_slot_icall (imap, name);
8393 return (gboolean)icall_uses_handles [slotnum];
8397 find_method_icall (const IcallTypeDesc *imap, const char *name)
8399 gsize slotnum = find_slot_icall (imap, name);
8402 return (gpointer)icall_functions [slotnum];
8406 compare_class_imap (const void *key, const void *elem)
8408 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8409 return strcmp (key, class_name);
8412 static const IcallTypeDesc*
8413 find_class_icalls (const char *name)
8415 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);
8418 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8421 #else /* HAVE_ARRAY_ELEM_INIT */
8424 compare_method_imap (const void *key, const void *elem)
8426 const char** method_name = (const char**)elem;
8427 return strcmp (key, *method_name);
8431 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8433 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8436 return nameslot - icall_names;
8440 find_method_icall (const IcallTypeDesc *imap, const char *name)
8442 gsize slotnum = find_slot_icall (imap, name);
8445 return (gpointer)icall_functions [slotnum];
8449 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8451 gsize slotnum = find_slot_icall (imap, name);
8454 return (gboolean)icall_uses_handles [slotnum];
8458 compare_class_imap (const void *key, const void *elem)
8460 const char** class_name = (const char**)elem;
8461 return strcmp (key, *class_name);
8464 static const IcallTypeDesc*
8465 find_class_icalls (const char *name)
8467 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8470 return &icall_type_descs [nameslot - icall_type_names];
8473 #endif /* HAVE_ARRAY_ELEM_INIT */
8475 #endif /* DISABLE_ICALL_TABLES */
8478 * we should probably export this as an helper (handle nested types).
8479 * Returns the number of chars written in buf.
8482 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8484 int nspacelen, cnamelen;
8485 nspacelen = strlen (klass->name_space);
8486 cnamelen = strlen (klass->name);
8487 if (nspacelen + cnamelen + 2 > bufsize)
8490 memcpy (buf, klass->name_space, nspacelen);
8491 buf [nspacelen ++] = '.';
8493 memcpy (buf + nspacelen, klass->name, cnamelen);
8494 buf [nspacelen + cnamelen] = 0;
8495 return nspacelen + cnamelen;
8498 #ifdef DISABLE_ICALL_TABLES
8500 no_icall_table (void)
8502 g_assert_not_reached ();
8507 * mono_lookup_internal_call_full:
8508 * @method: the method to look up
8509 * @uses_handles: out argument if method needs handles around managed objects.
8511 * Returns a pointer to the icall code for the given method. If
8512 * uses_handles is not NULL, it will be set to TRUE if the method
8513 * needs managed objects wrapped using the infrastructure in handle.h
8515 * If the method is not found, warns and returns NULL.
8518 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8523 int typelen = 0, mlen, siglen;
8525 #ifndef DISABLE_ICALL_TABLES
8526 const IcallTypeDesc *imap = NULL;
8529 g_assert (method != NULL);
8531 if (method->is_inflated)
8532 method = ((MonoMethodInflated *) method)->declaring;
8534 if (method->klass->nested_in) {
8535 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8539 mname [pos++] = '/';
8542 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8548 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8553 #ifndef DISABLE_ICALL_TABLES
8554 imap = find_class_icalls (mname);
8557 mname [typelen] = ':';
8558 mname [typelen + 1] = ':';
8560 mlen = strlen (method->name);
8561 memcpy (mname + typelen + 2, method->name, mlen);
8562 sigstart = mname + typelen + 2 + mlen;
8565 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8566 siglen = strlen (tmpsig);
8567 if (typelen + mlen + siglen + 6 > sizeof (mname))
8570 memcpy (sigstart + 1, tmpsig, siglen);
8571 sigstart [siglen + 1] = ')';
8572 sigstart [siglen + 2] = 0;
8577 res = g_hash_table_lookup (icall_hash, mname);
8580 *uses_handles = FALSE;
8581 mono_icall_unlock ();;
8584 /* try without signature */
8586 res = g_hash_table_lookup (icall_hash, mname);
8589 *uses_handles = FALSE;
8590 mono_icall_unlock ();
8594 #ifdef DISABLE_ICALL_TABLES
8595 mono_icall_unlock ();
8596 /* Fail only when the result is actually used */
8597 /* mono_marshal_get_native_wrapper () depends on this */
8598 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8599 return ves_icall_System_String_ctor_RedirectToCreateString;
8601 return no_icall_table;
8603 /* it wasn't found in the static call tables */
8606 *uses_handles = FALSE;
8607 mono_icall_unlock ();
8610 res = find_method_icall (imap, sigstart - mlen);
8613 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8614 mono_icall_unlock ();
8617 /* try _with_ signature */
8619 res = find_method_icall (imap, sigstart - mlen);
8622 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8623 mono_icall_unlock ();
8627 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8628 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8629 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8630 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8631 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");
8632 g_print ("If you see other errors or faults after this message they are probably related\n");
8633 g_print ("and you need to fix your mono install first.\n");
8635 mono_icall_unlock ();
8642 mono_lookup_internal_call (MonoMethod *method)
8644 return mono_lookup_internal_call_full (method, NULL);
8647 #ifdef ENABLE_ICALL_SYMBOL_MAP
8649 func_cmp (gconstpointer key, gconstpointer p)
8651 return (gsize)key - (gsize)*(gsize*)p;
8656 * mono_lookup_icall_symbol:
8658 * Given the icall METHOD, returns its C symbol.
8661 mono_lookup_icall_symbol (MonoMethod *m)
8663 #ifdef DISABLE_ICALL_TABLES
8664 g_assert_not_reached ();
8667 #ifdef ENABLE_ICALL_SYMBOL_MAP
8671 static gconstpointer *functions_sorted;
8672 static const char**symbols_sorted;
8673 static gboolean inited;
8678 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8679 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8680 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8681 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8682 /* Bubble sort the two arrays */
8686 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8687 if (functions_sorted [i] > functions_sorted [i + 1]) {
8690 tmp = functions_sorted [i];
8691 functions_sorted [i] = functions_sorted [i + 1];
8692 functions_sorted [i + 1] = tmp;
8693 tmp = symbols_sorted [i];
8694 symbols_sorted [i] = symbols_sorted [i + 1];
8695 symbols_sorted [i + 1] = tmp;
8702 func = mono_lookup_internal_call (m);
8705 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8709 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8711 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8712 g_assert_not_reached ();
8719 type_from_typename (char *type_name)
8721 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8723 if (!strcmp (type_name, "int"))
8724 klass = mono_defaults.int_class;
8725 else if (!strcmp (type_name, "ptr"))
8726 klass = mono_defaults.int_class;
8727 else if (!strcmp (type_name, "void"))
8728 klass = mono_defaults.void_class;
8729 else if (!strcmp (type_name, "int32"))
8730 klass = mono_defaults.int32_class;
8731 else if (!strcmp (type_name, "uint32"))
8732 klass = mono_defaults.uint32_class;
8733 else if (!strcmp (type_name, "int8"))
8734 klass = mono_defaults.sbyte_class;
8735 else if (!strcmp (type_name, "uint8"))
8736 klass = mono_defaults.byte_class;
8737 else if (!strcmp (type_name, "int16"))
8738 klass = mono_defaults.int16_class;
8739 else if (!strcmp (type_name, "uint16"))
8740 klass = mono_defaults.uint16_class;
8741 else if (!strcmp (type_name, "long"))
8742 klass = mono_defaults.int64_class;
8743 else if (!strcmp (type_name, "ulong"))
8744 klass = mono_defaults.uint64_class;
8745 else if (!strcmp (type_name, "float"))
8746 klass = mono_defaults.single_class;
8747 else if (!strcmp (type_name, "double"))
8748 klass = mono_defaults.double_class;
8749 else if (!strcmp (type_name, "object"))
8750 klass = mono_defaults.object_class;
8751 else if (!strcmp (type_name, "obj"))
8752 klass = mono_defaults.object_class;
8753 else if (!strcmp (type_name, "string"))
8754 klass = mono_defaults.string_class;
8755 else if (!strcmp (type_name, "bool"))
8756 klass = mono_defaults.boolean_class;
8757 else if (!strcmp (type_name, "boolean"))
8758 klass = mono_defaults.boolean_class;
8760 g_error ("%s", type_name);
8761 g_assert_not_reached ();
8763 return &klass->byval_arg;
8767 * LOCKING: Take the corlib image lock.
8769 MonoMethodSignature*
8770 mono_create_icall_signature (const char *sigstr)
8775 MonoMethodSignature *res, *res2;
8776 MonoImage *corlib = mono_defaults.corlib;
8778 mono_image_lock (corlib);
8779 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8780 mono_image_unlock (corlib);
8785 parts = g_strsplit (sigstr, " ", 256);
8794 res = mono_metadata_signature_alloc (corlib, len - 1);
8799 * Under windows, the default pinvoke calling convention is STDCALL but
8802 res->call_convention = MONO_CALL_C;
8805 res->ret = type_from_typename (parts [0]);
8806 for (i = 1; i < len; ++i) {
8807 res->params [i - 1] = type_from_typename (parts [i]);
8812 mono_image_lock (corlib);
8813 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8815 res = res2; /*Value is allocated in the image pool*/
8817 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8818 mono_image_unlock (corlib);
8824 mono_find_jit_icall_by_name (const char *name)
8826 MonoJitICallInfo *info;
8827 g_assert (jit_icall_hash_name);
8830 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8831 mono_icall_unlock ();
8836 mono_find_jit_icall_by_addr (gconstpointer addr)
8838 MonoJitICallInfo *info;
8839 g_assert (jit_icall_hash_addr);
8842 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8843 mono_icall_unlock ();
8849 * mono_get_jit_icall_info:
8851 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8852 * caller should access it while holding the icall lock.
8855 mono_get_jit_icall_info (void)
8857 return jit_icall_hash_name;
8861 * mono_lookup_jit_icall_symbol:
8863 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8866 mono_lookup_jit_icall_symbol (const char *name)
8868 MonoJitICallInfo *info;
8869 const char *res = NULL;
8872 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8874 res = info->c_symbol;
8875 mono_icall_unlock ();
8880 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8883 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8884 mono_icall_unlock ();
8888 * 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
8889 * icalls without wrappers in some cases.
8892 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8894 MonoJitICallInfo *info;
8901 if (!jit_icall_hash_name) {
8902 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8903 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8906 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8907 g_warning ("jit icall already defined \"%s\"\n", name);
8908 g_assert_not_reached ();
8911 info = g_new0 (MonoJitICallInfo, 1);
8916 info->c_symbol = c_symbol;
8917 info->no_raise = no_raise;
8920 info->wrapper = func;
8922 info->wrapper = NULL;
8925 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8926 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8928 mono_icall_unlock ();
8933 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8935 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);