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>
115 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
117 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
119 /* Lazy class loading functions */
120 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
121 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
122 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
123 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
124 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
125 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
128 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
130 static inline MonoBoolean
131 is_generic_parameter (MonoType *type)
133 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
137 mono_class_init_checked (MonoClass *klass, MonoError *error)
139 mono_error_init (error);
141 if (!mono_class_init (klass))
142 mono_error_set_for_class_failure (error, klass);
145 ICALL_EXPORT MonoObject *
146 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
152 MonoObject *result = NULL;
154 ac = (MonoClass *)arr->obj.vtable->klass;
156 esize = mono_array_element_size (ac);
157 ea = (gpointer*)((char*)arr->vector + (pos * esize));
159 if (ac->element_class->valuetype) {
160 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
161 mono_error_set_pending_exception (&error);
163 result = (MonoObject *)*ea;
167 ICALL_EXPORT MonoObject *
168 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
174 MONO_CHECK_ARG_NULL (idxs, NULL);
177 ic = (MonoClass *)io->obj.vtable->klass;
179 ac = (MonoClass *)arr->obj.vtable->klass;
181 g_assert (ic->rank == 1);
182 if (io->bounds != NULL || io->max_length != ac->rank) {
183 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
187 ind = (gint32 *)io->vector;
189 if (arr->bounds == NULL) {
190 if (*ind < 0 || *ind >= arr->max_length) {
191 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
195 return ves_icall_System_Array_GetValueImpl (arr, *ind);
198 for (i = 0; i < ac->rank; i++) {
199 if ((ind [i] < arr->bounds [i].lower_bound) ||
200 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
201 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
206 pos = ind [0] - arr->bounds [0].lower_bound;
207 for (i = 1; i < ac->rank; i++)
208 pos = pos * arr->bounds [i].length + ind [i] -
209 arr->bounds [i].lower_bound;
211 return ves_icall_System_Array_GetValueImpl (arr, pos);
215 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
218 MonoClass *ac, *vc, *ec;
227 mono_error_init (&error);
230 vc = value->vtable->klass;
234 ac = arr->obj.vtable->klass;
235 ec = ac->element_class;
237 esize = mono_array_element_size (ac);
238 ea = (gpointer*)((char*)arr->vector + (pos * esize));
239 va = (gpointer*)((char*)value + sizeof (MonoObject));
241 if (mono_class_is_nullable (ec)) {
242 mono_nullable_init ((guint8*)ea, value, ec);
247 mono_gc_bzero_atomic (ea, esize);
251 #define NO_WIDENING_CONVERSION G_STMT_START{\
252 mono_set_pending_exception (mono_get_exception_argument ( \
253 "value", "not a widening conversion")); \
257 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
258 if (esize < vsize + (extra)) { \
259 mono_set_pending_exception (mono_get_exception_argument ( \
260 "value", "not a widening conversion")); \
265 #define INVALID_CAST G_STMT_START{ \
266 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
267 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
271 /* Check element (destination) type. */
272 switch (ec->byval_arg.type) {
273 case MONO_TYPE_STRING:
274 switch (vc->byval_arg.type) {
275 case MONO_TYPE_STRING:
281 case MONO_TYPE_BOOLEAN:
282 switch (vc->byval_arg.type) {
283 case MONO_TYPE_BOOLEAN:
296 NO_WIDENING_CONVERSION;
305 if (!ec->valuetype) {
306 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
307 if (mono_error_set_pending_exception (&error))
311 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
315 if (mono_object_isinst_checked (value, ec, &error)) {
316 if (ec->has_references)
317 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
319 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
322 if (mono_error_set_pending_exception (&error))
328 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
330 et = ec->byval_arg.type;
331 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
332 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
334 vt = vc->byval_arg.type;
335 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
336 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
338 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
344 case MONO_TYPE_CHAR: \
345 CHECK_WIDENING_CONVERSION(0); \
346 *(etype *) ea = (etype) u64; \
348 /* You can't assign a signed value to an unsigned array. */ \
353 /* You can't assign a floating point number to an integer array. */ \
356 NO_WIDENING_CONVERSION; \
360 #define ASSIGN_SIGNED(etype) G_STMT_START{\
366 CHECK_WIDENING_CONVERSION(0); \
367 *(etype *) ea = (etype) i64; \
369 /* You can assign an unsigned value to a signed array if the array's */ \
370 /* element size is larger than the value size. */ \
375 case MONO_TYPE_CHAR: \
376 CHECK_WIDENING_CONVERSION(1); \
377 *(etype *) ea = (etype) u64; \
379 /* You can't assign a floating point number to an integer array. */ \
382 NO_WIDENING_CONVERSION; \
386 #define ASSIGN_REAL(etype) G_STMT_START{\
390 CHECK_WIDENING_CONVERSION(0); \
391 *(etype *) ea = (etype) r64; \
393 /* All integer values fit into a floating point array, so we don't */ \
394 /* need to CHECK_WIDENING_CONVERSION here. */ \
399 *(etype *) ea = (etype) i64; \
405 case MONO_TYPE_CHAR: \
406 *(etype *) ea = (etype) u64; \
413 u64 = *(guint8 *) va;
416 u64 = *(guint16 *) va;
419 u64 = *(guint32 *) va;
422 u64 = *(guint64 *) va;
428 i64 = *(gint16 *) va;
431 i64 = *(gint32 *) va;
434 i64 = *(gint64 *) va;
437 r64 = *(gfloat *) va;
440 r64 = *(gdouble *) va;
443 u64 = *(guint16 *) va;
445 case MONO_TYPE_BOOLEAN:
446 /* Boolean is only compatible with itself. */
459 NO_WIDENING_CONVERSION;
466 /* If we can't do a direct copy, let's try a widening conversion. */
469 ASSIGN_UNSIGNED (guint16);
471 ASSIGN_UNSIGNED (guint8);
473 ASSIGN_UNSIGNED (guint16);
475 ASSIGN_UNSIGNED (guint32);
477 ASSIGN_UNSIGNED (guint64);
479 ASSIGN_SIGNED (gint8);
481 ASSIGN_SIGNED (gint16);
483 ASSIGN_SIGNED (gint32);
485 ASSIGN_SIGNED (gint64);
487 ASSIGN_REAL (gfloat);
489 ASSIGN_REAL (gdouble);
493 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
497 #undef NO_WIDENING_CONVERSION
498 #undef CHECK_WIDENING_CONVERSION
499 #undef ASSIGN_UNSIGNED
505 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
511 MONO_CHECK_ARG_NULL (idxs,);
513 ic = idxs->obj.vtable->klass;
514 ac = arr->obj.vtable->klass;
516 g_assert (ic->rank == 1);
517 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
518 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
522 ind = (gint32 *)idxs->vector;
524 if (arr->bounds == NULL) {
525 if (*ind < 0 || *ind >= arr->max_length) {
526 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
530 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
534 for (i = 0; i < ac->rank; i++)
535 if ((ind [i] < arr->bounds [i].lower_bound) ||
536 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
537 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
541 pos = ind [0] - arr->bounds [0].lower_bound;
542 for (i = 1; i < ac->rank; i++)
543 pos = pos * arr->bounds [i].length + ind [i] -
544 arr->bounds [i].lower_bound;
546 ves_icall_System_Array_SetValueImpl (arr, value, pos);
549 ICALL_EXPORT MonoArray *
550 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
553 MonoClass *aklass, *klass;
556 gboolean bounded = FALSE;
558 MONO_CHECK_ARG_NULL (type, NULL);
559 MONO_CHECK_ARG_NULL (lengths, NULL);
561 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
563 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
565 for (i = 0; i < mono_array_length (lengths); i++) {
566 if (mono_array_get (lengths, gint32, i) < 0) {
567 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
572 klass = mono_class_from_mono_type (type->type);
573 mono_class_init_checked (klass, &error);
574 if (mono_error_set_pending_exception (&error))
577 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
578 /* vectors are not the same as one dimensional arrays with no-zero bounds */
583 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
585 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
586 for (i = 0; i < aklass->rank; ++i) {
587 sizes [i] = mono_array_get (lengths, guint32, i);
589 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
591 sizes [i + aklass->rank] = 0;
594 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
595 mono_error_set_pending_exception (&error);
600 ICALL_EXPORT MonoArray *
601 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
604 MonoClass *aklass, *klass;
607 gboolean bounded = FALSE;
609 MONO_CHECK_ARG_NULL (type, NULL);
610 MONO_CHECK_ARG_NULL (lengths, NULL);
612 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
614 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
616 for (i = 0; i < mono_array_length (lengths); i++) {
617 if ((mono_array_get (lengths, gint64, i) < 0) ||
618 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
619 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
624 klass = mono_class_from_mono_type (type->type);
625 mono_class_init_checked (klass, &error);
626 if (mono_error_set_pending_exception (&error))
629 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
630 /* vectors are not the same as one dimensional arrays with no-zero bounds */
635 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
637 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
638 for (i = 0; i < aklass->rank; ++i) {
639 sizes [i] = mono_array_get (lengths, guint64, i);
641 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
643 sizes [i + aklass->rank] = 0;
646 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
647 mono_error_set_pending_exception (&error);
653 ves_icall_System_Array_GetRank (MonoObject *arr)
655 return arr->vtable->klass->rank;
659 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
661 gint32 rank = arr->obj.vtable->klass->rank;
664 if ((dimension < 0) || (dimension >= rank)) {
665 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
669 if (arr->bounds == NULL)
670 length = arr->max_length;
672 length = arr->bounds [dimension].length;
674 #ifdef MONO_BIG_ARRAYS
675 if (length > G_MAXINT32) {
676 mono_set_pending_exception (mono_get_exception_overflow ());
684 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
686 gint32 rank = arr->obj.vtable->klass->rank;
688 if ((dimension < 0) || (dimension >= rank)) {
689 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
693 if (arr->bounds == NULL)
694 return arr->max_length;
696 return arr->bounds [dimension].length;
700 ves_icall_System_Array_GetLowerBound (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)
712 return arr->bounds [dimension].lower_bound;
716 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
718 int sz = mono_array_element_size (mono_object_class (arr));
719 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
722 ICALL_EXPORT MonoArray*
723 ves_icall_System_Array_Clone (MonoArray *arr)
726 MonoArray *result = mono_array_clone_checked (arr, &error);
727 mono_error_set_pending_exception (&error);
731 ICALL_EXPORT gboolean
732 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
737 MonoVTable *src_vtable;
738 MonoVTable *dest_vtable;
739 MonoClass *src_class;
740 MonoClass *dest_class;
742 src_vtable = source->obj.vtable;
743 dest_vtable = dest->obj.vtable;
745 if (src_vtable->rank != dest_vtable->rank)
748 if (source->bounds || dest->bounds)
751 /* there's no integer overflow since mono_array_length returns an unsigned integer */
752 if ((dest_idx + length > mono_array_length_fast (dest)) ||
753 (source_idx + length > mono_array_length_fast (source)))
756 src_class = src_vtable->klass->element_class;
757 dest_class = dest_vtable->klass->element_class;
760 * Handle common cases.
763 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
764 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
766 if (src_class == mono_defaults.object_class && dest_class->valuetype)
769 /* Check if we're copying a char[] <==> (u)short[] */
770 if (src_class != dest_class) {
771 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
774 /* 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. */
775 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
779 if (dest_class->valuetype) {
780 element_size = mono_array_element_size (source->obj.vtable->klass);
781 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
782 if (dest_class->has_references) {
783 mono_value_copy_array (dest, dest_idx, source_addr, length);
785 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
786 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
789 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
796 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
802 ac = (MonoClass *)arr->obj.vtable->klass;
804 esize = mono_array_element_size (ac);
805 ea = (gpointer*)((char*)arr->vector + (pos * esize));
807 mono_gc_memmove_atomic (value, ea, esize);
811 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
817 ac = (MonoClass *)arr->obj.vtable->klass;
818 ec = ac->element_class;
820 esize = mono_array_element_size (ac);
821 ea = (gpointer*)((char*)arr->vector + (pos * esize));
823 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
824 g_assert (esize == sizeof (gpointer));
825 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
827 g_assert (ec->inited);
828 g_assert (esize == mono_class_value_size (ec, NULL));
829 if (ec->has_references)
830 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
832 mono_gc_memmove_atomic (ea, value, esize);
837 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
839 MonoClass *klass = array->obj.vtable->klass;
840 guint32 size = mono_array_element_size (klass);
841 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
843 const char *field_data;
845 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
846 MonoException *exc = mono_get_exception_argument("array",
847 "Cannot initialize array of non-primitive type.");
848 mono_set_pending_exception (exc);
852 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
853 MonoException *exc = mono_get_exception_argument("field_handle",
854 "Field doesn't have an RVA");
855 mono_set_pending_exception (exc);
859 size *= array->max_length;
860 field_data = mono_field_get_data (field_handle);
862 if (size > mono_type_size (field_handle->type, &align)) {
863 MonoException *exc = mono_get_exception_argument("field_handle",
864 "Field not large enough to fill array");
865 mono_set_pending_exception (exc);
869 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
871 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
872 guint ## n *src = (guint ## n *) field_data; \
874 nEnt = (size / sizeof(guint ## n)); \
876 for (i = 0; i < nEnt; i++) { \
877 data[i] = read ## n (&src[i]); \
881 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
883 switch (type->type) {
900 memcpy (mono_array_addr (array, char, 0), field_data, size);
904 memcpy (mono_array_addr (array, char, 0), field_data, size);
909 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
911 return offsetof (MonoString, chars);
914 ICALL_EXPORT MonoObject *
915 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
917 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
921 MonoObject *ret = mono_object_clone_checked (obj, &error);
922 mono_error_set_pending_exception (&error);
929 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
935 MONO_CHECK_ARG_NULL (handle,);
937 klass = mono_class_from_mono_type (handle);
938 MONO_CHECK_ARG (handle, klass,);
940 if (klass->generic_container)
943 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
944 if (!is_ok (&error)) {
945 mono_error_set_pending_exception (&error);
949 /* This will call the type constructor */
950 if (!mono_runtime_class_init_full (vtable, &error))
951 mono_error_set_pending_exception (&error);
955 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
959 mono_image_check_for_module_cctor (image);
960 if (image->has_module_cctor) {
961 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
962 if (!mono_error_ok (&error)) {
963 mono_error_set_pending_exception (&error);
966 /*It's fine to raise the exception here*/
967 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
968 if (!is_ok (&error)) {
969 mono_error_set_pending_exception (&error);
972 if (!mono_runtime_class_init_full (vtable, &error))
973 mono_error_set_pending_exception (&error);
977 ICALL_EXPORT MonoBoolean
978 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
983 /* later make this configurable and per-arch */
984 int min_size = 4096 * 4 * sizeof (void*);
985 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
986 /* if we have no info we are optimistic and assume there is enough room */
989 current = (guint8 *)&stack_addr;
990 if (current > stack_addr) {
991 if ((current - stack_addr) < min_size)
994 if (current - (stack_addr - stack_size) < min_size)
1000 ICALL_EXPORT MonoObject *
1001 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1004 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1005 mono_error_set_pending_exception (&error);
1011 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1015 MonoObject **values = NULL;
1018 gint32 result = (int)(gsize)mono_defaults.int32_class;
1019 MonoClassField* field;
1022 klass = mono_object_class (this_obj);
1024 if (mono_class_num_fields (klass) == 0)
1028 * Compute the starting value of the hashcode for fields of primitive
1029 * types, and return the remaining fields in an array to the managed side.
1030 * This way, we can avoid costly reflection operations in managed code.
1033 while ((field = mono_class_get_fields (klass, &iter))) {
1034 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1036 if (mono_field_is_deleted (field))
1038 /* FIXME: Add more types */
1039 switch (field->type->type) {
1041 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1043 case MONO_TYPE_STRING: {
1045 s = *(MonoString**)((guint8*)this_obj + field->offset);
1047 result ^= mono_string_hash (s);
1052 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1053 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1054 if (!is_ok (&error)) {
1055 mono_error_set_pending_exception (&error);
1058 values [count++] = o;
1064 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1065 if (mono_error_set_pending_exception (&error))
1067 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1068 for (i = 0; i < count; ++i)
1069 mono_array_setref (*fields, i, values [i]);
1076 ICALL_EXPORT MonoBoolean
1077 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1081 MonoObject **values = NULL;
1083 MonoClassField* field;
1087 MONO_CHECK_ARG_NULL (that, FALSE);
1089 if (this_obj->vtable != that->vtable)
1092 klass = mono_object_class (this_obj);
1094 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1095 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1098 * Do the comparison for fields of primitive type and return a result if
1099 * possible. Otherwise, return the remaining fields in an array to the
1100 * managed side. This way, we can avoid costly reflection operations in
1105 while ((field = mono_class_get_fields (klass, &iter))) {
1106 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1108 if (mono_field_is_deleted (field))
1110 /* FIXME: Add more types */
1111 switch (field->type->type) {
1114 case MONO_TYPE_BOOLEAN:
1115 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1120 case MONO_TYPE_CHAR:
1121 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1126 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1131 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1135 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1139 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1144 case MONO_TYPE_STRING: {
1145 MonoString *s1, *s2;
1146 guint32 s1len, s2len;
1147 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1148 s2 = *(MonoString**)((guint8*)that + field->offset);
1151 if ((s1 == NULL) || (s2 == NULL))
1153 s1len = mono_string_length (s1);
1154 s2len = mono_string_length (s2);
1158 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1164 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1165 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1166 if (!is_ok (&error)) {
1167 mono_error_set_pending_exception (&error);
1170 values [count++] = o;
1171 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1172 if (!is_ok (&error)) {
1173 mono_error_set_pending_exception (&error);
1176 values [count++] = o;
1179 if (klass->enumtype)
1180 /* enums only have one non-static field */
1186 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1187 if (mono_error_set_pending_exception (&error))
1189 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1190 for (i = 0; i < count; ++i)
1191 mono_array_setref_fast (*fields, i, values [i]);
1198 ICALL_EXPORT MonoReflectionType *
1199 ves_icall_System_Object_GetType (MonoObject *obj)
1202 MonoReflectionType *ret;
1203 #ifndef DISABLE_REMOTING
1204 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1205 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1208 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1210 mono_error_set_pending_exception (&error);
1215 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1217 MonoMethod **dest = (MonoMethod **)data;
1219 /* skip unmanaged frames */
1224 if (!strcmp (m->klass->name_space, "System.Reflection"))
1233 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1235 MonoMethod **dest = (MonoMethod **)data;
1237 /* skip unmanaged frames */
1241 if (m->wrapper_type != MONO_WRAPPER_NONE)
1249 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1260 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1262 MonoMethod **dest = (MonoMethod **)data;
1264 /* skip unmanaged frames */
1268 if (m->wrapper_type != MONO_WRAPPER_NONE)
1276 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1277 || (!strcmp (m->klass->name_space, "System"))))
1287 static MonoReflectionType *
1288 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1290 MonoMethod *m, *dest;
1292 MonoType *type = NULL;
1293 MonoAssembly *assembly = NULL;
1294 gboolean type_resolve = FALSE;
1295 MonoImage *rootimage = NULL;
1297 mono_error_init (error);
1300 * We must compute the calling assembly as type loading must happen under a metadata context.
1301 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1302 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1304 m = mono_method_get_last_managed ();
1306 if (m && m->klass->image != mono_defaults.corlib) {
1307 /* Happens with inlining */
1309 /* Ugly hack: type_from_parsed_name is called from
1310 * System.Type.internal_from_name, which is called most
1311 * directly from System.Type.GetType(string,bool,bool) but
1312 * also indirectly from places such as
1313 * System.Type.GetType(string,func,func) (via
1314 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1315 * so we need to skip over all of those to find the true caller.
1317 * It would be nice if we had stack marks.
1319 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1325 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1326 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1327 * to crash. This only seems to happen in some strange remoting
1328 * scenarios and I was unable to figure out what's happening there.
1329 * Dec 10, 2005 - Martin.
1333 assembly = dest->klass->image->assembly;
1334 type_resolve = TRUE;
1335 rootimage = assembly->image;
1337 g_warning (G_STRLOC);
1340 if (info->assembly.name)
1341 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1344 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1345 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1346 return_val_if_nok (error, NULL);
1350 // Say we're looking for System.Generic.Dict<int, Local>
1351 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1352 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1353 // is messed up when we go to construct the Local as the type arg...
1355 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1356 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1357 if (!info->assembly.name && !type) {
1359 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1360 return_val_if_nok (error, NULL);
1362 if (assembly && !type && type_resolve) {
1363 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1364 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1365 return_val_if_nok (error, NULL);
1371 return mono_type_get_object_checked (mono_domain_get (), type, error);
1374 ICALL_EXPORT MonoReflectionType*
1375 ves_icall_System_Type_internal_from_name (MonoString *name,
1376 MonoBoolean throwOnError,
1377 MonoBoolean ignoreCase)
1380 MonoTypeNameParse info;
1381 MonoReflectionType *type = NULL;
1384 char *str = mono_string_to_utf8_checked (name, &error);
1385 if (!is_ok (&error))
1388 parsedOk = mono_reflection_parse_type (str, &info);
1390 /* mono_reflection_parse_type() mangles the string */
1392 mono_reflection_free_type_info (&info);
1394 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1398 type = type_from_parsed_name (&info, ignoreCase, &error);
1400 mono_reflection_free_type_info (&info);
1402 if (!is_ok (&error))
1407 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1414 if (!is_ok (&error)) {
1416 mono_error_set_pending_exception (&error);
1418 mono_error_cleanup (&error);
1426 ICALL_EXPORT MonoReflectionType*
1427 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1430 MonoReflectionType *ret;
1431 MonoDomain *domain = mono_domain_get ();
1433 ret = mono_type_get_object_checked (domain, handle, &error);
1434 mono_error_set_pending_exception (&error);
1439 ICALL_EXPORT MonoType*
1440 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1442 return mono_class_get_type (klass);
1446 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1448 g_ptr_array_free (ptr_array, TRUE);
1452 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1458 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1461 char *res = mono_string_to_utf8_checked (s, &error);
1462 mono_error_set_pending_exception (&error);
1466 /* System.TypeCode */
1485 TYPECODE_STRING = 18
1488 ICALL_EXPORT guint32
1489 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1491 int t = type->type->type;
1493 if (type->type->byref)
1494 return TYPECODE_OBJECT;
1498 case MONO_TYPE_VOID:
1499 return TYPECODE_OBJECT;
1500 case MONO_TYPE_BOOLEAN:
1501 return TYPECODE_BOOLEAN;
1503 return TYPECODE_BYTE;
1505 return TYPECODE_SBYTE;
1507 return TYPECODE_UINT16;
1509 return TYPECODE_INT16;
1510 case MONO_TYPE_CHAR:
1511 return TYPECODE_CHAR;
1515 return TYPECODE_OBJECT;
1517 return TYPECODE_UINT32;
1519 return TYPECODE_INT32;
1521 return TYPECODE_UINT64;
1523 return TYPECODE_INT64;
1525 return TYPECODE_SINGLE;
1527 return TYPECODE_DOUBLE;
1528 case MONO_TYPE_VALUETYPE: {
1529 MonoClass *klass = type->type->data.klass;
1531 if (klass->enumtype) {
1532 t = mono_class_enum_basetype (klass)->type;
1534 } else if (mono_is_corlib_image (klass->image)) {
1535 if (strcmp (klass->name_space, "System") == 0) {
1536 if (strcmp (klass->name, "Decimal") == 0)
1537 return TYPECODE_DECIMAL;
1538 else if (strcmp (klass->name, "DateTime") == 0)
1539 return TYPECODE_DATETIME;
1542 return TYPECODE_OBJECT;
1544 case MONO_TYPE_STRING:
1545 return TYPECODE_STRING;
1546 case MONO_TYPE_SZARRAY:
1547 case MONO_TYPE_ARRAY:
1548 case MONO_TYPE_OBJECT:
1550 case MONO_TYPE_MVAR:
1551 case MONO_TYPE_TYPEDBYREF:
1552 return TYPECODE_OBJECT;
1553 case MONO_TYPE_CLASS:
1555 MonoClass *klass = type->type->data.klass;
1556 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1557 if (strcmp (klass->name, "DBNull") == 0)
1558 return TYPECODE_DBNULL;
1561 return TYPECODE_OBJECT;
1562 case MONO_TYPE_GENERICINST:
1563 return TYPECODE_OBJECT;
1565 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1571 mono_type_is_primitive (MonoType *type)
1573 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1574 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1578 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1580 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1581 return mono_class_enum_basetype (type->data.klass);
1582 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1583 return mono_class_enum_basetype (type->data.generic_class->container_class);
1587 ICALL_EXPORT guint32
1588 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1593 g_assert (type != NULL);
1595 klass = mono_class_from_mono_type (type->type);
1596 klassc = mono_class_from_mono_type (c->type);
1598 if (type->type->byref ^ c->type->byref)
1601 if (type->type->byref) {
1602 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1603 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1605 klass = mono_class_from_mono_type (t);
1606 klassc = mono_class_from_mono_type (ot);
1608 if (mono_type_is_primitive (t)) {
1609 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1610 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1611 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1612 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1613 return t->type == ot->type;
1615 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1618 if (klass->valuetype)
1619 return klass == klassc;
1620 return klass->valuetype == klassc->valuetype;
1623 return mono_class_is_assignable_from (klass, klassc);
1626 ICALL_EXPORT guint32
1627 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1630 MonoClass *klass = mono_class_from_mono_type (type->type);
1631 mono_class_init_checked (klass, &error);
1632 if (!is_ok (&error)) {
1633 mono_error_set_pending_exception (&error);
1636 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1637 mono_error_set_pending_exception (&error);
1641 ICALL_EXPORT guint32
1642 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1644 MonoClass *klass = mono_class_from_mono_type (type->type);
1645 return klass->flags;
1648 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1649 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1652 MonoClass *klass = field->field->parent;
1653 MonoMarshalType *info;
1657 if (klass->generic_container ||
1658 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1661 ftype = mono_field_get_type (field->field);
1662 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1665 info = mono_marshal_load_type_info (klass);
1667 for (i = 0; i < info->num_fields; ++i) {
1668 if (info->fields [i].field == field->field) {
1669 if (!info->fields [i].mspec)
1672 MonoReflectionMarshalAsAttribute* obj;
1673 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1674 if (!mono_error_ok (&error))
1675 mono_error_set_pending_exception (&error);
1684 ICALL_EXPORT MonoReflectionField*
1685 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1688 gboolean found = FALSE;
1694 klass = handle->parent;
1696 klass = mono_class_from_mono_type (type);
1698 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1701 /* The managed code will throw the exception */
1705 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1706 mono_error_set_pending_exception (&error);
1710 ICALL_EXPORT MonoReflectionEvent*
1711 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1719 klass = handle->parent;
1721 klass = mono_class_from_mono_type (type);
1723 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1725 /* Managed code will throw an exception */
1729 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1730 mono_error_set_pending_exception (&error);
1735 ICALL_EXPORT MonoReflectionProperty*
1736 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1744 klass = handle->parent;
1746 klass = mono_class_from_mono_type (type);
1748 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1750 /* Managed code will throw an exception */
1754 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1755 mono_error_set_pending_exception (&error);
1759 ICALL_EXPORT MonoArray*
1760 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1763 MonoType *type = mono_field_get_type_checked (field->field, &error);
1766 if (!mono_error_ok (&error)) {
1767 mono_error_set_pending_exception (&error);
1771 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1772 mono_error_set_pending_exception (&error);
1777 vell_icall_get_method_attributes (MonoMethod *method)
1779 return method->flags;
1783 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1786 MonoReflectionType *rt;
1787 MonoDomain *domain = mono_domain_get ();
1788 MonoMethodSignature* sig;
1790 sig = mono_method_signature_checked (method, &error);
1791 if (!mono_error_ok (&error)) {
1792 mono_error_set_pending_exception (&error);
1796 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1797 if (!mono_error_ok (&error)) {
1798 mono_error_set_pending_exception (&error);
1802 MONO_STRUCT_SETREF (info, parent, rt);
1804 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1805 if (!mono_error_ok (&error)) {
1806 mono_error_set_pending_exception (&error);
1810 MONO_STRUCT_SETREF (info, ret, rt);
1812 info->attrs = method->flags;
1813 info->implattrs = method->iflags;
1814 if (sig->call_convention == MONO_CALL_DEFAULT)
1815 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1817 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1822 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1825 ICALL_EXPORT MonoArray*
1826 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1829 MonoDomain *domain = mono_domain_get ();
1831 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1832 mono_error_set_pending_exception (&error);
1836 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1837 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1840 MonoDomain *domain = mono_domain_get ();
1841 MonoReflectionMarshalAsAttribute* res = NULL;
1842 MonoMarshalSpec **mspecs;
1845 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1846 mono_method_get_marshal_info (method, mspecs);
1849 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1850 if (!mono_error_ok (&error)) {
1851 mono_error_set_pending_exception (&error);
1856 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1858 mono_metadata_free_marshal_spec (mspecs [i]);
1865 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1867 MonoClass *parent = field->field->parent;
1868 if (!parent->size_inited)
1869 mono_class_init (parent);
1870 mono_class_setup_fields_locking (parent);
1872 return field->field->offset - sizeof (MonoObject);
1875 ICALL_EXPORT MonoReflectionType*
1876 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1879 MonoReflectionType *ret;
1882 parent = declaring? field->field->parent: field->klass;
1884 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1885 mono_error_set_pending_exception (&error);
1891 ICALL_EXPORT MonoObject *
1892 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1895 MonoClass *fklass = field->klass;
1896 MonoClassField *cf = field->field;
1897 MonoDomain *domain = mono_object_domain (field);
1899 if (fklass->image->assembly->ref_only) {
1900 mono_set_pending_exception (mono_get_exception_invalid_operation (
1901 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1905 if (mono_security_core_clr_enabled () &&
1906 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1907 mono_error_set_pending_exception (&error);
1911 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1912 mono_error_set_pending_exception (&error);
1917 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1920 MonoClassField *cf = field->field;
1924 if (field->klass->image->assembly->ref_only) {
1925 mono_set_pending_exception (mono_get_exception_invalid_operation (
1926 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1930 if (mono_security_core_clr_enabled () &&
1931 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1932 mono_error_set_pending_exception (&error);
1936 type = mono_field_get_type_checked (cf, &error);
1937 if (!mono_error_ok (&error)) {
1938 mono_error_set_pending_exception (&error);
1942 v = (gchar *) value;
1944 switch (type->type) {
1947 case MONO_TYPE_BOOLEAN:
1950 case MONO_TYPE_CHAR:
1959 case MONO_TYPE_VALUETYPE:
1962 v += sizeof (MonoObject);
1964 case MONO_TYPE_STRING:
1965 case MONO_TYPE_OBJECT:
1966 case MONO_TYPE_CLASS:
1967 case MONO_TYPE_ARRAY:
1968 case MONO_TYPE_SZARRAY:
1971 case MONO_TYPE_GENERICINST: {
1972 MonoGenericClass *gclass = type->data.generic_class;
1973 g_assert (!gclass->context.class_inst->is_open);
1975 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1976 MonoClass *nklass = mono_class_from_mono_type (type);
1977 MonoObject *nullable;
1980 * Convert the boxed vtype into a Nullable structure.
1981 * This is complicated by the fact that Nullables have
1982 * a variable structure.
1984 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1985 if (!mono_error_ok (&error)) {
1986 mono_error_set_pending_exception (&error);
1990 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1992 v = (gchar *)mono_object_unbox (nullable);
1995 if (gclass->container_class->valuetype && (v != NULL))
1996 v += sizeof (MonoObject);
2000 g_error ("type 0x%x not handled in "
2001 "ves_icall_FieldInfo_SetValueInternal", type->type);
2006 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2007 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2008 if (!is_ok (&error)) {
2009 mono_error_set_pending_exception (&error);
2012 if (!vtable->initialized) {
2013 if (!mono_runtime_class_init_full (vtable, &error)) {
2014 mono_error_set_pending_exception (&error);
2018 mono_field_static_set_value (vtable, cf, v);
2020 mono_field_set_value (obj, cf, v);
2025 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2034 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2035 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2039 if (MONO_TYPE_IS_REFERENCE (f->type))
2040 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2042 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2045 ICALL_EXPORT MonoObject *
2046 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2048 MonoObject *o = NULL;
2049 MonoClassField *field = rfield->field;
2051 MonoDomain *domain = mono_object_domain (rfield);
2053 MonoTypeEnum def_type;
2054 const char *def_value;
2058 mono_class_init (field->parent);
2060 t = mono_field_get_type_checked (field, &error);
2061 if (!mono_error_ok (&error)) {
2062 mono_error_set_pending_exception (&error);
2066 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2067 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2071 if (image_is_dynamic (field->parent->image)) {
2072 MonoClass *klass = field->parent;
2073 int fidx = field - klass->fields;
2075 g_assert (fidx >= 0 && fidx < klass->field.count);
2076 g_assert (klass->ext);
2077 g_assert (klass->ext->field_def_values);
2078 def_type = klass->ext->field_def_values [fidx].def_type;
2079 def_value = klass->ext->field_def_values [fidx].data;
2080 if (def_type == MONO_TYPE_END) {
2081 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2085 def_value = mono_class_get_field_default_value (field, &def_type);
2086 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2088 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2093 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2097 case MONO_TYPE_BOOLEAN:
2100 case MONO_TYPE_CHAR:
2108 case MONO_TYPE_R8: {
2111 /* boxed value type */
2112 t = g_new0 (MonoType, 1);
2114 klass = mono_class_from_mono_type (t);
2116 o = mono_object_new_checked (domain, klass, &error);
2117 if (!mono_error_ok (&error)) {
2118 mono_error_set_pending_exception (&error);
2121 v = ((gchar *) o) + sizeof (MonoObject);
2122 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2123 if (mono_error_set_pending_exception (&error))
2127 case MONO_TYPE_STRING:
2128 case MONO_TYPE_CLASS:
2129 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2130 if (mono_error_set_pending_exception (&error))
2134 g_assert_not_reached ();
2140 ICALL_EXPORT MonoReflectionType*
2141 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2144 MonoReflectionType *ret;
2147 type = mono_field_get_type_checked (ref_field->field, &error);
2148 if (!mono_error_ok (&error)) {
2149 mono_error_set_pending_exception (&error);
2153 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2154 if (!mono_error_ok (&error)) {
2155 mono_error_set_pending_exception (&error);
2162 /* From MonoProperty.cs */
2164 PInfo_Attributes = 1,
2165 PInfo_GetMethod = 1 << 1,
2166 PInfo_SetMethod = 1 << 2,
2167 PInfo_ReflectedType = 1 << 3,
2168 PInfo_DeclaringType = 1 << 4,
2173 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2176 MonoReflectionType *rt;
2177 MonoReflectionMethod *rm;
2178 MonoDomain *domain = mono_object_domain (property);
2179 const MonoProperty *pproperty = property->property;
2181 if ((req_info & PInfo_ReflectedType) != 0) {
2182 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2183 if (mono_error_set_pending_exception (&error))
2186 MONO_STRUCT_SETREF (info, parent, rt);
2188 if ((req_info & PInfo_DeclaringType) != 0) {
2189 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2190 if (mono_error_set_pending_exception (&error))
2193 MONO_STRUCT_SETREF (info, declaring_type, rt);
2196 if ((req_info & PInfo_Name) != 0)
2197 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2199 if ((req_info & PInfo_Attributes) != 0)
2200 info->attrs = pproperty->attrs;
2202 if ((req_info & PInfo_GetMethod) != 0) {
2203 if (pproperty->get &&
2204 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2205 pproperty->get->klass == property->klass)) {
2206 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2207 if (mono_error_set_pending_exception (&error))
2213 MONO_STRUCT_SETREF (info, get, rm);
2215 if ((req_info & PInfo_SetMethod) != 0) {
2216 if (pproperty->set &&
2217 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2218 pproperty->set->klass == property->klass)) {
2219 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2220 if (mono_error_set_pending_exception (&error))
2226 MONO_STRUCT_SETREF (info, set, rm);
2229 * There may be other methods defined for properties, though, it seems they are not exposed
2230 * in the reflection API
2235 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2238 MonoReflectionType *rt;
2239 MonoReflectionMethod *rm;
2240 MonoDomain *domain = mono_object_domain (event);
2242 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2243 if (mono_error_set_pending_exception (&error))
2246 MONO_STRUCT_SETREF (info, reflected_type, rt);
2248 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2249 if (mono_error_set_pending_exception (&error))
2252 MONO_STRUCT_SETREF (info, declaring_type, rt);
2254 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2255 info->attrs = event->event->attrs;
2257 if (event->event->add) {
2258 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2259 if (mono_error_set_pending_exception (&error))
2265 MONO_STRUCT_SETREF (info, add_method, rm);
2267 if (event->event->remove) {
2268 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2269 if (mono_error_set_pending_exception (&error))
2275 MONO_STRUCT_SETREF (info, remove_method, rm);
2277 if (event->event->raise) {
2278 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2279 if (mono_error_set_pending_exception (&error))
2285 MONO_STRUCT_SETREF (info, raise_method, rm);
2287 #ifndef MONO_SMALL_CONFIG
2288 if (event->event->other) {
2290 while (event->event->other [n])
2292 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2293 if (mono_error_set_pending_exception (&error))
2295 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2297 for (i = 0; i < n; i++) {
2298 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2299 if (mono_error_set_pending_exception (&error))
2301 mono_array_setref (info->other_methods, i, rm);
2308 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2313 mono_class_setup_interfaces (klass, error);
2314 if (!mono_error_ok (error))
2317 for (i = 0; i < klass->interface_count; i++) {
2318 ic = klass->interfaces [i];
2319 g_hash_table_insert (ifaces, ic, ic);
2321 collect_interfaces (ic, ifaces, error);
2322 if (!mono_error_ok (error))
2328 MonoArray *iface_array;
2329 MonoGenericContext *context;
2333 } FillIfaceArrayData;
2336 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2338 MonoReflectionType *rt;
2339 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2340 MonoClass *ic = (MonoClass *)key;
2341 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2343 if (!mono_error_ok (data->error))
2346 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2347 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2348 if (!mono_error_ok (data->error))
2352 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2353 if (!mono_error_ok (data->error))
2356 mono_array_setref (data->iface_array, data->next_idx++, rt);
2359 mono_metadata_free_type (inflated);
2363 get_interfaces_hash (gconstpointer v1)
2365 MonoClass *k = (MonoClass*)v1;
2367 return k->type_token;
2370 ICALL_EXPORT MonoArray*
2371 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2374 MonoClass *klass = mono_class_from_mono_type (type->type);
2376 FillIfaceArrayData data = { 0 };
2379 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2381 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2382 data.context = mono_class_get_context (klass);
2383 klass = klass->generic_class->container_class;
2386 for (parent = klass; parent; parent = parent->parent) {
2387 mono_class_setup_interfaces (parent, &error);
2388 if (!mono_error_ok (&error))
2390 collect_interfaces (parent, iface_hash, &error);
2391 if (!mono_error_ok (&error))
2395 data.error = &error;
2396 data.domain = mono_object_domain (type);
2398 len = g_hash_table_size (iface_hash);
2400 g_hash_table_destroy (iface_hash);
2401 if (!data.domain->empty_types) {
2402 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2403 if (!is_ok (&error))
2406 return data.domain->empty_types;
2409 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2410 if (!is_ok (&error))
2412 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2413 if (!mono_error_ok (&error))
2416 g_hash_table_destroy (iface_hash);
2417 return data.iface_array;
2420 g_hash_table_destroy (iface_hash);
2421 mono_error_set_pending_exception (&error);
2426 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2428 gboolean variance_used;
2429 MonoClass *klass = mono_class_from_mono_type (type->type);
2430 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2431 MonoReflectionMethod *member;
2434 int i = 0, len, ioffset;
2438 mono_class_init_checked (klass, &error);
2439 if (mono_error_set_pending_exception (&error))
2441 mono_class_init_checked (iclass, &error);
2442 if (mono_error_set_pending_exception (&error))
2445 mono_class_setup_vtable (klass);
2447 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2451 len = mono_class_num_methods (iclass);
2452 domain = mono_object_domain (type);
2453 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2454 if (mono_error_set_pending_exception (&error))
2456 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2457 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2458 if (mono_error_set_pending_exception (&error))
2460 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2462 while ((method = mono_class_get_methods (iclass, &iter))) {
2463 member = mono_method_get_object_checked (domain, method, iclass, &error);
2464 if (mono_error_set_pending_exception (&error))
2466 mono_array_setref (*methods, i, member);
2467 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2468 if (mono_error_set_pending_exception (&error))
2470 mono_array_setref (*targets, i, member);
2477 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2480 MonoClass *klass = mono_class_from_mono_type (type->type);
2482 mono_class_init_checked (klass, &error);
2483 if (mono_error_set_pending_exception (&error))
2486 if (image_is_dynamic (klass->image)) {
2487 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2488 *packing = tb->packing_size;
2489 *size = tb->class_size;
2491 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2495 ICALL_EXPORT MonoReflectionType*
2496 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2499 MonoReflectionType *ret;
2502 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2503 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2504 mono_error_set_pending_exception (&error);
2508 klass = mono_class_from_mono_type (type->type);
2509 mono_class_init_checked (klass, &error);
2510 if (mono_error_set_pending_exception (&error))
2514 // GetElementType should only return a type for:
2515 // Array Pointer PassedByRef
2516 if (type->type->byref)
2517 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2518 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2519 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2520 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2521 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2525 mono_error_set_pending_exception (&error);
2530 ICALL_EXPORT MonoReflectionType*
2531 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2534 MonoReflectionType *ret;
2536 if (type->type->byref)
2539 MonoClass *klass = mono_class_from_mono_type (type->type);
2543 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2544 mono_error_set_pending_exception (&error);
2549 ICALL_EXPORT MonoBoolean
2550 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2552 return type->type->type == MONO_TYPE_PTR;
2555 ICALL_EXPORT MonoBoolean
2556 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2558 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)));
2561 ICALL_EXPORT MonoBoolean
2562 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2564 return type->type->byref;
2567 ICALL_EXPORT MonoBoolean
2568 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2571 MonoClass *klass = mono_class_from_mono_type (type->type);
2572 mono_class_init_checked (klass, &error);
2573 if (mono_error_set_pending_exception (&error))
2576 return mono_class_is_com_object (klass);
2579 ICALL_EXPORT guint32
2580 ves_icall_reflection_get_token (MonoObject* obj)
2583 guint32 result = mono_reflection_get_token_checked (obj, &error);
2584 mono_error_set_pending_exception (&error);
2588 ICALL_EXPORT MonoReflectionModule*
2589 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2592 MonoReflectionModule *result = NULL;
2593 MonoClass *klass = mono_class_from_mono_type (type->type);
2594 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2595 mono_error_set_pending_exception (&error);
2599 ICALL_EXPORT MonoReflectionAssembly*
2600 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2603 MonoDomain *domain = mono_domain_get ();
2604 MonoClass *klass = mono_class_from_mono_type (type->type);
2605 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2606 mono_error_set_pending_exception (&error);
2610 ICALL_EXPORT MonoReflectionType*
2611 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2614 MonoReflectionType *ret;
2615 MonoDomain *domain = mono_domain_get ();
2618 if (type->type->byref)
2620 if (type->type->type == MONO_TYPE_VAR) {
2621 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2622 klass = param ? param->owner.klass : NULL;
2623 } else if (type->type->type == MONO_TYPE_MVAR) {
2624 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2625 klass = param ? param->owner.method->klass : NULL;
2627 klass = mono_class_from_mono_type (type->type)->nested_in;
2633 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2634 mono_error_set_pending_exception (&error);
2639 ICALL_EXPORT MonoStringHandle
2640 ves_icall_RuntimeType_get_Name (MonoReflectionTypeHandle reftype, MonoError *error)
2642 MonoDomain *domain = mono_domain_get ();
2643 MonoType *type = MONO_HANDLE_RAW(reftype)->type;
2644 MonoClass *klass = mono_class_from_mono_type (type);
2647 char *n = g_strdup_printf ("%s&", klass->name);
2648 MonoStringHandle res = mono_string_new_handle (domain, n, error);
2654 return mono_string_new_handle (domain, klass->name, error);
2658 ICALL_EXPORT MonoStringHandle
2659 ves_icall_RuntimeType_get_Namespace (MonoReflectionTypeHandle type, MonoError *error)
2661 MonoDomain *domain = mono_domain_get ();
2662 MonoClass *klass = mono_class_from_mono_type_handle (type);
2664 while (klass->nested_in)
2665 klass = klass->nested_in;
2667 if (klass->name_space [0] == '\0')
2668 return NULL_HANDLE_STRING;
2670 return mono_string_new_handle (domain, klass->name_space, error);
2674 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2678 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2679 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2683 klass = mono_class_from_mono_type (type->type);
2689 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2691 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2694 ICALL_EXPORT MonoArray*
2695 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2698 MonoReflectionType *rt;
2700 MonoClass *klass, *pklass;
2701 MonoDomain *domain = mono_object_domain (type);
2704 klass = mono_class_from_mono_type (type->type);
2706 if (klass->generic_container) {
2707 MonoGenericContainer *container = klass->generic_container;
2708 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2709 if (mono_error_set_pending_exception (&error))
2711 for (i = 0; i < container->type_argc; ++i) {
2712 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2714 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2715 if (mono_error_set_pending_exception (&error))
2718 mono_array_setref (res, i, rt);
2720 } else if (klass->generic_class) {
2721 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2722 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2723 if (mono_error_set_pending_exception (&error))
2725 for (i = 0; i < inst->type_argc; ++i) {
2726 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2727 if (mono_error_set_pending_exception (&error))
2730 mono_array_setref (res, i, rt);
2738 ICALL_EXPORT gboolean
2739 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2743 if (!IS_MONOTYPE (type))
2746 if (type->type->byref)
2749 klass = mono_class_from_mono_type (type->type);
2750 return klass->generic_container != NULL;
2753 ICALL_EXPORT MonoReflectionType*
2754 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2757 MonoReflectionType *ret;
2760 if (type->type->byref)
2763 klass = mono_class_from_mono_type (type->type);
2765 if (klass->generic_container) {
2766 return type; /* check this one */
2768 if (klass->generic_class) {
2769 MonoClass *generic_class = klass->generic_class->container_class;
2772 tb = mono_class_get_ref_info (generic_class);
2774 if (generic_class->wastypebuilder && tb)
2775 return (MonoReflectionType *)tb;
2777 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2778 mono_error_set_pending_exception (&error);
2786 ICALL_EXPORT MonoReflectionType*
2787 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2790 MonoReflectionType *ret;
2792 MonoType *geninst, **types;
2795 g_assert (IS_MONOTYPE (type));
2796 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2797 if (mono_error_set_pending_exception (&error))
2800 count = mono_array_length (type_array);
2801 types = g_new0 (MonoType *, count);
2803 for (i = 0; i < count; i++) {
2804 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2805 types [i] = t->type;
2808 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2811 mono_error_set_pending_exception (&error);
2815 klass = mono_class_from_mono_type (geninst);
2817 /*we might inflate to the GTD*/
2818 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2819 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2823 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2824 mono_error_set_pending_exception (&error);
2829 ICALL_EXPORT gboolean
2830 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2834 if (!IS_MONOTYPE (type))
2837 if (type->type->byref)
2840 klass = mono_class_from_mono_type (type->type);
2841 return klass->generic_class != NULL || klass->generic_container != NULL;
2845 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2847 if (!IS_MONOTYPE (type))
2850 if (is_generic_parameter (type->type))
2851 return mono_type_get_generic_param_num (type->type);
2855 ICALL_EXPORT MonoGenericParamInfo *
2856 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2858 return mono_generic_param_info (type->type->data.generic_param);
2861 ICALL_EXPORT MonoBoolean
2862 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2864 return is_generic_parameter (type->type);
2867 ICALL_EXPORT MonoReflectionMethod*
2868 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2869 MonoReflectionMethod* generic)
2876 MonoReflectionMethod *ret = NULL;
2878 domain = ((MonoObject *)type)->vtable->domain;
2880 klass = mono_class_from_mono_type (type->type);
2881 mono_class_init_checked (klass, &error);
2882 if (mono_error_set_pending_exception (&error))
2886 while ((method = mono_class_get_methods (klass, &iter))) {
2887 if (method->token == generic->method->token) {
2888 ret = mono_method_get_object_checked (domain, method, klass, &error);
2889 if (mono_error_set_pending_exception (&error))
2897 ICALL_EXPORT MonoReflectionMethod *
2898 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2901 MonoType *type = ref_type->type;
2903 MonoReflectionMethod *ret = NULL;
2905 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2906 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2909 if (type->type == MONO_TYPE_VAR)
2912 method = mono_type_get_generic_param_owner (type)->owner.method;
2915 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2916 if (!mono_error_ok (&error))
2917 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2921 ICALL_EXPORT MonoBoolean
2922 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2924 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2928 ICALL_EXPORT MonoBoolean
2929 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2931 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2936 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2938 MonoDomain *domain = mono_domain_get ();
2939 MonoImage *image = method->method->klass->image;
2940 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2941 MonoTableInfo *tables = image->tables;
2942 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2943 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2944 guint32 im_cols [MONO_IMPLMAP_SIZE];
2945 guint32 scope_token;
2946 const char *import = NULL;
2947 const char *scope = NULL;
2949 if (image_is_dynamic (image)) {
2950 MonoReflectionMethodAux *method_aux =
2951 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2953 import = method_aux->dllentry;
2954 scope = method_aux->dll;
2957 if (!import || !scope) {
2958 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2963 if (piinfo->implmap_idx) {
2964 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2966 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2967 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2968 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2969 scope = mono_metadata_string_heap (image, scope_token);
2973 *flags = piinfo->piflags;
2974 *entry_point = mono_string_new (domain, import);
2975 *dll_name = mono_string_new (domain, scope);
2978 ICALL_EXPORT MonoReflectionMethod *
2979 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2981 MonoMethodInflated *imethod;
2983 MonoReflectionMethod *ret = NULL;
2986 if (method->method->is_generic)
2989 if (!method->method->is_inflated)
2992 imethod = (MonoMethodInflated *) method->method;
2994 result = imethod->declaring;
2995 /* Not a generic method. */
2996 if (!result->is_generic)
2999 if (image_is_dynamic (method->method->klass->image)) {
3000 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3001 MonoReflectionMethod *res;
3004 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3005 * the dynamic case as well ?
3007 mono_image_lock ((MonoImage*)image);
3008 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3009 mono_image_unlock ((MonoImage*)image);
3015 if (imethod->context.class_inst) {
3016 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3017 /*Generic methods gets the context of the GTD.*/
3018 if (mono_class_get_context (klass)) {
3019 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3020 if (!mono_error_ok (&error))
3025 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3027 if (!mono_error_ok (&error))
3028 mono_error_set_pending_exception (&error);
3032 ICALL_EXPORT gboolean
3033 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3035 return mono_method_signature (method->method)->generic_param_count != 0;
3038 ICALL_EXPORT gboolean
3039 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3041 return method->method->is_generic;
3044 ICALL_EXPORT MonoArray*
3045 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3048 MonoReflectionType *rt;
3053 domain = mono_object_domain (method);
3055 if (method->method->is_inflated) {
3056 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3059 count = inst->type_argc;
3060 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3061 if (mono_error_set_pending_exception (&error))
3064 for (i = 0; i < count; i++) {
3065 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3066 if (mono_error_set_pending_exception (&error))
3069 mono_array_setref (res, i, rt);
3076 count = mono_method_signature (method->method)->generic_param_count;
3077 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3078 if (mono_error_set_pending_exception (&error))
3081 for (i = 0; i < count; i++) {
3082 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3083 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3084 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3086 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3087 if (mono_error_set_pending_exception (&error))
3090 mono_array_setref (res, i, rt);
3096 ICALL_EXPORT MonoObject *
3097 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3101 * Invoke from reflection is supposed to always be a virtual call (the API
3102 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3103 * greater flexibility.
3105 MonoMethod *m = method->method;
3106 MonoMethodSignature *sig = mono_method_signature (m);
3109 void *obj = this_arg;
3113 if (mono_security_core_clr_enabled () &&
3114 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3115 mono_error_set_pending_exception (&error);
3119 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3120 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3121 mono_error_cleanup (&error); /* FIXME does this make sense? */
3122 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3127 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3128 if (!is_ok (&error)) {
3129 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3132 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3133 char *target_name = mono_type_get_full_name (m->klass);
3134 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3135 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3137 g_free (target_name);
3141 m = mono_object_get_virtual_method (this_arg, m);
3142 /* must pass the pointer to the value for valuetype methods */
3143 if (m->klass->valuetype)
3144 obj = mono_object_unbox (this_arg);
3145 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3146 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3151 if (sig->ret->byref) {
3152 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"));
3156 pcount = params? mono_array_length (params): 0;
3157 if (pcount != sig->param_count) {
3158 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3162 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3163 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."));
3167 image = m->klass->image;
3168 if (image->assembly->ref_only) {
3169 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."));
3173 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3174 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3178 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3182 intptr_t *lower_bounds;
3183 pcount = mono_array_length (params);
3184 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3185 /* Note: the synthetized array .ctors have int32 as argument type */
3186 for (i = 0; i < pcount; ++i)
3187 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3189 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3190 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3191 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3192 if (!mono_error_ok (&error)) {
3193 mono_error_set_pending_exception (&error);
3197 for (i = 0; i < mono_array_length (arr); ++i) {
3198 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3199 if (!mono_error_ok (&error)) {
3200 mono_error_set_pending_exception (&error);
3203 mono_array_setref_fast (arr, i, subarray);
3205 return (MonoObject*)arr;
3208 if (m->klass->rank == pcount) {
3209 /* Only lengths provided. */
3210 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3211 if (!mono_error_ok (&error)) {
3212 mono_error_set_pending_exception (&error);
3216 return (MonoObject*)arr;
3218 g_assert (pcount == (m->klass->rank * 2));
3219 /* The arguments are lower-bound-length pairs */
3220 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3222 for (i = 0; i < pcount / 2; ++i) {
3223 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3224 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3227 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3228 if (!mono_error_ok (&error)) {
3229 mono_error_set_pending_exception (&error);
3233 return (MonoObject*)arr;
3236 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3237 mono_error_set_pending_exception (&error);
3241 #ifndef DISABLE_REMOTING
3242 ICALL_EXPORT MonoObject *
3243 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3246 MonoDomain *domain = mono_object_domain (method);
3247 MonoMethod *m = method->method;
3248 MonoMethodSignature *sig = mono_method_signature (m);
3249 MonoArray *out_args;
3251 int i, j, outarg_count = 0;
3253 if (m->klass == mono_defaults.object_class) {
3254 if (!strcmp (m->name, "FieldGetter")) {
3255 MonoClass *k = this_arg->vtable->klass;
3259 /* If this is a proxy, then it must be a CBO */
3260 if (k == mono_defaults.transparent_proxy_class) {
3261 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3262 this_arg = tp->rp->unwrapped_server;
3263 g_assert (this_arg);
3264 k = this_arg->vtable->klass;
3267 name = mono_array_get (params, MonoString *, 1);
3268 str = mono_string_to_utf8_checked (name, &error);
3269 if (mono_error_set_pending_exception (&error))
3273 MonoClassField* field = mono_class_get_field_from_name (k, str);
3276 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3277 if (field_klass->valuetype) {
3278 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3279 if (mono_error_set_pending_exception (&error))
3282 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3284 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3285 if (mono_error_set_pending_exception (&error))
3287 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3288 mono_array_setref (out_args, 0, result);
3295 g_assert_not_reached ();
3297 } else if (!strcmp (m->name, "FieldSetter")) {
3298 MonoClass *k = this_arg->vtable->klass;
3304 /* If this is a proxy, then it must be a CBO */
3305 if (k == mono_defaults.transparent_proxy_class) {
3306 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3307 this_arg = tp->rp->unwrapped_server;
3308 g_assert (this_arg);
3309 k = this_arg->vtable->klass;
3312 name = mono_array_get (params, MonoString *, 1);
3313 str = mono_string_to_utf8_checked (name, &error);
3314 if (mono_error_set_pending_exception (&error))
3318 MonoClassField* field = mono_class_get_field_from_name (k, str);
3321 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3322 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3324 if (field_klass->valuetype) {
3325 size = mono_type_size (field->type, &align);
3326 g_assert (size == mono_class_value_size (field_klass, NULL));
3327 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3329 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3332 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3333 if (mono_error_set_pending_exception (&error))
3335 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3344 g_assert_not_reached ();
3349 for (i = 0; i < mono_array_length (params); i++) {
3350 if (sig->params [i]->byref)
3354 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3355 if (mono_error_set_pending_exception (&error))
3358 /* handle constructors only for objects already allocated */
3359 if (!strcmp (method->method->name, ".ctor"))
3360 g_assert (this_arg);
3362 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3363 g_assert (!method->method->klass->valuetype);
3364 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3365 if (mono_error_set_pending_exception (&error))
3368 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3369 if (sig->params [i]->byref) {
3371 arg = mono_array_get (params, gpointer, i);
3372 mono_array_setref (out_args, j, arg);
3377 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3384 read_enum_value (const char *mem, int type)
3387 case MONO_TYPE_BOOLEAN:
3389 return *(guint8*)mem;
3391 return *(gint8*)mem;
3392 case MONO_TYPE_CHAR:
3394 return read16 (mem);
3396 return (gint16) read16 (mem);
3398 return read32 (mem);
3400 return (gint32) read32 (mem);
3403 return read64 (mem);
3405 g_assert_not_reached ();
3411 write_enum_value (char *mem, int type, guint64 value)
3415 case MONO_TYPE_I1: {
3416 guint8 *p = (guint8*)mem;
3422 case MONO_TYPE_CHAR: {
3423 guint16 *p = (guint16 *)mem;
3428 case MONO_TYPE_I4: {
3429 guint32 *p = (guint32 *)mem;
3434 case MONO_TYPE_I8: {
3435 guint64 *p = (guint64 *)mem;
3440 g_assert_not_reached ();
3445 ICALL_EXPORT MonoObject *
3446 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3454 domain = mono_object_domain (enumType);
3455 enumc = mono_class_from_mono_type (enumType->type);
3457 mono_class_init_checked (enumc, &error);
3458 if (mono_error_set_pending_exception (&error))
3461 etype = mono_class_enum_basetype (enumc);
3463 res = mono_object_new_checked (domain, enumc, &error);
3464 if (mono_error_set_pending_exception (&error))
3466 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3471 ICALL_EXPORT MonoBoolean
3472 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3474 int size = mono_class_value_size (a->vtable->klass, NULL);
3475 guint64 a_val = 0, b_val = 0;
3477 memcpy (&a_val, mono_object_unbox (a), size);
3478 memcpy (&b_val, mono_object_unbox (b), size);
3480 return (a_val & b_val) == b_val;
3483 ICALL_EXPORT MonoObject *
3484 ves_icall_System_Enum_get_value (MonoObject *eobj)
3496 g_assert (eobj->vtable->klass->enumtype);
3498 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3499 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3500 if (mono_error_set_pending_exception (&error))
3502 dst = (char *)res + sizeof (MonoObject);
3503 src = (char *)eobj + sizeof (MonoObject);
3504 size = mono_class_value_size (enumc, NULL);
3506 memcpy (dst, src, size);
3511 ICALL_EXPORT MonoReflectionType *
3512 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3515 MonoReflectionType *ret;
3519 klass = mono_class_from_mono_type (type->type);
3520 mono_class_init_checked (klass, &error);
3521 if (mono_error_set_pending_exception (&error))
3524 etype = mono_class_enum_basetype (klass);
3526 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3530 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3531 mono_error_set_pending_exception (&error);
3537 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3539 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3540 gpointer odata = (char *)other + sizeof (MonoObject);
3541 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3542 g_assert (basetype);
3547 if (eobj->vtable->klass != other->vtable->klass)
3550 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3551 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3552 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3555 return me > other ? 1 : -1; \
3558 switch (basetype->type) {
3560 COMPARE_ENUM_VALUES (guint8);
3562 COMPARE_ENUM_VALUES (gint8);
3563 case MONO_TYPE_CHAR:
3565 COMPARE_ENUM_VALUES (guint16);
3567 COMPARE_ENUM_VALUES (gint16);
3569 COMPARE_ENUM_VALUES (guint32);
3571 COMPARE_ENUM_VALUES (gint32);
3573 COMPARE_ENUM_VALUES (guint64);
3575 COMPARE_ENUM_VALUES (gint64);
3579 #undef COMPARE_ENUM_VALUES
3580 /* indicates that the enum was of an unsupported unerlying type */
3585 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3587 gpointer data = (char *)eobj + sizeof (MonoObject);
3588 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3589 g_assert (basetype);
3591 switch (basetype->type) {
3592 case MONO_TYPE_I1: {
3593 gint8 value = *((gint8*)data);
3594 return ((int)value ^ (int)value << 8);
3597 return *((guint8*)data);
3598 case MONO_TYPE_CHAR:
3600 return *((guint16*)data);
3602 case MONO_TYPE_I2: {
3603 gint16 value = *((gint16*)data);
3604 return ((int)(guint16)value | (((int)value) << 16));
3607 return *((guint32*)data);
3609 return *((gint32*)data);
3611 case MONO_TYPE_I8: {
3612 gint64 value = *((gint64*)data);
3613 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3616 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3621 ICALL_EXPORT MonoBoolean
3622 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3625 MonoDomain *domain = mono_object_domain (type);
3626 MonoClass *enumc = mono_class_from_mono_type (type->type);
3627 guint j = 0, nvalues;
3629 MonoClassField *field;
3631 guint64 field_value, previous_value = 0;
3632 gboolean sorted = TRUE;
3634 mono_class_init_checked (enumc, &error);
3635 if (mono_error_set_pending_exception (&error))
3639 if (!enumc->enumtype) {
3640 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3644 base_type = mono_class_enum_basetype (enumc)->type;
3646 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3647 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3648 if (mono_error_set_pending_exception (&error))
3650 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3651 if (mono_error_set_pending_exception (&error))
3655 while ((field = mono_class_get_fields (enumc, &iter))) {
3657 MonoTypeEnum def_type;
3659 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3661 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3663 if (mono_field_is_deleted (field))
3665 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3667 p = mono_class_get_field_default_value (field, &def_type);
3668 /* len = */ mono_metadata_decode_blob_size (p, &p);
3670 field_value = read_enum_value (p, base_type);
3671 mono_array_set (*values, guint64, j, field_value);
3673 if (previous_value > field_value)
3676 previous_value = field_value;
3684 BFLAGS_IgnoreCase = 1,
3685 BFLAGS_DeclaredOnly = 2,
3686 BFLAGS_Instance = 4,
3688 BFLAGS_Public = 0x10,
3689 BFLAGS_NonPublic = 0x20,
3690 BFLAGS_FlattenHierarchy = 0x40,
3691 BFLAGS_InvokeMethod = 0x100,
3692 BFLAGS_CreateInstance = 0x200,
3693 BFLAGS_GetField = 0x400,
3694 BFLAGS_SetField = 0x800,
3695 BFLAGS_GetProperty = 0x1000,
3696 BFLAGS_SetProperty = 0x2000,
3697 BFLAGS_ExactBinding = 0x10000,
3698 BFLAGS_SuppressChangeType = 0x20000,
3699 BFLAGS_OptionalParamBinding = 0x40000
3702 ICALL_EXPORT GPtrArray*
3703 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3706 MonoClass *startklass, *klass;
3709 int (*compare_func) (const char *s1, const char *s2) = NULL;
3710 MonoClassField *field;
3712 if (type->type->byref) {
3713 return g_ptr_array_new ();
3716 mono_error_init (&error);
3718 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3720 klass = startklass = mono_class_from_mono_type (type->type);
3722 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3725 if (mono_class_has_failure (klass)) {
3726 mono_error_set_for_class_failure (&error, klass);
3731 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3732 guint32 flags = mono_field_get_flags (field);
3734 if (mono_field_is_deleted_with_flags (field, flags))
3736 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3737 if (bflags & BFLAGS_Public)
3739 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3740 if (bflags & BFLAGS_NonPublic) {
3747 if (flags & FIELD_ATTRIBUTE_STATIC) {
3748 if (bflags & BFLAGS_Static)
3749 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3752 if (bflags & BFLAGS_Instance)
3759 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3762 g_ptr_array_add (ptr_array, field);
3764 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3770 g_ptr_array_free (ptr_array, TRUE);
3771 mono_error_set_pending_exception (&error);
3776 method_nonpublic (MonoMethod* method, gboolean start_klass)
3778 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3779 case METHOD_ATTRIBUTE_ASSEM:
3780 return (start_klass || mono_defaults.generic_ilist_class);
3781 case METHOD_ATTRIBUTE_PRIVATE:
3783 case METHOD_ATTRIBUTE_PUBLIC:
3791 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3794 MonoClass *startklass;
3798 /*FIXME, use MonoBitSet*/
3799 guint32 method_slots_default [8];
3800 guint32 *method_slots = NULL;
3801 int (*compare_func) (const char *s1, const char *s2) = NULL;
3803 array = g_ptr_array_new ();
3805 mono_error_init (error);
3808 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3810 /* An optimization for calls made from Delegate:CreateDelegate () */
3811 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3812 method = mono_get_delegate_invoke (klass);
3815 g_ptr_array_add (array, method);
3819 mono_class_setup_methods (klass);
3820 mono_class_setup_vtable (klass);
3821 if (mono_class_has_failure (klass))
3824 if (is_generic_parameter (&klass->byval_arg))
3825 nslots = mono_class_get_vtable_size (klass->parent);
3827 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3828 if (nslots >= sizeof (method_slots_default) * 8) {
3829 method_slots = g_new0 (guint32, nslots / 32 + 1);
3831 method_slots = method_slots_default;
3832 memset (method_slots, 0, sizeof (method_slots_default));
3835 mono_class_setup_methods (klass);
3836 mono_class_setup_vtable (klass);
3837 if (mono_class_has_failure (klass))
3841 while ((method = mono_class_get_methods (klass, &iter))) {
3843 if (method->slot != -1) {
3844 g_assert (method->slot < nslots);
3845 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3847 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3848 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3851 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3853 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3854 if (bflags & BFLAGS_Public)
3856 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3862 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3863 if (bflags & BFLAGS_Static)
3864 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3867 if (bflags & BFLAGS_Instance)
3875 if (compare_func (name, method->name))
3880 g_ptr_array_add (array, method);
3882 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3884 if (method_slots != method_slots_default)
3885 g_free (method_slots);
3890 if (method_slots != method_slots_default)
3891 g_free (method_slots);
3892 g_ptr_array_free (array, TRUE);
3894 g_assert (mono_class_has_failure (klass));
3895 mono_error_set_for_class_failure (error, klass);
3899 ICALL_EXPORT GPtrArray*
3900 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3903 GPtrArray *method_array;
3906 klass = mono_class_from_mono_type (type->type);
3907 if (type->type->byref) {
3908 return g_ptr_array_new ();
3911 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3912 mono_error_set_pending_exception (&error);
3913 return method_array;
3916 ICALL_EXPORT GPtrArray*
3917 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3919 MonoClass *startklass, *klass;
3922 gpointer iter = NULL;
3923 GPtrArray *res_array;
3926 if (type->type->byref) {
3927 return g_ptr_array_new ();
3930 klass = startklass = mono_class_from_mono_type (type->type);
3932 mono_class_setup_methods (klass);
3933 if (mono_class_has_failure (klass)) {
3934 mono_error_init (&error);
3935 mono_error_set_for_class_failure (&error, klass);
3936 mono_error_set_pending_exception (&error);
3940 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3943 while ((method = mono_class_get_methods (klass, &iter))) {
3945 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3947 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3948 if (bflags & BFLAGS_Public)
3951 if (bflags & BFLAGS_NonPublic)
3957 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3958 if (bflags & BFLAGS_Static)
3959 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3962 if (bflags & BFLAGS_Instance)
3968 g_ptr_array_add (res_array, method);
3975 property_hash (gconstpointer data)
3977 MonoProperty *prop = (MonoProperty*)data;
3979 return g_str_hash (prop->name);
3983 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
3985 if (method1->slot != -1 && method1->slot == method2->slot)
3988 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
3989 if (method1->is_inflated)
3990 method1 = ((MonoMethodInflated*) method1)->declaring;
3991 if (method2->is_inflated)
3992 method2 = ((MonoMethodInflated*) method2)->declaring;
3995 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3999 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4001 // Properties are hide-by-name-and-signature
4002 if (!g_str_equal (prop1->name, prop2->name))
4005 /* If we see a property in a generic method, we want to
4006 compare the generic signatures, not the inflated signatures
4007 because we might conflate two properties that were
4011 public T this[T t] { getter { return t; } } // method 1
4012 public U this[U u] { getter { return u; } } // method 2
4015 If we see int Foo<int,int>::Item[int] we need to know if
4016 the indexer came from method 1 or from method 2, and we
4017 shouldn't conflate them. (Bugzilla 36283)
4019 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4022 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4029 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4034 return method_nonpublic (accessor, start_klass);
4037 ICALL_EXPORT GPtrArray*
4038 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4041 MonoClass *startklass, *klass;
4046 int (*compare_func) (const char *s1, const char *s2) = NULL;
4048 GHashTable *properties = NULL;
4049 GPtrArray *res_array;
4051 if (type->type->byref) {
4052 return g_ptr_array_new ();
4055 mono_error_init (&error);
4057 klass = startklass = mono_class_from_mono_type (type->type);
4059 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4061 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4063 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4065 mono_class_setup_methods (klass);
4066 mono_class_setup_vtable (klass);
4067 if (mono_class_has_failure (klass)) {
4068 mono_error_set_for_class_failure (&error, klass);
4073 while ((prop = mono_class_get_properties (klass, &iter))) {
4079 flags = method->flags;
4082 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4083 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4084 if (bflags & BFLAGS_Public)
4086 } else if (bflags & BFLAGS_NonPublic) {
4087 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4088 property_accessor_nonpublic(prop->set, startklass == klass)) {
4095 if (flags & METHOD_ATTRIBUTE_STATIC) {
4096 if (bflags & BFLAGS_Static)
4097 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4100 if (bflags & BFLAGS_Instance)
4108 if (propname != NULL && compare_func (propname, prop->name))
4111 if (g_hash_table_lookup (properties, prop))
4114 g_ptr_array_add (res_array, prop);
4116 g_hash_table_insert (properties, prop, prop);
4118 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4121 g_hash_table_destroy (properties);
4128 g_hash_table_destroy (properties);
4129 g_ptr_array_free (res_array, TRUE);
4131 mono_error_set_pending_exception (&error);
4137 event_hash (gconstpointer data)
4139 MonoEvent *event = (MonoEvent*)data;
4141 return g_str_hash (event->name);
4145 event_equal (MonoEvent *event1, MonoEvent *event2)
4147 // Events are hide-by-name
4148 return g_str_equal (event1->name, event2->name);
4151 ICALL_EXPORT GPtrArray*
4152 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4155 MonoClass *startklass, *klass;
4160 int (*compare_func) (const char *s1, const char *s2) = NULL;
4161 GHashTable *events = NULL;
4162 GPtrArray *res_array;
4164 if (type->type->byref) {
4165 return g_ptr_array_new ();
4168 mono_error_init (&error);
4170 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4172 res_array = g_ptr_array_sized_new (4);
4174 klass = startklass = mono_class_from_mono_type (type->type);
4176 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4178 mono_class_setup_methods (klass);
4179 mono_class_setup_vtable (klass);
4180 if (mono_class_has_failure (klass)) {
4181 mono_error_set_for_class_failure (&error, klass);
4186 while ((event = mono_class_get_events (klass, &iter))) {
4188 method = event->add;
4190 method = event->remove;
4192 method = event->raise;
4194 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4195 if (bflags & BFLAGS_Public)
4197 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4198 if (bflags & BFLAGS_NonPublic)
4203 if (bflags & BFLAGS_NonPublic)
4209 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4210 if (bflags & BFLAGS_Static)
4211 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4214 if (bflags & BFLAGS_Instance)
4219 if (bflags & BFLAGS_Instance)
4224 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4227 if (g_hash_table_lookup (events, event))
4230 g_ptr_array_add (res_array, event);
4232 g_hash_table_insert (events, event, event);
4234 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4237 g_hash_table_destroy (events);
4243 g_hash_table_destroy (events);
4245 g_ptr_array_free (res_array, TRUE);
4247 mono_error_set_pending_exception (&error);
4251 ICALL_EXPORT GPtrArray *
4252 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4258 GPtrArray *res_array;
4260 if (type->type->byref) {
4261 return g_ptr_array_new ();
4264 klass = mono_class_from_mono_type (type->type);
4267 * If a nested type is generic, return its generic type definition.
4268 * Note that this means that the return value is essentially the set
4269 * of nested types of the generic type definition of @klass.
4271 * A note in MSDN claims that a generic type definition can have
4272 * nested types that aren't generic. In any case, the container of that
4273 * nested type would be the generic type definition.
4275 if (klass->generic_class)
4276 klass = klass->generic_class->container_class;
4278 res_array = g_ptr_array_new ();
4281 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4283 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4284 if (bflags & BFLAGS_Public)
4287 if (bflags & BFLAGS_NonPublic)
4293 if (str != NULL && strcmp (nested->name, str))
4296 g_ptr_array_add (res_array, &nested->byval_arg);
4302 ICALL_EXPORT MonoReflectionType*
4303 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4306 MonoReflectionType *ret;
4308 MonoType *type = NULL;
4309 MonoTypeNameParse info;
4310 gboolean type_resolve;
4312 /* On MS.NET, this does not fire a TypeResolve event */
4313 type_resolve = TRUE;
4314 str = mono_string_to_utf8_checked (name, &error);
4315 if (mono_error_set_pending_exception (&error))
4317 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4318 if (!mono_reflection_parse_type (str, &info)) {
4320 mono_reflection_free_type_info (&info);
4322 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4325 /*g_print ("failed parse\n");*/
4329 if (info.assembly.name) {
4331 mono_reflection_free_type_info (&info);
4333 /* 1.0 and 2.0 throw different exceptions */
4334 if (mono_defaults.generic_ilist_class)
4335 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4337 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4343 if (module != NULL) {
4344 if (module->image) {
4345 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4346 if (!is_ok (&error)) {
4348 mono_reflection_free_type_info (&info);
4349 mono_error_set_pending_exception (&error);
4356 if (assembly_is_dynamic (assembly->assembly)) {
4357 /* Enumerate all modules */
4358 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4362 if (abuilder->modules) {
4363 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4364 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4365 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4366 if (!is_ok (&error)) {
4368 mono_reflection_free_type_info (&info);
4369 mono_error_set_pending_exception (&error);
4377 if (!type && abuilder->loaded_modules) {
4378 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4379 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4380 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4381 if (!is_ok (&error)) {
4383 mono_reflection_free_type_info (&info);
4384 mono_error_set_pending_exception (&error);
4393 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4394 if (!is_ok (&error)) {
4396 mono_reflection_free_type_info (&info);
4397 mono_error_set_pending_exception (&error);
4402 mono_reflection_free_type_info (&info);
4404 MonoException *e = NULL;
4407 e = mono_get_exception_type_load (name, NULL);
4410 mono_set_pending_exception (e);
4414 if (type->type == MONO_TYPE_CLASS) {
4415 MonoClass *klass = mono_type_get_class (type);
4417 /* need to report exceptions ? */
4418 if (throwOnError && mono_class_has_failure (klass)) {
4419 /* report SecurityException (or others) that occured when loading the assembly */
4420 MonoException *exc = mono_class_get_exception_for_failure (klass);
4421 mono_set_pending_exception (exc);
4426 /* g_print ("got it\n"); */
4427 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4428 mono_error_set_pending_exception (&error);
4434 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4437 gchar *shadow_ini_file;
4440 /* Check for shadow-copied assembly */
4441 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4442 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4444 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4445 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4451 g_free (shadow_ini_file);
4452 if (content != NULL) {
4455 *filename = content;
4462 ICALL_EXPORT MonoString *
4463 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4465 MonoDomain *domain = mono_object_domain (assembly);
4466 MonoAssembly *mass = assembly->assembly;
4467 MonoString *res = NULL;
4472 if (g_path_is_absolute (mass->image->name)) {
4473 absolute = g_strdup (mass->image->name);
4474 dirname = g_path_get_dirname (absolute);
4476 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4477 dirname = g_strdup (mass->basedir);
4480 replace_shadow_path (domain, dirname, &absolute);
4485 for (i = strlen (absolute) - 1; i >= 0; i--)
4486 if (absolute [i] == '\\')
4491 uri = g_filename_to_uri (absolute, NULL, NULL);
4493 const char *prepend = "file://";
4495 if (*absolute == '/' && *(absolute + 1) == '/') {
4498 prepend = "file:///";
4501 uri = g_strconcat (prepend, absolute, NULL);
4505 res = mono_string_new (domain, uri);
4512 ICALL_EXPORT MonoBoolean
4513 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4515 MonoAssembly *mass = assembly->assembly;
4517 return mass->in_gac;
4520 ICALL_EXPORT MonoReflectionAssembly*
4521 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4526 MonoImageOpenStatus status;
4527 MonoReflectionAssembly* result = NULL;
4529 name = mono_string_to_utf8_checked (mname, &error);
4530 if (mono_error_set_pending_exception (&error))
4532 res = mono_assembly_load_with_partial_name (name, &status);
4538 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4540 mono_error_set_pending_exception (&error);
4544 ICALL_EXPORT MonoStringHandle
4545 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4547 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4548 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4549 return mono_string_new_handle (domain, mono_image_get_filename (assembly->image), error);
4552 ICALL_EXPORT MonoBoolean
4553 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4555 return assembly->assembly->ref_only;
4558 ICALL_EXPORT MonoStringHandle
4559 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssemblyHandle refassembly, MonoError *error)
4561 MonoDomain *domain = MONO_HANDLE_DOMAIN (refassembly);
4562 MonoAssembly *assembly = MONO_HANDLE_RAW (refassembly)->assembly;
4564 return mono_string_new_handle (domain, assembly->image->version, error);
4567 ICALL_EXPORT MonoReflectionMethod*
4568 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4571 MonoReflectionMethod *res = NULL;
4574 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4578 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4579 if (!mono_error_ok (&error))
4582 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4585 if (!mono_error_ok (&error))
4586 mono_error_set_pending_exception (&error);
4590 ICALL_EXPORT MonoReflectionModule*
4591 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4594 MonoReflectionModule *result = NULL;
4595 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4596 if (!mono_error_ok (&error))
4597 mono_error_set_pending_exception (&error);
4601 ICALL_EXPORT MonoArray*
4602 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4605 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4606 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4607 if (mono_error_set_pending_exception (&error))
4612 for (i = 0; i < table->rows; ++i) {
4613 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4614 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4619 ICALL_EXPORT MonoStringHandle
4620 ves_icall_System_Reflection_Assembly_GetAotId (MonoError *error)
4623 guint8 aotid_sum = 0;
4624 MonoDomain* domain = mono_domain_get ();
4626 if (!domain->entry_assembly || !domain->entry_assembly->image)
4629 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4631 for (i = 0; i < 16; ++i)
4632 aotid_sum |= (*aotid)[i];
4637 gchar *guid = mono_guid_to_string((guint8*) aotid);
4638 MonoStringHandle res = mono_string_new_handle (domain, guid, error);
4644 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4646 static MonoMethod *create_version = NULL;
4650 mono_error_init (error);
4653 if (!create_version) {
4654 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4655 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4656 g_assert (create_version);
4657 mono_method_desc_free (desc);
4663 args [3] = &revision;
4664 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4665 return_val_if_nok (error, NULL);
4667 mono_runtime_invoke_checked (create_version, result, args, error);
4668 return_val_if_nok (error, NULL);
4673 ICALL_EXPORT MonoArray*
4674 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4678 MonoDomain *domain = mono_object_domain (assembly);
4680 static MonoMethod *create_culture = NULL;
4681 MonoImage *image = assembly->assembly->image;
4685 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4688 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4689 if (mono_error_set_pending_exception (&error))
4693 if (count > 0 && !create_culture) {
4694 MonoMethodDesc *desc = mono_method_desc_new (
4695 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4696 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4697 g_assert (create_culture);
4698 mono_method_desc_free (desc);
4701 for (i = 0; i < count; i++) {
4702 MonoObject *version;
4703 MonoReflectionAssemblyName *aname;
4704 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4706 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4708 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4709 domain, mono_class_get_assembly_name_class (), &error);
4710 if (mono_error_set_pending_exception (&error))
4713 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4715 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4716 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4717 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4718 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4719 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4720 aname->versioncompat = 1; /* SameMachine (default) */
4721 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4723 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4724 if (mono_error_set_pending_exception (&error))
4727 MONO_OBJECT_SETREF (aname, version, version);
4729 if (create_culture) {
4731 MonoBoolean assembly_ref = 1;
4732 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4733 args [1] = &assembly_ref;
4735 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4736 if (mono_error_set_pending_exception (&error))
4739 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4742 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4743 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4744 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4746 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4747 /* public key token isn't copied - the class library will
4748 automatically generate it from the public key if required */
4749 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4750 if (mono_error_set_pending_exception (&error))
4753 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4754 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4756 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4757 if (mono_error_set_pending_exception (&error))
4760 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4761 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4764 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4765 if (mono_error_set_pending_exception (&error))
4768 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4771 /* note: this function doesn't return the codebase on purpose (i.e. it can
4772 be used under partial trust as path information isn't present). */
4774 mono_array_setref (result, i, aname);
4779 /* move this in some file in mono/util/ */
4781 g_concat_dir_and_file (const char *dir, const char *file)
4783 g_return_val_if_fail (dir != NULL, NULL);
4784 g_return_val_if_fail (file != NULL, NULL);
4787 * If the directory name doesn't have a / on the end, we need
4788 * to add one so we get a proper path to the file
4790 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4791 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4793 return g_strconcat (dir, file, NULL);
4797 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4800 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4802 guint32 cols [MONO_MANIFEST_SIZE];
4803 guint32 impl, file_idx;
4807 char *n = mono_string_to_utf8_checked (name, &error);
4808 if (mono_error_set_pending_exception (&error))
4811 for (i = 0; i < table->rows; ++i) {
4812 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4813 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4814 if (strcmp (val, n) == 0)
4818 if (i == table->rows)
4821 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4824 * this code should only be called after obtaining the
4825 * ResourceInfo and handling the other cases.
4827 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4828 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4830 module = mono_image_load_file_for_image_checked (assembly->assembly->image, file_idx, &error);
4831 if (mono_error_set_pending_exception (&error) || !module)
4835 module = assembly->assembly->image;
4838 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4839 if (mono_error_set_pending_exception (&error))
4841 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4843 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4846 ICALL_EXPORT gboolean
4847 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4850 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4852 guint32 cols [MONO_MANIFEST_SIZE];
4853 guint32 file_cols [MONO_FILE_SIZE];
4857 n = mono_string_to_utf8_checked (name, &error);
4858 if (mono_error_set_pending_exception (&error))
4860 for (i = 0; i < table->rows; ++i) {
4861 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4862 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4863 if (strcmp (val, n) == 0)
4867 if (i == table->rows)
4870 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4871 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4874 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4875 case MONO_IMPLEMENTATION_FILE:
4876 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4877 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4878 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4879 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4880 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4881 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4884 info->location = RESOURCE_LOCATION_EMBEDDED;
4887 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4888 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4889 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4890 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4891 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4892 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4894 mono_set_pending_exception (ex);
4897 MonoReflectionAssembly *assm_obj;
4898 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4900 mono_error_set_pending_exception (&error);
4903 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4905 /* Obtain info recursively */
4906 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4907 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4910 case MONO_IMPLEMENTATION_EXP_TYPE:
4911 g_assert_not_reached ();
4919 ICALL_EXPORT MonoObject*
4920 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4923 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4924 MonoArray *result = NULL;
4929 /* check hash if needed */
4931 n = mono_string_to_utf8_checked (name, &error);
4932 if (mono_error_set_pending_exception (&error))
4935 for (i = 0; i < table->rows; ++i) {
4936 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4937 if (strcmp (val, n) == 0) {
4940 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4941 fn = mono_string_new (mono_object_domain (assembly), n);
4943 return (MonoObject*)fn;
4951 for (i = 0; i < table->rows; ++i) {
4952 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4956 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
4957 if (mono_error_set_pending_exception (&error))
4962 for (i = 0; i < table->rows; ++i) {
4963 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4964 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4965 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4966 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4971 return (MonoObject*)result;
4974 ICALL_EXPORT MonoArray*
4975 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4978 MonoDomain *domain = mono_domain_get();
4981 int i, j, file_count = 0;
4982 MonoImage **modules;
4983 guint32 module_count, real_module_count;
4984 MonoTableInfo *table;
4985 guint32 cols [MONO_FILE_SIZE];
4986 MonoImage *image = assembly->assembly->image;
4988 g_assert (image != NULL);
4989 g_assert (!assembly_is_dynamic (assembly->assembly));
4991 table = &image->tables [MONO_TABLE_FILE];
4992 file_count = table->rows;
4994 modules = image->modules;
4995 module_count = image->module_count;
4997 real_module_count = 0;
4998 for (i = 0; i < module_count; ++i)
5000 real_module_count ++;
5002 klass = mono_class_get_module_class ();
5003 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5004 if (mono_error_set_pending_exception (&error))
5007 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5008 if (mono_error_set_pending_exception (&error))
5011 mono_array_setref (res, 0, image_obj);
5013 for (i = 0; i < module_count; ++i)
5015 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5016 if (mono_error_set_pending_exception (&error))
5018 mono_array_setref (res, j, rm);
5022 for (i = 0; i < file_count; ++i, ++j) {
5023 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5024 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5025 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5026 if (mono_error_set_pending_exception (&error))
5028 mono_array_setref (res, j, rm);
5031 MonoImage *m = mono_image_load_file_for_image_checked (image, i + 1, &error);
5032 if (mono_error_set_pending_exception (&error))
5035 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5036 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5039 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5040 if (mono_error_set_pending_exception (&error))
5042 mono_array_setref (res, j, rm);
5049 ICALL_EXPORT MonoReflectionMethod*
5050 ves_icall_GetCurrentMethod (void)
5052 MonoReflectionMethod *res = NULL;
5055 MonoMethod *m = mono_method_get_last_managed ();
5058 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5062 while (m->is_inflated)
5063 m = ((MonoMethodInflated*)m)->declaring;
5065 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5066 mono_error_set_pending_exception (&error);
5072 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5075 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5078 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5079 //method is inflated, we should inflate it on the other class
5080 MonoGenericContext ctx;
5081 ctx.method_inst = inflated->context.method_inst;
5082 ctx.class_inst = inflated->context.class_inst;
5083 if (klass->generic_class)
5084 ctx.class_inst = klass->generic_class->context.class_inst;
5085 else if (klass->generic_container)
5086 ctx.class_inst = klass->generic_container->context.class_inst;
5087 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5088 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5092 mono_class_setup_methods (method->klass);
5093 if (mono_class_has_failure (method->klass))
5095 for (i = 0; i < method->klass->method.count; ++i) {
5096 if (method->klass->methods [i] == method) {
5101 mono_class_setup_methods (klass);
5102 if (mono_class_has_failure (klass))
5104 g_assert (offset >= 0 && offset < klass->method.count);
5105 return klass->methods [offset];
5108 ICALL_EXPORT MonoReflectionMethod*
5109 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5111 MonoReflectionMethod *res = NULL;
5114 if (type && generic_check) {
5115 klass = mono_class_from_mono_type (type);
5116 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5119 if (method->klass != klass) {
5120 method = mono_method_get_equivalent_method (method, klass);
5125 klass = mono_class_from_mono_type (type);
5127 klass = method->klass;
5128 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5129 mono_error_set_pending_exception (&error);
5133 ICALL_EXPORT MonoReflectionMethodBody*
5134 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5137 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5138 mono_error_set_pending_exception (&error);
5142 ICALL_EXPORT MonoReflectionAssembly*
5143 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5146 MonoReflectionAssembly *result;
5147 MonoMethod *dest = NULL;
5149 mono_stack_walk_no_il (get_executing, &dest);
5151 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5153 mono_error_set_pending_exception (&error);
5158 ICALL_EXPORT MonoReflectionAssembly*
5159 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5162 MonoReflectionAssembly *result;
5163 MonoDomain* domain = mono_domain_get ();
5165 if (!domain->entry_assembly)
5168 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5170 mono_error_set_pending_exception (&error);
5174 ICALL_EXPORT MonoReflectionAssembly*
5175 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5180 MonoReflectionAssembly *result;
5183 mono_stack_walk_no_il (get_executing, &dest);
5185 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5189 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5192 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5194 mono_error_set_pending_exception (&error);
5198 ICALL_EXPORT MonoStringHandle
5199 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5200 gboolean assembly_qualified, MonoError *error)
5202 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5203 MonoType *type = MONO_HANDLE_RAW (object)->type;
5204 MonoTypeNameFormat format;
5205 MonoStringHandle res;
5209 format = assembly_qualified ?
5210 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5211 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5213 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5215 name = mono_type_get_name_full (type, format);
5217 return NULL_HANDLE_STRING;
5219 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5221 return NULL_HANDLE_STRING;
5224 res = mono_string_new_handle (domain, name, error);
5231 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5234 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5236 mono_class_init_checked (klass, &error);
5237 mono_error_set_pending_exception (&error);
5238 return mono_security_core_clr_class_level (klass);
5242 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5244 MonoClassField *field = rfield->field;
5245 return mono_security_core_clr_field_level (field, TRUE);
5249 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5251 MonoMethod *method = rfield->method;
5252 return mono_security_core_clr_method_level (method, TRUE);
5256 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)
5258 static MonoMethod *create_culture = NULL;
5262 const char *pkey_ptr;
5264 MonoBoolean assembly_ref = 0;
5266 mono_error_init (error);
5268 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5269 aname->major = name->major;
5270 aname->minor = name->minor;
5271 aname->build = name->build;
5272 aname->flags = name->flags;
5273 aname->revision = name->revision;
5274 aname->hashalg = name->hash_alg;
5275 aname->versioncompat = 1; /* SameMachine (default) */
5276 aname->processor_architecture = name->arch;
5278 if (by_default_version) {
5279 MonoObject *version;
5281 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5282 return_if_nok (error);
5284 MONO_OBJECT_SETREF (aname, version, version);
5288 if (absolute != NULL && *absolute != '\0') {
5289 const gchar *prepend = "file://";
5292 codebase = g_strdup (absolute);
5297 for (i = strlen (codebase) - 1; i >= 0; i--)
5298 if (codebase [i] == '\\')
5301 if (*codebase == '/' && *(codebase + 1) == '/') {
5304 prepend = "file:///";
5308 result = g_strconcat (prepend, codebase, NULL);
5314 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5318 if (!create_culture) {
5319 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5320 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5321 g_assert (create_culture);
5322 mono_method_desc_free (desc);
5325 if (name->culture) {
5326 args [0] = mono_string_new (domain, name->culture);
5327 args [1] = &assembly_ref;
5329 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5330 return_if_nok (error);
5332 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5335 if (name->public_key) {
5336 pkey_ptr = (char*)name->public_key;
5337 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5339 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5340 return_if_nok (error);
5341 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5342 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5343 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5344 } else if (default_publickey) {
5345 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5346 return_if_nok (error);
5347 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5348 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5351 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5352 if (name->public_key_token [0]) {
5356 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5357 return_if_nok (error);
5359 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5360 p = mono_array_addr (keyToken, char, 0);
5362 for (i = 0, j = 0; i < 8; i++) {
5363 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5364 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5367 } else if (default_token) {
5368 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5369 return_if_nok (error);
5370 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5374 ICALL_EXPORT MonoString *
5375 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5377 MonoDomain *domain = mono_object_domain (assembly);
5378 MonoAssembly *mass = assembly->assembly;
5382 name = mono_stringify_assembly_name (&mass->aname);
5383 res = mono_string_new (domain, name);
5389 ICALL_EXPORT MonoAssemblyName *
5390 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5392 return &mass->aname;
5396 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5400 MonoImageOpenStatus status = MONO_IMAGE_OK;
5403 MonoAssemblyName name;
5406 filename = mono_string_to_utf8_checked (fname, &error);
5407 if (mono_error_set_pending_exception (&error))
5410 dirname = g_path_get_dirname (filename);
5411 replace_shadow_path (mono_domain_get (), dirname, &filename);
5414 image = mono_image_open (filename, &status);
5420 if (status == MONO_IMAGE_IMAGE_INVALID)
5421 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5423 exc = mono_get_exception_file_not_found2 (NULL, fname);
5424 mono_set_pending_exception (exc);
5428 res = mono_assembly_fill_assembly_name (image, &name);
5430 mono_image_close (image);
5432 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5436 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5437 mono_error_set_pending_exception (&error);
5439 mono_image_close (image);
5443 ICALL_EXPORT MonoBoolean
5444 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5445 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5447 MonoBoolean result = FALSE;
5448 MonoDeclSecurityEntry entry;
5450 /* SecurityAction.RequestMinimum */
5451 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5452 *minimum = entry.blob;
5453 *minLength = entry.size;
5456 /* SecurityAction.RequestOptional */
5457 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5458 *optional = entry.blob;
5459 *optLength = entry.size;
5462 /* SecurityAction.RequestRefuse */
5463 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5464 *refused = entry.blob;
5465 *refLength = entry.size;
5473 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5475 guint32 attrs, visibility;
5477 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5478 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5479 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5482 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5488 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5490 MonoReflectionType *rt;
5493 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5496 mono_error_init (error);
5498 /* we start the count from 1 because we skip the special type <Module> */
5501 for (i = 1; i < tdef->rows; ++i) {
5502 if (mono_module_type_is_visible (tdef, image, i + 1))
5506 count = tdef->rows - 1;
5508 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5509 return_val_if_nok (error, NULL);
5510 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5511 return_val_if_nok (error, NULL);
5513 for (i = 1; i < tdef->rows; ++i) {
5514 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5515 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5518 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5519 return_val_if_nok (error, NULL);
5521 mono_array_setref (res, count, rt);
5523 MonoException *ex = mono_error_convert_to_exception (error);
5524 mono_array_setref (*exceptions, count, ex);
5533 ICALL_EXPORT MonoArray*
5534 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5537 MonoArray *res = NULL;
5538 MonoArray *exceptions = NULL;
5539 MonoImage *image = NULL;
5540 MonoTableInfo *table = NULL;
5543 int i, len, ex_count;
5545 domain = mono_object_domain (assembly);
5547 g_assert (!assembly_is_dynamic (assembly->assembly));
5548 image = assembly->assembly->image;
5549 table = &image->tables [MONO_TABLE_FILE];
5550 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5551 if (mono_error_set_pending_exception (&error))
5554 /* Append data from all modules in the assembly */
5555 for (i = 0; i < table->rows; ++i) {
5556 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5557 MonoImage *loaded_image = mono_assembly_load_module_checked (image->assembly, i + 1, &error);
5558 if (mono_error_set_pending_exception (&error))
5564 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5565 if (mono_error_set_pending_exception (&error))
5569 /* Append the new types to the end of the array */
5570 if (mono_array_length (res2) > 0) {
5572 MonoArray *res3, *ex3;
5574 len1 = mono_array_length (res);
5575 len2 = mono_array_length (res2);
5577 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5578 if (mono_error_set_pending_exception (&error))
5580 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5581 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5584 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5585 if (mono_error_set_pending_exception (&error))
5587 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5588 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5595 /* the ReflectionTypeLoadException must have all the types (Types property),
5596 * NULL replacing types which throws an exception. The LoaderException must
5597 * contain all exceptions for NULL items.
5600 len = mono_array_length (res);
5603 for (i = 0; i < len; i++) {
5604 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5608 klass = mono_type_get_class (t->type);
5609 if ((klass != NULL) && mono_class_has_failure (klass)) {
5610 /* keep the class in the list */
5611 list = g_list_append (list, klass);
5612 /* and replace Type with NULL */
5613 mono_array_setref (res, i, NULL);
5620 if (list || ex_count) {
5622 MonoException *exc = NULL;
5623 MonoArray *exl = NULL;
5624 int j, length = g_list_length (list) + ex_count;
5626 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5627 if (mono_error_set_pending_exception (&error)) {
5631 /* Types for which mono_class_get_checked () succeeded */
5632 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5633 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5634 mono_array_setref (exl, i, exc);
5636 /* Types for which it don't */
5637 for (j = 0; j < mono_array_length (exceptions); ++j) {
5638 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5640 g_assert (i < length);
5641 mono_array_setref (exl, i, exc);
5648 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5649 if (!is_ok (&error)) {
5650 mono_error_set_pending_exception (&error);
5653 mono_set_pending_exception (exc);
5661 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5663 mono_assembly_name_free (aname);
5666 ICALL_EXPORT gboolean
5667 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5669 *is_version_definited = *is_token_defined = FALSE;
5671 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5674 ICALL_EXPORT MonoReflectionType*
5675 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5678 MonoReflectionType *ret;
5679 MonoDomain *domain = mono_object_domain (module);
5682 g_assert (module->image);
5684 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5685 /* These images do not have a global type */
5688 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5689 if (!mono_error_ok (&error)) {
5690 mono_error_set_pending_exception (&error);
5694 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5695 if (!mono_error_ok (&error)) {
5696 mono_error_set_pending_exception (&error);
5704 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5706 /*if (module->image)
5707 mono_image_close (module->image);*/
5710 ICALL_EXPORT MonoStringHandle
5711 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5713 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5714 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5717 return mono_string_new_handle (domain, image->guid, error);
5720 ICALL_EXPORT gpointer
5721 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5724 if (module->image && module->image->is_module_handle)
5725 return module->image->raw_data;
5728 return (gpointer) (-1);
5732 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5734 if (image_is_dynamic (image)) {
5735 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5736 *pe_kind = dyn->pe_kind;
5737 *machine = dyn->machine;
5740 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5741 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5746 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5748 return (image->md_version_major << 16) | (image->md_version_minor);
5751 ICALL_EXPORT MonoArray*
5752 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5755 MonoArray *exceptions;
5758 if (!module->image) {
5759 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5760 mono_error_set_pending_exception (&error);
5765 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5766 if (mono_error_set_pending_exception (&error))
5769 for (i = 0; i < mono_array_length (exceptions); ++i) {
5770 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5772 mono_set_pending_exception (ex);
5781 mono_memberref_is_method (MonoImage *image, guint32 token)
5783 if (!image_is_dynamic (image)) {
5784 guint32 cols [MONO_MEMBERREF_SIZE];
5786 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5787 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5788 mono_metadata_decode_blob_size (sig, &sig);
5789 return (*sig != 0x6);
5792 MonoClass *handle_class;
5794 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5795 mono_error_cleanup (&error); /* just probing, ignore error */
5799 return mono_defaults.methodhandle_class == handle_class;
5804 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5807 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5808 mono_array_addr (type_args, MonoType*, 0));
5810 context->class_inst = NULL;
5812 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5813 mono_array_addr (method_args, MonoType*, 0));
5815 context->method_inst = NULL;
5818 ICALL_EXPORT MonoType*
5819 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5822 int table = mono_metadata_token_table (token);
5823 int index = mono_metadata_token_index (token);
5824 MonoGenericContext context;
5827 *resolve_error = ResolveTokenError_Other;
5829 /* Validate token */
5830 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5831 (table != MONO_TABLE_TYPESPEC)) {
5832 *resolve_error = ResolveTokenError_BadTable;
5836 if (image_is_dynamic (image)) {
5837 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5838 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5839 mono_error_cleanup (&error);
5840 return klass ? &klass->byval_arg : NULL;
5843 init_generic_context_from_args (&context, type_args, method_args);
5844 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5845 mono_error_cleanup (&error);
5846 return klass ? &klass->byval_arg : NULL;
5849 if ((index <= 0) || (index > image->tables [table].rows)) {
5850 *resolve_error = ResolveTokenError_OutOfRange;
5854 init_generic_context_from_args (&context, type_args, method_args);
5855 klass = mono_class_get_checked (image, token, &error);
5857 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5858 if (!mono_error_ok (&error)) {
5859 mono_error_set_pending_exception (&error);
5864 return &klass->byval_arg;
5869 ICALL_EXPORT MonoMethod*
5870 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5873 int table = mono_metadata_token_table (token);
5874 int index = mono_metadata_token_index (token);
5875 MonoGenericContext context;
5878 *resolve_error = ResolveTokenError_Other;
5880 /* Validate token */
5881 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5882 (table != MONO_TABLE_MEMBERREF)) {
5883 *resolve_error = ResolveTokenError_BadTable;
5887 if (image_is_dynamic (image)) {
5888 if (table == MONO_TABLE_METHOD) {
5889 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5890 mono_error_cleanup (&error);
5894 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5895 *resolve_error = ResolveTokenError_BadTable;
5899 init_generic_context_from_args (&context, type_args, method_args);
5900 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5901 mono_error_cleanup (&error);
5905 if ((index <= 0) || (index > image->tables [table].rows)) {
5906 *resolve_error = ResolveTokenError_OutOfRange;
5909 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5910 *resolve_error = ResolveTokenError_BadTable;
5914 init_generic_context_from_args (&context, type_args, method_args);
5915 method = mono_get_method_checked (image, token, NULL, &context, &error);
5916 mono_error_set_pending_exception (&error);
5921 ICALL_EXPORT MonoString*
5922 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5925 int index = mono_metadata_token_index (token);
5927 *resolve_error = ResolveTokenError_Other;
5929 /* Validate token */
5930 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5931 *resolve_error = ResolveTokenError_BadTable;
5935 if (image_is_dynamic (image)) {
5936 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5937 mono_error_cleanup (&error);
5941 if ((index <= 0) || (index >= image->heap_us.size)) {
5942 *resolve_error = ResolveTokenError_OutOfRange;
5946 /* FIXME: What to do if the index points into the middle of a string ? */
5948 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5949 mono_error_set_pending_exception (&error);
5953 ICALL_EXPORT MonoClassField*
5954 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5958 int table = mono_metadata_token_table (token);
5959 int index = mono_metadata_token_index (token);
5960 MonoGenericContext context;
5961 MonoClassField *field;
5963 *resolve_error = ResolveTokenError_Other;
5965 /* Validate token */
5966 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5967 *resolve_error = ResolveTokenError_BadTable;
5971 if (image_is_dynamic (image)) {
5972 if (table == MONO_TABLE_FIELD) {
5973 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5974 mono_error_cleanup (&error);
5978 if (mono_memberref_is_method (image, token)) {
5979 *resolve_error = ResolveTokenError_BadTable;
5983 init_generic_context_from_args (&context, type_args, method_args);
5984 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5985 mono_error_cleanup (&error);
5989 if ((index <= 0) || (index > image->tables [table].rows)) {
5990 *resolve_error = ResolveTokenError_OutOfRange;
5993 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5994 *resolve_error = ResolveTokenError_BadTable;
5998 init_generic_context_from_args (&context, type_args, method_args);
5999 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6000 mono_error_set_pending_exception (&error);
6006 ICALL_EXPORT MonoObject*
6007 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6011 int table = mono_metadata_token_table (token);
6013 *error = ResolveTokenError_Other;
6016 case MONO_TABLE_TYPEDEF:
6017 case MONO_TABLE_TYPEREF:
6018 case MONO_TABLE_TYPESPEC: {
6019 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6021 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6022 mono_error_set_pending_exception (&merror);
6029 case MONO_TABLE_METHOD:
6030 case MONO_TABLE_METHODSPEC: {
6031 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6033 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6034 mono_error_set_pending_exception (&merror);
6040 case MONO_TABLE_FIELD: {
6041 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6043 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6044 mono_error_set_pending_exception (&merror);
6050 case MONO_TABLE_MEMBERREF:
6051 if (mono_memberref_is_method (image, token)) {
6052 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6054 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6055 mono_error_set_pending_exception (&merror);
6062 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6064 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6065 mono_error_set_pending_exception (&merror);
6074 *error = ResolveTokenError_BadTable;
6080 ICALL_EXPORT MonoArray*
6081 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6084 int table = mono_metadata_token_table (token);
6085 int idx = mono_metadata_token_index (token);
6086 MonoTableInfo *tables = image->tables;
6091 *resolve_error = ResolveTokenError_OutOfRange;
6093 /* FIXME: Support other tables ? */
6094 if (table != MONO_TABLE_STANDALONESIG)
6097 if (image_is_dynamic (image))
6100 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6103 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6105 ptr = mono_metadata_blob_heap (image, sig);
6106 len = mono_metadata_decode_blob_size (ptr, &ptr);
6108 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6109 if (mono_error_set_pending_exception (&error))
6111 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6115 ICALL_EXPORT MonoBoolean
6116 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6122 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6128 check_for_invalid_type (MonoClass *klass, MonoError *error)
6133 mono_error_init (error);
6135 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6138 name = mono_type_get_full_name (klass);
6139 str = mono_string_new (mono_domain_get (), name);
6141 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6144 ICALL_EXPORT MonoReflectionType *
6145 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6148 MonoReflectionType *ret;
6149 MonoClass *klass, *aklass;
6151 klass = mono_class_from_mono_type (type->type);
6152 check_for_invalid_type (klass, &error);
6153 mono_error_set_pending_exception (&error);
6155 if (rank == 0) //single dimentional array
6156 aklass = mono_array_class_get (klass, 1);
6158 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6160 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6161 mono_error_set_pending_exception (&error);
6166 ICALL_EXPORT MonoReflectionType *
6167 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6170 MonoReflectionType *ret;
6173 klass = mono_class_from_mono_type (type->type);
6174 mono_class_init_checked (klass, &error);
6175 if (mono_error_set_pending_exception (&error))
6178 check_for_invalid_type (klass, &error);
6179 if (mono_error_set_pending_exception (&error))
6182 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6183 mono_error_set_pending_exception (&error);
6188 ICALL_EXPORT MonoReflectionType *
6189 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6192 MonoReflectionType *ret;
6193 MonoClass *klass, *pklass;
6195 klass = mono_class_from_mono_type (type->type);
6196 mono_class_init_checked (klass, &error);
6197 if (mono_error_set_pending_exception (&error))
6199 check_for_invalid_type (klass, &error);
6200 if (mono_error_set_pending_exception (&error))
6203 pklass = mono_ptr_class_get (type->type);
6205 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6206 mono_error_set_pending_exception (&error);
6211 ICALL_EXPORT MonoObject *
6212 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6213 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6216 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6217 MonoObject *delegate;
6219 MonoMethod *method = info->method;
6220 MonoMethodSignature *sig = mono_method_signature(method);
6222 mono_class_init_checked (delegate_class, &error);
6223 if (mono_error_set_pending_exception (&error))
6226 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6227 /* FIXME improve this exception message */
6228 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6230 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6231 mono_error_set_pending_exception (&error);
6235 if (mono_security_core_clr_enabled ()) {
6236 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6237 if (throwOnBindFailure)
6238 mono_error_set_pending_exception (&error);
6240 mono_error_cleanup (&error);
6245 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6246 if (!method->is_inflated) {
6247 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"));
6252 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6253 if (mono_error_set_pending_exception (&error))
6256 if (method_is_dynamic (method)) {
6257 /* Creating a trampoline would leak memory */
6258 func = mono_compile_method_checked (method, &error);
6259 if (mono_error_set_pending_exception (&error))
6262 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6263 method = mono_object_get_virtual_method (target, method);
6264 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6265 if (mono_error_set_pending_exception (&error))
6267 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6270 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6271 if (mono_error_set_pending_exception (&error))
6276 ICALL_EXPORT MonoMulticastDelegate *
6277 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6280 MonoMulticastDelegate *ret;
6282 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6284 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6285 if (mono_error_set_pending_exception (&error))
6288 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6293 ICALL_EXPORT MonoReflectionMethod*
6294 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6296 MonoReflectionMethod *ret = NULL;
6298 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6299 mono_error_set_pending_exception (&error);
6305 static inline gint32
6306 mono_array_get_byte_length (MonoArray *array)
6312 klass = array->obj.vtable->klass;
6314 if (array->bounds == NULL)
6315 length = array->max_length;
6318 for (i = 0; i < klass->rank; ++ i)
6319 length *= array->bounds [i].length;
6322 switch (klass->element_class->byval_arg.type) {
6325 case MONO_TYPE_BOOLEAN:
6329 case MONO_TYPE_CHAR:
6337 return length * sizeof (gpointer);
6348 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6350 return mono_array_get_byte_length (array);
6354 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6356 return mono_array_get (array, gint8, idx);
6360 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6362 mono_array_set (array, gint8, idx, value);
6365 ICALL_EXPORT MonoBoolean
6366 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6368 guint8 *src_buf, *dest_buf;
6371 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6375 g_assert (count >= 0);
6377 /* This is called directly from the class libraries without going through the managed wrapper */
6378 MONO_CHECK_ARG_NULL (src, FALSE);
6379 MONO_CHECK_ARG_NULL (dest, FALSE);
6381 /* watch out for integer overflow */
6382 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6385 src_buf = (guint8 *)src->vector + src_offset;
6386 dest_buf = (guint8 *)dest->vector + dest_offset;
6389 memcpy (dest_buf, src_buf, count);
6391 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6396 #ifndef DISABLE_REMOTING
6397 ICALL_EXPORT MonoObject *
6398 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6401 MonoDomain *domain = mono_object_domain (this_obj);
6403 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6404 MonoTransparentProxy *tp;
6408 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6409 if (mono_error_set_pending_exception (&error))
6412 tp = (MonoTransparentProxy*) res;
6414 MONO_OBJECT_SETREF (tp, rp, rp);
6415 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6416 klass = mono_class_from_mono_type (type);
6418 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6419 mono_class_setup_vtable (klass);
6420 if (mono_class_has_failure (klass)) {
6421 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6425 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6426 if (mono_error_set_pending_exception (&error))
6428 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6429 if (mono_error_set_pending_exception (&error))
6432 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6433 if (mono_error_set_pending_exception (&error))
6438 ICALL_EXPORT MonoReflectionType *
6439 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6442 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6443 mono_error_set_pending_exception (&error);
6449 /* System.Environment */
6452 ves_icall_System_Environment_get_UserName (void)
6454 /* using glib is more portable */
6455 return mono_string_new (mono_domain_get (), g_get_user_name ());
6459 ICALL_EXPORT MonoString *
6460 ves_icall_System_Environment_get_MachineName (void)
6462 #if defined (HOST_WIN32)
6467 len = MAX_COMPUTERNAME_LENGTH + 1;
6468 buf = g_new (gunichar2, len);
6471 if (GetComputerName (buf, (PDWORD) &len)) {
6473 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6474 mono_error_set_pending_exception (&error);
6479 #elif !defined(DISABLE_SOCKETS)
6483 #if defined _SC_HOST_NAME_MAX
6484 n = sysconf (_SC_HOST_NAME_MAX);
6488 buf = g_malloc (n+1);
6490 if (gethostname (buf, n) == 0){
6492 result = mono_string_new (mono_domain_get (), buf);
6499 return mono_string_new (mono_domain_get (), "mono");
6504 ves_icall_System_Environment_get_Platform (void)
6506 #if defined (TARGET_WIN32)
6509 #elif defined(__MACH__)
6512 // Notice that the value is hidden from user code, and only exposed
6513 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6514 // define and making assumptions based on Unix/128/4 values before there
6515 // was a MacOS define. Lots of code would assume that not-Unix meant
6516 // Windows, but in this case, it would be OSX.
6525 ICALL_EXPORT MonoString *
6526 ves_icall_System_Environment_get_NewLine (void)
6528 #if defined (HOST_WIN32)
6529 return mono_string_new (mono_domain_get (), "\r\n");
6531 return mono_string_new (mono_domain_get (), "\n");
6535 ICALL_EXPORT MonoBoolean
6536 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6538 #if SIZEOF_VOID_P == 8
6542 gboolean isWow64Process = FALSE;
6543 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6544 return (MonoBoolean)isWow64Process;
6546 #elif defined(HAVE_SYS_UTSNAME_H)
6547 struct utsname name;
6549 if (uname (&name) >= 0) {
6550 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6557 ICALL_EXPORT MonoStringHandle
6558 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6562 if (utf8_name == NULL)
6563 return NULL_HANDLE_STRING;
6565 value = g_getenv (utf8_name);
6568 return NULL_HANDLE_STRING;
6570 return mono_string_new_handle (mono_domain_get (), value, error);
6574 * There is no standard way to get at environ.
6577 #ifndef __MINGW32_VERSION
6578 #if defined(__APPLE__)
6579 #if defined (TARGET_OSX)
6580 /* Apple defines this in crt_externs.h but doesn't provide that header for
6581 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6582 * in fact exist on all implementations (so far)
6584 gchar ***_NSGetEnviron(void);
6585 #define environ (*_NSGetEnviron())
6587 static char *mono_environ[1] = { NULL };
6588 #define environ mono_environ
6589 #endif /* defined (TARGET_OSX) */
6597 ICALL_EXPORT MonoArray *
6598 ves_icall_System_Environment_GetCoomandLineArgs (void)
6601 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6602 mono_error_set_pending_exception (&error);
6606 ICALL_EXPORT MonoArray *
6607 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6619 env_strings = GetEnvironmentStrings();
6622 env_string = env_strings;
6623 while (*env_string != '\0') {
6624 /* weird case that MS seems to skip */
6625 if (*env_string != '=')
6627 while (*env_string != '\0')
6633 domain = mono_domain_get ();
6634 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6635 if (mono_error_set_pending_exception (&error))
6640 env_string = env_strings;
6641 while (*env_string != '\0') {
6642 /* weird case that MS seems to skip */
6643 if (*env_string != '=') {
6644 equal_str = wcschr(env_string, '=');
6645 g_assert(equal_str);
6647 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6648 if (mono_error_set_pending_exception (&error))
6651 mono_array_setref (names, n, str);
6654 while (*env_string != '\0')
6659 FreeEnvironmentStrings (env_strings);
6673 for (e = environ; *e != 0; ++ e)
6676 domain = mono_domain_get ();
6677 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6678 if (mono_error_set_pending_exception (&error))
6682 for (e = environ; *e != 0; ++ e) {
6683 parts = g_strsplit (*e, "=", 2);
6685 str = mono_string_new (domain, *parts);
6686 mono_array_setref (names, n, str);
6699 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6702 gunichar2 *utf16_name, *utf16_value;
6704 gchar *utf8_name, *utf8_value;
6709 utf16_name = mono_string_to_utf16 (name);
6710 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6711 SetEnvironmentVariable (utf16_name, NULL);
6712 g_free (utf16_name);
6716 utf16_value = mono_string_to_utf16 (value);
6718 SetEnvironmentVariable (utf16_name, utf16_value);
6720 g_free (utf16_name);
6721 g_free (utf16_value);
6723 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6724 if (mono_error_set_pending_exception (&error))
6727 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6728 g_unsetenv (utf8_name);
6733 utf8_value = mono_string_to_utf8_checked (value, &error);
6734 if (!mono_error_ok (&error)) {
6736 mono_error_set_pending_exception (&error);
6739 g_setenv (utf8_name, utf8_value, TRUE);
6742 g_free (utf8_value);
6747 ves_icall_System_Environment_Exit (int result)
6749 mono_environment_exitcode_set (result);
6751 /* FIXME: There are some cleanup hangs that should be worked out, but
6752 * if the program is going to exit, everything will be cleaned up when
6753 * NaCl exits anyway.
6755 #ifndef __native_client__
6756 if (!mono_runtime_try_shutdown ())
6757 mono_thread_exit ();
6759 /* Suspend all managed threads since the runtime is going away */
6760 mono_thread_suspend_all_other_threads ();
6762 mono_runtime_quit ();
6765 /* we may need to do some cleanup here... */
6769 ICALL_EXPORT MonoStringHandle
6770 ves_icall_System_Environment_GetGacPath (MonoError *error)
6772 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6775 ICALL_EXPORT MonoString*
6776 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6778 #if defined (HOST_WIN32)
6779 #ifndef CSIDL_FLAG_CREATE
6780 #define CSIDL_FLAG_CREATE 0x8000
6783 WCHAR path [MAX_PATH];
6784 /* Create directory if no existing */
6785 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6790 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6791 mono_error_set_pending_exception (&error);
6795 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6797 return mono_string_new (mono_domain_get (), "");
6800 ICALL_EXPORT MonoArray *
6801 ves_icall_System_Environment_GetLogicalDrives (void)
6804 gunichar2 buf [256], *ptr, *dname;
6806 guint initial_size = 127, size = 128;
6809 MonoString *drivestr;
6810 MonoDomain *domain = mono_domain_get ();
6816 while (size > initial_size) {
6817 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6818 if (size > initial_size) {
6821 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6822 initial_size = size;
6836 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6837 if (mono_error_set_pending_exception (&error))
6844 while (*u16) { u16++; len ++; }
6845 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6846 if (mono_error_set_pending_exception (&error))
6849 mono_array_setref (result, ndrives++, drivestr);
6860 ICALL_EXPORT MonoString *
6861 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6864 gunichar2 volume_name [MAX_PATH + 1];
6866 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6868 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6869 mono_error_set_pending_exception (&error);
6873 ICALL_EXPORT MonoStringHandle
6874 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6876 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6879 static const char *encodings [] = {
6881 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6882 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6883 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6885 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6886 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6887 "x_unicode_2_0_utf_7",
6889 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6890 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6892 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6895 "unicodefffe", "utf_16be",
6902 * Returns the internal codepage, if the value of "int_code_page" is
6903 * 1 at entry, and we can not compute a suitable code page number,
6904 * returns the code page as a string
6906 ICALL_EXPORT MonoString*
6907 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6912 char *codepage = NULL;
6914 int want_name = *int_code_page;
6917 *int_code_page = -1;
6919 g_get_charset (&cset);
6920 c = codepage = strdup (cset);
6921 for (c = codepage; *c; c++){
6922 if (isascii (*c) && isalpha (*c))
6927 /* g_print ("charset: %s\n", cset); */
6929 /* handle some common aliases */
6932 for (i = 0; p != 0; ){
6935 p = encodings [++i];
6938 if (strcmp (p, codepage) == 0){
6939 *int_code_page = code;
6942 p = encodings [++i];
6945 if (strstr (codepage, "utf_8") != NULL)
6946 *int_code_page |= 0x10000000;
6949 if (want_name && *int_code_page == -1)
6950 return mono_string_new (mono_domain_get (), cset);
6955 ICALL_EXPORT MonoBoolean
6956 ves_icall_System_Environment_get_HasShutdownStarted (void)
6958 if (mono_runtime_is_shutting_down ())
6961 if (mono_domain_is_unloading (mono_domain_get ()))
6968 ves_icall_System_Environment_BroadcastSettingChange (void)
6971 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6977 ves_icall_System_Environment_get_TickCount (void)
6979 /* this will overflow after ~24 days */
6980 return (gint32) (mono_msec_boottime () & 0xffffffff);
6984 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6989 #ifndef DISABLE_REMOTING
6990 ICALL_EXPORT MonoBoolean
6991 ves_icall_IsTransparentProxy (MonoObject *proxy)
6996 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7002 ICALL_EXPORT MonoReflectionMethod *
7003 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7004 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7006 MonoReflectionMethod *ret = NULL;
7011 MonoMethod **vtable;
7012 MonoMethod *res = NULL;
7014 MONO_CHECK_ARG_NULL (rtype, NULL);
7015 MONO_CHECK_ARG_NULL (rmethod, NULL);
7017 method = rmethod->method;
7018 klass = mono_class_from_mono_type (rtype->type);
7019 mono_class_init_checked (klass, &error);
7020 if (mono_error_set_pending_exception (&error))
7023 if (MONO_CLASS_IS_INTERFACE (klass))
7026 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7029 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7030 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7036 mono_class_setup_vtable (klass);
7037 vtable = klass->vtable;
7039 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7040 gboolean variance_used = FALSE;
7041 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7042 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7044 res = vtable [offs + method->slot];
7046 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7049 if (method->slot != -1)
7050 res = vtable [method->slot];
7056 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7057 mono_error_set_pending_exception (&error);
7062 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7068 klass = mono_class_from_mono_type (type->type);
7069 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7070 if (!is_ok (&error)) {
7071 mono_error_set_pending_exception (&error);
7075 mono_vtable_set_is_remote (vtable, enable);
7078 #else /* DISABLE_REMOTING */
7081 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7083 g_assert_not_reached ();
7088 ICALL_EXPORT MonoObject *
7089 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7096 domain = mono_object_domain (type);
7097 klass = mono_class_from_mono_type (type->type);
7098 mono_class_init_checked (klass, &error);
7099 if (mono_error_set_pending_exception (&error))
7102 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7103 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7107 if (klass->rank >= 1) {
7108 g_assert (klass->rank == 1);
7109 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7110 mono_error_set_pending_exception (&error);
7113 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7114 if (!is_ok (&error)) {
7115 mono_error_set_pending_exception (&error);
7118 /* Bypass remoting object creation check */
7119 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7120 mono_error_set_pending_exception (&error);
7126 ICALL_EXPORT MonoStringHandle
7127 ves_icall_System_IO_get_temp_path (MonoError *error)
7129 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7132 #ifndef PLATFORM_NO_DRIVEINFO
7133 ICALL_EXPORT MonoBoolean
7134 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7135 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7139 ULARGE_INTEGER wapi_free_bytes_avail;
7140 ULARGE_INTEGER wapi_total_number_of_bytes;
7141 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7143 *error = ERROR_SUCCESS;
7144 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7145 &wapi_total_number_of_free_bytes);
7148 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7149 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7150 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7152 *free_bytes_avail = 0;
7153 *total_number_of_bytes = 0;
7154 *total_number_of_free_bytes = 0;
7155 *error = GetLastError ();
7161 ICALL_EXPORT guint32
7162 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7164 return GetDriveType (mono_string_chars (root_path_name));
7168 ICALL_EXPORT gpointer
7169 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7172 gpointer result = mono_compile_method_checked (method, &error);
7173 mono_error_set_pending_exception (&error);
7177 ICALL_EXPORT MonoString *
7178 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7183 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7185 #if defined (HOST_WIN32)
7186 /* Avoid mixing '/' and '\\' */
7189 for (i = strlen (path) - 1; i >= 0; i--)
7190 if (path [i] == '/')
7194 mcpath = mono_string_new (mono_domain_get (), path);
7200 /* this is an icall */
7202 get_bundled_app_config (void)
7205 const gchar *app_config;
7208 gchar *config_file_name, *config_file_path;
7209 gsize len, config_file_path_length, config_ext_length;
7212 domain = mono_domain_get ();
7213 file = domain->setup->configuration_file;
7214 if (!file || file->length == 0)
7217 // Retrieve config file and remove the extension
7218 config_file_name = mono_string_to_utf8_checked (file, &error);
7219 if (mono_error_set_pending_exception (&error))
7221 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7222 if (!config_file_path)
7223 config_file_path = config_file_name;
7225 config_file_path_length = strlen (config_file_path);
7226 config_ext_length = strlen (".config");
7227 if (config_file_path_length <= config_ext_length)
7230 len = config_file_path_length - config_ext_length;
7231 module = (gchar *)g_malloc0 (len + 1);
7232 memcpy (module, config_file_path, len);
7233 // Get the config file from the module name
7234 app_config = mono_config_string_for_assembly_file (module);
7237 if (config_file_name != config_file_path)
7238 g_free (config_file_name);
7239 g_free (config_file_path);
7244 return mono_string_new (mono_domain_get (), app_config);
7247 /* this is an icall */
7248 static MonoStringHandle
7249 get_bundled_machine_config (MonoError *error)
7251 const gchar *machine_config;
7253 machine_config = mono_get_machine_config ();
7255 if (!machine_config)
7256 return NULL_HANDLE_STRING;
7258 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7261 ICALL_EXPORT MonoString *
7262 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7267 path = g_path_get_dirname (mono_get_config_dir ());
7269 #if defined (HOST_WIN32)
7270 /* Avoid mixing '/' and '\\' */
7273 for (i = strlen (path) - 1; i >= 0; i--)
7274 if (path [i] == '/')
7278 ipath = mono_string_new (mono_domain_get (), path);
7284 ICALL_EXPORT gboolean
7285 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7287 MonoPEResourceDataEntry *entry;
7290 if (!assembly || !result || !size)
7295 image = assembly->assembly->image;
7296 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7300 *result = mono_image_rva_map (image, entry->rde_data_offset);
7305 *size = entry->rde_size;
7310 ICALL_EXPORT MonoBoolean
7311 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7313 return mono_is_debugger_attached ();
7316 ICALL_EXPORT MonoBoolean
7317 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7319 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7320 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7326 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7328 if (mono_get_runtime_callbacks ()->debug_log)
7329 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7333 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7335 #if defined (HOST_WIN32)
7336 OutputDebugString (mono_string_chars (message));
7338 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7342 /* Only used for value types */
7343 ICALL_EXPORT MonoObject *
7344 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7351 domain = mono_object_domain (type);
7352 klass = mono_class_from_mono_type (type->type);
7353 mono_class_init_checked (klass, &error);
7354 if (mono_error_set_pending_exception (&error))
7357 if (mono_class_is_nullable (klass))
7358 /* No arguments -> null */
7361 result = mono_object_new_checked (domain, klass, &error);
7362 mono_error_set_pending_exception (&error);
7366 ICALL_EXPORT MonoReflectionMethod *
7367 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7369 MonoReflectionMethod *ret = NULL;
7372 MonoClass *klass, *parent;
7373 MonoGenericContext *generic_inst = NULL;
7374 MonoMethod *method = m->method;
7375 MonoMethod *result = NULL;
7378 if (method->klass == NULL)
7381 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7382 MONO_CLASS_IS_INTERFACE (method->klass) ||
7383 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7386 slot = mono_method_get_vtable_slot (method);
7390 klass = method->klass;
7391 if (klass->generic_class) {
7392 generic_inst = mono_class_get_context (klass);
7393 klass = klass->generic_class->container_class;
7398 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7399 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7400 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7401 or klass is the generic container class and generic_inst is the instantiation.
7403 when we go to the parent, if the parent is an open constructed type, we need to
7404 replace the type parameters by the definitions from the generic_inst, and then take it
7405 apart again into the klass and the generic_inst.
7407 For cases like this:
7408 class C<T> : B<T, int> {
7409 public override void Foo () { ... }
7411 class B<U,V> : A<HashMap<U,V>> {
7412 public override void Foo () { ... }
7415 public virtual void Foo () { ... }
7418 if at each iteration the parent isn't open, we can skip inflating it. if at some
7419 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7422 MonoGenericContext *parent_inst = NULL;
7423 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7424 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7425 if (!mono_error_ok (&error)) {
7426 mono_error_set_pending_exception (&error);
7430 if (parent->generic_class) {
7431 parent_inst = mono_class_get_context (parent);
7432 parent = parent->generic_class->container_class;
7435 mono_class_setup_vtable (parent);
7436 if (parent->vtable_size <= slot)
7439 generic_inst = parent_inst;
7442 klass = klass->parent;
7445 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7446 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7447 if (!mono_error_ok (&error)) {
7448 mono_error_set_pending_exception (&error);
7452 generic_inst = NULL;
7454 if (klass->generic_class) {
7455 generic_inst = mono_class_get_context (klass);
7456 klass = klass->generic_class->container_class;
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);
7469 if (klass == method->klass)
7472 /*This is possible if definition == FALSE.
7473 * Do it here to be really sure we don't read invalid memory.
7475 if (slot >= klass->vtable_size)
7478 mono_class_setup_vtable (klass);
7480 result = klass->vtable [slot];
7481 if (result == NULL) {
7482 /* It is an abstract method */
7483 gboolean found = FALSE;
7484 gpointer iter = NULL;
7485 while ((result = mono_class_get_methods (klass, &iter))) {
7486 if (result->slot == slot) {
7491 /* found might be FALSE if we looked in an abstract class
7492 * that doesn't override an abstract method of its
7494 * abstract class Base {
7495 * public abstract void Foo ();
7497 * abstract class Derived : Base { }
7498 * class Child : Derived {
7499 * public override void Foo () { }
7502 * if m was Child.Foo and we ask for the base method,
7503 * then we get here with klass == Derived and found == FALSE
7505 /* but it shouldn't be the case that if we're looking
7506 * for the definition and didn't find a result; the
7507 * loop above should've taken us as far as we could
7509 g_assert (!(definition && !found));
7514 g_assert (result != NULL);
7516 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7517 mono_error_set_pending_exception (&error);
7521 ICALL_EXPORT MonoString*
7522 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7524 MonoMethod *method = m->method;
7526 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7531 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7533 iter->sig = *(MonoMethodSignature**)argsp;
7535 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7536 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7539 /* FIXME: it's not documented what start is exactly... */
7543 iter->args = argsp + sizeof (gpointer);
7545 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7547 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7550 ICALL_EXPORT MonoTypedRef
7551 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7553 guint32 i, arg_size;
7557 i = iter->sig->sentinelpos + iter->next_arg;
7559 g_assert (i < iter->sig->param_count);
7561 res.type = iter->sig->params [i];
7562 res.klass = mono_class_from_mono_type (res.type);
7563 arg_size = mono_type_stack_size (res.type, &align);
7564 #if defined(__arm__) || defined(__mips__)
7565 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7567 res.value = iter->args;
7568 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7569 /* Values are stored as 8 byte register sized objects, but 'value'
7570 * is dereferenced as a pointer in other routines.
7572 res.value = (char*)res.value + 4;
7574 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7575 if (arg_size <= sizeof (gpointer)) {
7577 int padding = arg_size - mono_type_size (res.type, &dummy);
7578 res.value = (guint8*)res.value + padding;
7581 iter->args = (char*)iter->args + arg_size;
7584 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7589 ICALL_EXPORT MonoTypedRef
7590 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7592 guint32 i, arg_size;
7596 i = iter->sig->sentinelpos + iter->next_arg;
7598 g_assert (i < iter->sig->param_count);
7600 while (i < iter->sig->param_count) {
7601 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7603 res.type = iter->sig->params [i];
7604 res.klass = mono_class_from_mono_type (res.type);
7605 /* FIXME: endianess issue... */
7606 arg_size = mono_type_stack_size (res.type, &align);
7607 #if defined(__arm__) || defined(__mips__)
7608 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7610 res.value = iter->args;
7611 iter->args = (char*)iter->args + arg_size;
7613 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7616 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7624 ICALL_EXPORT MonoType*
7625 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7629 i = iter->sig->sentinelpos + iter->next_arg;
7631 g_assert (i < iter->sig->param_count);
7633 return iter->sig->params [i];
7636 ICALL_EXPORT MonoObject*
7637 mono_TypedReference_ToObject (MonoTypedRef* tref)
7640 MonoObject *result = NULL;
7641 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7642 MonoObject** objp = (MonoObject **)tref->value;
7646 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7647 mono_error_set_pending_exception (&error);
7651 ICALL_EXPORT MonoTypedRef
7652 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7655 MonoReflectionField *f;
7657 MonoType *ftype = NULL;
7661 memset (&res, 0, sizeof (res));
7664 g_assert (mono_array_length (fields) > 0);
7666 klass = target->vtable->klass;
7668 for (i = 0; i < mono_array_length (fields); ++i) {
7669 f = mono_array_get (fields, MonoReflectionField*, i);
7671 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7674 if (f->field->parent != klass) {
7675 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7679 p = (guint8*)target + f->field->offset;
7681 p += f->field->offset - sizeof (MonoObject);
7682 klass = mono_class_from_mono_type (f->field->type);
7683 ftype = f->field->type;
7687 res.klass = mono_class_from_mono_type (ftype);
7694 prelink_method (MonoMethod *method, MonoError *error)
7696 const char *exc_class, *exc_arg;
7698 mono_error_init (error);
7699 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7701 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7703 mono_error_set_exception_instance (error,
7704 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7707 /* create the wrapper, too? */
7711 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7715 prelink_method (method->method, &error);
7716 mono_error_set_pending_exception (&error);
7720 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7723 MonoClass *klass = mono_class_from_mono_type (type->type);
7725 gpointer iter = NULL;
7727 mono_class_init_checked (klass, &error);
7728 if (mono_error_set_pending_exception (&error))
7731 while ((m = mono_class_get_methods (klass, &iter))) {
7732 prelink_method (m, &error);
7733 if (mono_error_set_pending_exception (&error))
7738 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7740 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7741 gint32 const **exponents,
7742 gunichar2 const **digitLowerTable,
7743 gunichar2 const **digitUpperTable,
7744 gint64 const **tenPowersList,
7745 gint32 const **decHexDigits)
7747 *mantissas = Formatter_MantissaBitsTable;
7748 *exponents = Formatter_TensExponentTable;
7749 *digitLowerTable = Formatter_DigitLowerTable;
7750 *digitUpperTable = Formatter_DigitUpperTable;
7751 *tenPowersList = Formatter_TenPowersList;
7752 *decHexDigits = Formatter_DecHexDigits;
7756 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7757 * and avoid useless allocations.
7760 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7762 MonoReflectionType *rt;
7766 mono_error_init (error);
7767 for (i = 0; i < type->num_mods; ++i) {
7768 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7773 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7774 return_val_if_nok (error, NULL);
7776 for (i = 0; i < type->num_mods; ++i) {
7777 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7778 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7779 return_val_if_nok (error, NULL);
7781 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7782 return_val_if_nok (error, NULL);
7784 mono_array_setref (res, count, rt);
7791 ICALL_EXPORT MonoArray*
7792 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7795 MonoType *type = param->ClassImpl->type;
7796 MonoClass *member_class = mono_object_class (param->MemberImpl);
7797 MonoMethod *method = NULL;
7800 MonoMethodSignature *sig;
7803 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7804 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7805 method = rmethod->method;
7806 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7807 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7808 if (!(method = prop->property->get))
7809 method = prop->property->set;
7812 char *type_name = mono_type_get_full_name (member_class);
7813 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7814 MonoException *ex = mono_get_exception_not_supported (msg);
7817 mono_set_pending_exception (ex);
7821 image = method->klass->image;
7822 pos = param->PositionImpl;
7823 sig = mono_method_signature (method);
7827 type = sig->params [pos];
7829 res = type_array_from_modifiers (image, type, optional, &error);
7830 mono_error_set_pending_exception (&error);
7835 get_property_type (MonoProperty *prop)
7837 MonoMethodSignature *sig;
7839 sig = mono_method_signature (prop->get);
7841 } else if (prop->set) {
7842 sig = mono_method_signature (prop->set);
7843 return sig->params [sig->param_count - 1];
7848 ICALL_EXPORT MonoArray*
7849 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7852 MonoType *type = get_property_type (property->property);
7853 MonoImage *image = property->klass->image;
7858 res = type_array_from_modifiers (image, type, optional, &error);
7859 mono_error_set_pending_exception (&error);
7864 *Construct a MonoType suited to be used to decode a constant blob object.
7866 * @type is the target type which will be constructed
7867 * @blob_type is the blob type, for example, that comes from the constant table
7868 * @real_type is the expected constructed type.
7871 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7873 type->type = blob_type;
7874 type->data.klass = NULL;
7875 if (blob_type == MONO_TYPE_CLASS)
7876 type->data.klass = mono_defaults.object_class;
7877 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7878 /* For enums, we need to use the base type */
7879 type->type = MONO_TYPE_VALUETYPE;
7880 type->data.klass = mono_class_from_mono_type (real_type);
7882 type->data.klass = mono_class_from_mono_type (real_type);
7885 ICALL_EXPORT MonoObject*
7886 property_info_get_default_value (MonoReflectionProperty *property)
7890 MonoProperty *prop = property->property;
7891 MonoType *type = get_property_type (prop);
7892 MonoDomain *domain = mono_object_domain (property);
7893 MonoTypeEnum def_type;
7894 const char *def_value;
7897 mono_class_init (prop->parent);
7899 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7900 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7904 def_value = mono_class_get_property_default_value (prop, &def_type);
7906 mono_type_from_blob_type (&blob_type, def_type, type);
7907 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7909 mono_error_set_pending_exception (&error);
7913 ICALL_EXPORT MonoBoolean
7914 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7917 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7918 MonoCustomAttrInfo *cinfo;
7921 mono_class_init_checked (attr_class, &error);
7922 if (mono_error_set_pending_exception (&error))
7925 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7926 if (!is_ok (&error)) {
7927 mono_error_set_pending_exception (&error);
7932 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7934 mono_custom_attrs_free (cinfo);
7938 ICALL_EXPORT MonoArray*
7939 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7941 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7946 mono_class_init_checked (attr_class, &error);
7947 if (mono_error_set_pending_exception (&error))
7951 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7952 if (!mono_error_ok (&error)) {
7953 mono_error_set_pending_exception (&error);
7960 ICALL_EXPORT MonoArray*
7961 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7965 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7966 mono_error_set_pending_exception (&error);
7971 ICALL_EXPORT MonoString*
7972 ves_icall_Mono_Runtime_GetDisplayName (void)
7975 MonoString *display_name;
7977 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7978 display_name = mono_string_new (mono_domain_get (), info);
7980 return display_name;
7983 ICALL_EXPORT MonoString*
7984 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7987 MonoString *message;
7991 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7992 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7995 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7997 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7998 if (mono_error_set_pending_exception (&error))
8005 ICALL_EXPORT gpointer
8006 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8008 return GetCurrentProcess ();
8011 ICALL_EXPORT MonoBoolean
8012 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8014 return GetExitCodeProcess (handle, (guint32*) exitcode);
8017 ICALL_EXPORT MonoBoolean
8018 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8020 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8021 return CloseHandle (handle);
8023 return CloseProcess (handle);
8027 ICALL_EXPORT MonoBoolean
8028 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8030 return TerminateProcess (handle, exitcode);
8034 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8037 return WaitForInputIdle (handle, milliseconds);
8039 /*TODO: Not implemented*/
8040 return WAIT_TIMEOUT;
8044 ICALL_EXPORT MonoBoolean
8045 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8047 return GetProcessWorkingSetSize (handle, min, max);
8050 ICALL_EXPORT MonoBoolean
8051 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8053 return SetProcessWorkingSetSize (handle, min, max);
8056 ICALL_EXPORT MonoBoolean
8057 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8059 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8063 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8065 return mono_process_current_pid ();
8069 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8071 return GetPriorityClass (handle);
8074 ICALL_EXPORT MonoBoolean
8075 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8077 return SetPriorityClass (handle, priorityClass);
8080 #ifndef DISABLE_ICALL_TABLES
8082 #define ICALL_TYPE(id,name,first)
8083 #define ICALL(id,name,func) Icall_ ## id,
8084 #define HANDLES(inner) inner
8087 #include "metadata/icall-def.h"
8093 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8094 #define ICALL(id,name,func)
8096 #define HANDLES(inner) inner
8098 #include "metadata/icall-def.h"
8104 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8105 #define ICALL(id,name,func)
8107 #define HANDLES(inner) inner
8109 guint16 first_icall;
8112 static const IcallTypeDesc
8113 icall_type_descs [] = {
8114 #include "metadata/icall-def.h"
8118 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8121 #define HANDLES(inner) inner
8123 #define ICALL_TYPE(id,name,first)
8126 #ifdef HAVE_ARRAY_ELEM_INIT
8127 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8128 #define MSGSTRFIELD1(line) str##line
8130 static const struct msgstrtn_t {
8131 #define ICALL(id,name,func)
8133 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8134 #include "metadata/icall-def.h"
8136 } icall_type_names_str = {
8137 #define ICALL_TYPE(id,name,first) (name),
8138 #include "metadata/icall-def.h"
8141 static const guint16 icall_type_names_idx [] = {
8142 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8143 #include "metadata/icall-def.h"
8146 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8148 static const struct msgstr_t {
8150 #define ICALL_TYPE(id,name,first)
8151 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8152 #include "metadata/icall-def.h"
8154 } icall_names_str = {
8155 #define ICALL(id,name,func) (name),
8156 #include "metadata/icall-def.h"
8159 static const guint16 icall_names_idx [] = {
8160 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8161 #include "metadata/icall-def.h"
8164 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8170 #define ICALL_TYPE(id,name,first) name,
8171 #define ICALL(id,name,func)
8172 static const char* const
8173 icall_type_names [] = {
8174 #include "metadata/icall-def.h"
8178 #define icall_type_name_get(id) (icall_type_names [(id)])
8182 #define ICALL_TYPE(id,name,first)
8183 #define ICALL(id,name,func) name,
8184 static const char* const
8186 #include "metadata/icall-def.h"
8189 #define icall_name_get(id) icall_names [(id)]
8191 #endif /* !HAVE_ARRAY_ELEM_INIT */
8194 #define HANDLES(inner) inner
8197 #define ICALL_TYPE(id,name,first)
8198 #define ICALL(id,name,func) func,
8199 static const gconstpointer
8200 icall_functions [] = {
8201 #include "metadata/icall-def.h"
8205 #ifdef ENABLE_ICALL_SYMBOL_MAP
8207 #define HANDLES(inner) inner
8210 #define ICALL_TYPE(id,name,first)
8211 #define ICALL(id,name,func) #func,
8212 static const gconstpointer
8213 icall_symbols [] = {
8214 #include "metadata/icall-def.h"
8221 #define ICALL_TYPE(id,name,first)
8222 #define ICALL(id,name,func) 0,
8224 #define HANDLES(inner) 1,
8226 icall_uses_handles [] = {
8227 #include "metadata/icall-def.h"
8232 #endif /* DISABLE_ICALL_TABLES */
8234 static mono_mutex_t icall_mutex;
8235 static GHashTable *icall_hash = NULL;
8236 static GHashTable *jit_icall_hash_name = NULL;
8237 static GHashTable *jit_icall_hash_addr = NULL;
8240 mono_icall_init (void)
8242 #ifndef DISABLE_ICALL_TABLES
8245 /* check that tables are sorted: disable in release */
8248 const char *prev_class = NULL;
8249 const char *prev_method;
8251 for (i = 0; i < Icall_type_num; ++i) {
8252 const IcallTypeDesc *desc;
8255 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8256 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8257 prev_class = icall_type_name_get (i);
8258 desc = &icall_type_descs [i];
8259 num_icalls = icall_desc_num_icalls (desc);
8260 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8261 for (j = 0; j < num_icalls; ++j) {
8262 const char *methodn = icall_name_get (desc->first_icall + j);
8263 if (prev_method && strcmp (prev_method, methodn) >= 0)
8264 g_print ("method %s should come before method %s\n", methodn, prev_method);
8265 prev_method = methodn;
8271 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8272 mono_os_mutex_init (&icall_mutex);
8276 mono_icall_lock (void)
8278 mono_locks_os_acquire (&icall_mutex, IcallLock);
8282 mono_icall_unlock (void)
8284 mono_locks_os_release (&icall_mutex, IcallLock);
8288 mono_icall_cleanup (void)
8290 g_hash_table_destroy (icall_hash);
8291 g_hash_table_destroy (jit_icall_hash_name);
8292 g_hash_table_destroy (jit_icall_hash_addr);
8293 mono_os_mutex_destroy (&icall_mutex);
8297 * mono_add_internal_call:
8298 * @name: method specification to surface to the managed world
8299 * @method: pointer to a C method to invoke when the method is called
8301 * This method surfaces the C function pointed by @method as a method
8302 * that has been surfaced in managed code with the method specified in
8303 * @name as an internal call.
8305 * Internal calls are surfaced to all app domains loaded and they are
8306 * accessibly by a type with the specified name.
8308 * You must provide a fully qualified type name, that is namespaces
8309 * and type name, followed by a colon and the method name, with an
8310 * optional signature to bind.
8312 * For example, the following are all valid declarations:
8314 * "MyApp.Services.ScriptService:Accelerate"
8315 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8317 * You use method parameters in cases where there might be more than
8318 * one surface method to managed code. That way you can register different
8319 * internal calls for different method overloads.
8321 * The internal calls are invoked with no marshalling. This means that .NET
8322 * types like System.String are exposed as `MonoString *` parameters. This is
8323 * different than the way that strings are surfaced in P/Invoke.
8325 * For more information on how the parameters are marshalled, see the
8326 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8329 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8330 * reference for more information on the format of method descriptions.
8333 mono_add_internal_call (const char *name, gconstpointer method)
8337 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8339 mono_icall_unlock ();
8342 #ifndef DISABLE_ICALL_TABLES
8344 #ifdef HAVE_ARRAY_ELEM_INIT
8346 compare_method_imap (const void *key, const void *elem)
8348 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8349 return strcmp (key, method_name);
8353 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8355 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);
8358 return (nameslot - &icall_names_idx [0]);
8362 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8364 gsize slotnum = find_slot_icall (imap, name);
8367 return (gboolean)icall_uses_handles [slotnum];
8371 find_method_icall (const IcallTypeDesc *imap, const char *name)
8373 gsize slotnum = find_slot_icall (imap, name);
8376 return (gpointer)icall_functions [slotnum];
8380 compare_class_imap (const void *key, const void *elem)
8382 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8383 return strcmp (key, class_name);
8386 static const IcallTypeDesc*
8387 find_class_icalls (const char *name)
8389 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);
8392 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8395 #else /* HAVE_ARRAY_ELEM_INIT */
8398 compare_method_imap (const void *key, const void *elem)
8400 const char** method_name = (const char**)elem;
8401 return strcmp (key, *method_name);
8405 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8407 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8410 return nameslot - icall_names;
8414 find_method_icall (const IcallTypeDesc *imap, const char *name)
8416 gsize slotnum = find_slot_icall (imap, name);
8419 return (gpointer)icall_functions [slotnum];
8423 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8425 gsize slotnum = find_slot_icall (imap, name);
8428 return (gboolean)icall_uses_handles [slotnum];
8432 compare_class_imap (const void *key, const void *elem)
8434 const char** class_name = (const char**)elem;
8435 return strcmp (key, *class_name);
8438 static const IcallTypeDesc*
8439 find_class_icalls (const char *name)
8441 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8444 return &icall_type_descs [nameslot - icall_type_names];
8447 #endif /* HAVE_ARRAY_ELEM_INIT */
8449 #endif /* DISABLE_ICALL_TABLES */
8452 * we should probably export this as an helper (handle nested types).
8453 * Returns the number of chars written in buf.
8456 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8458 int nspacelen, cnamelen;
8459 nspacelen = strlen (klass->name_space);
8460 cnamelen = strlen (klass->name);
8461 if (nspacelen + cnamelen + 2 > bufsize)
8464 memcpy (buf, klass->name_space, nspacelen);
8465 buf [nspacelen ++] = '.';
8467 memcpy (buf + nspacelen, klass->name, cnamelen);
8468 buf [nspacelen + cnamelen] = 0;
8469 return nspacelen + cnamelen;
8472 #ifdef DISABLE_ICALL_TABLES
8474 no_icall_table (void)
8476 g_assert_not_reached ();
8481 * mono_lookup_internal_call_full:
8482 * @method: the method to look up
8483 * @uses_handles: out argument if method needs handles around managed objects.
8485 * Returns a pointer to the icall code for the given method. If
8486 * uses_handles is not NULL, it will be set to TRUE if the method
8487 * needs managed objects wrapped using the infrastructure in handle.h
8489 * If the method is not found, warns and returns NULL.
8492 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8497 int typelen = 0, mlen, siglen;
8499 #ifndef DISABLE_ICALL_TABLES
8500 const IcallTypeDesc *imap = NULL;
8503 g_assert (method != NULL);
8505 if (method->is_inflated)
8506 method = ((MonoMethodInflated *) method)->declaring;
8508 if (method->klass->nested_in) {
8509 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8513 mname [pos++] = '/';
8516 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8522 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8527 #ifndef DISABLE_ICALL_TABLES
8528 imap = find_class_icalls (mname);
8531 mname [typelen] = ':';
8532 mname [typelen + 1] = ':';
8534 mlen = strlen (method->name);
8535 memcpy (mname + typelen + 2, method->name, mlen);
8536 sigstart = mname + typelen + 2 + mlen;
8539 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8540 siglen = strlen (tmpsig);
8541 if (typelen + mlen + siglen + 6 > sizeof (mname))
8544 memcpy (sigstart + 1, tmpsig, siglen);
8545 sigstart [siglen + 1] = ')';
8546 sigstart [siglen + 2] = 0;
8551 res = g_hash_table_lookup (icall_hash, mname);
8554 *uses_handles = FALSE;
8555 mono_icall_unlock ();;
8558 /* try without signature */
8560 res = g_hash_table_lookup (icall_hash, mname);
8563 *uses_handles = FALSE;
8564 mono_icall_unlock ();
8568 #ifdef DISABLE_ICALL_TABLES
8569 mono_icall_unlock ();
8570 /* Fail only when the result is actually used */
8571 /* mono_marshal_get_native_wrapper () depends on this */
8572 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8573 return ves_icall_System_String_ctor_RedirectToCreateString;
8575 return no_icall_table;
8577 /* it wasn't found in the static call tables */
8580 *uses_handles = FALSE;
8581 mono_icall_unlock ();
8584 res = find_method_icall (imap, sigstart - mlen);
8587 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8588 mono_icall_unlock ();
8591 /* try _with_ signature */
8593 res = find_method_icall (imap, sigstart - mlen);
8596 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8597 mono_icall_unlock ();
8601 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8602 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8603 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8604 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8605 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");
8606 g_print ("If you see other errors or faults after this message they are probably related\n");
8607 g_print ("and you need to fix your mono install first.\n");
8609 mono_icall_unlock ();
8616 mono_lookup_internal_call (MonoMethod *method)
8618 return mono_lookup_internal_call_full (method, NULL);
8621 #ifdef ENABLE_ICALL_SYMBOL_MAP
8623 func_cmp (gconstpointer key, gconstpointer p)
8625 return (gsize)key - (gsize)*(gsize*)p;
8630 * mono_lookup_icall_symbol:
8632 * Given the icall METHOD, returns its C symbol.
8635 mono_lookup_icall_symbol (MonoMethod *m)
8637 #ifdef DISABLE_ICALL_TABLES
8638 g_assert_not_reached ();
8641 #ifdef ENABLE_ICALL_SYMBOL_MAP
8645 static gconstpointer *functions_sorted;
8646 static const char**symbols_sorted;
8647 static gboolean inited;
8652 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8653 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8654 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8655 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8656 /* Bubble sort the two arrays */
8660 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8661 if (functions_sorted [i] > functions_sorted [i + 1]) {
8664 tmp = functions_sorted [i];
8665 functions_sorted [i] = functions_sorted [i + 1];
8666 functions_sorted [i + 1] = tmp;
8667 tmp = symbols_sorted [i];
8668 symbols_sorted [i] = symbols_sorted [i + 1];
8669 symbols_sorted [i + 1] = tmp;
8676 func = mono_lookup_internal_call (m);
8679 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8683 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8685 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8686 g_assert_not_reached ();
8693 type_from_typename (char *type_name)
8695 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8697 if (!strcmp (type_name, "int"))
8698 klass = mono_defaults.int_class;
8699 else if (!strcmp (type_name, "ptr"))
8700 klass = mono_defaults.int_class;
8701 else if (!strcmp (type_name, "void"))
8702 klass = mono_defaults.void_class;
8703 else if (!strcmp (type_name, "int32"))
8704 klass = mono_defaults.int32_class;
8705 else if (!strcmp (type_name, "uint32"))
8706 klass = mono_defaults.uint32_class;
8707 else if (!strcmp (type_name, "int8"))
8708 klass = mono_defaults.sbyte_class;
8709 else if (!strcmp (type_name, "uint8"))
8710 klass = mono_defaults.byte_class;
8711 else if (!strcmp (type_name, "int16"))
8712 klass = mono_defaults.int16_class;
8713 else if (!strcmp (type_name, "uint16"))
8714 klass = mono_defaults.uint16_class;
8715 else if (!strcmp (type_name, "long"))
8716 klass = mono_defaults.int64_class;
8717 else if (!strcmp (type_name, "ulong"))
8718 klass = mono_defaults.uint64_class;
8719 else if (!strcmp (type_name, "float"))
8720 klass = mono_defaults.single_class;
8721 else if (!strcmp (type_name, "double"))
8722 klass = mono_defaults.double_class;
8723 else if (!strcmp (type_name, "object"))
8724 klass = mono_defaults.object_class;
8725 else if (!strcmp (type_name, "obj"))
8726 klass = mono_defaults.object_class;
8727 else if (!strcmp (type_name, "string"))
8728 klass = mono_defaults.string_class;
8729 else if (!strcmp (type_name, "bool"))
8730 klass = mono_defaults.boolean_class;
8731 else if (!strcmp (type_name, "boolean"))
8732 klass = mono_defaults.boolean_class;
8734 g_error ("%s", type_name);
8735 g_assert_not_reached ();
8737 return &klass->byval_arg;
8741 * LOCKING: Take the corlib image lock.
8743 MonoMethodSignature*
8744 mono_create_icall_signature (const char *sigstr)
8749 MonoMethodSignature *res, *res2;
8750 MonoImage *corlib = mono_defaults.corlib;
8752 mono_image_lock (corlib);
8753 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8754 mono_image_unlock (corlib);
8759 parts = g_strsplit (sigstr, " ", 256);
8768 res = mono_metadata_signature_alloc (corlib, len - 1);
8773 * Under windows, the default pinvoke calling convention is STDCALL but
8776 res->call_convention = MONO_CALL_C;
8779 res->ret = type_from_typename (parts [0]);
8780 for (i = 1; i < len; ++i) {
8781 res->params [i - 1] = type_from_typename (parts [i]);
8786 mono_image_lock (corlib);
8787 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8789 res = res2; /*Value is allocated in the image pool*/
8791 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8792 mono_image_unlock (corlib);
8798 mono_find_jit_icall_by_name (const char *name)
8800 MonoJitICallInfo *info;
8801 g_assert (jit_icall_hash_name);
8804 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8805 mono_icall_unlock ();
8810 mono_find_jit_icall_by_addr (gconstpointer addr)
8812 MonoJitICallInfo *info;
8813 g_assert (jit_icall_hash_addr);
8816 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8817 mono_icall_unlock ();
8823 * mono_get_jit_icall_info:
8825 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8826 * caller should access it while holding the icall lock.
8829 mono_get_jit_icall_info (void)
8831 return jit_icall_hash_name;
8835 * mono_lookup_jit_icall_symbol:
8837 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8840 mono_lookup_jit_icall_symbol (const char *name)
8842 MonoJitICallInfo *info;
8843 const char *res = NULL;
8846 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8848 res = info->c_symbol;
8849 mono_icall_unlock ();
8854 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8857 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8858 mono_icall_unlock ();
8862 * 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
8863 * icalls without wrappers in some cases.
8866 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8868 MonoJitICallInfo *info;
8875 if (!jit_icall_hash_name) {
8876 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8877 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8880 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8881 g_warning ("jit icall already defined \"%s\"\n", name);
8882 g_assert_not_reached ();
8885 info = g_new0 (MonoJitICallInfo, 1);
8890 info->c_symbol = c_symbol;
8891 info->no_raise = no_raise;
8894 info->wrapper = func;
8896 info->wrapper = NULL;
8899 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8900 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8902 mono_icall_unlock ();
8907 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8909 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);