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;
7397 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7398 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7399 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7400 or klass is the generic container class and generic_inst is the instantiation.
7402 when we go to the parent, if the parent is an open constructed type, we need to
7403 replace the type parameters by the definitions from the generic_inst, and then take it
7404 apart again into the klass and the generic_inst.
7406 For cases like this:
7407 class C<T> : B<T, int> {
7408 public override void Foo () { ... }
7410 class B<U,V> : A<HashMap<U,V>> {
7411 public override void Foo () { ... }
7414 public virtual void Foo () { ... }
7417 if at each iteration the parent isn't open, we can skip inflating it. if at some
7418 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7421 MonoGenericContext *parent_inst = NULL;
7422 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7423 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7424 if (!mono_error_ok (&error)) {
7425 mono_error_set_pending_exception (&error);
7429 if (parent->generic_class) {
7430 parent_inst = mono_class_get_context (parent);
7431 parent = parent->generic_class->container_class;
7434 mono_class_setup_vtable (parent);
7435 if (parent->vtable_size <= slot)
7438 generic_inst = parent_inst;
7441 klass = klass->parent;
7444 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7445 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7446 if (!mono_error_ok (&error)) {
7447 mono_error_set_pending_exception (&error);
7451 generic_inst = NULL;
7453 if (klass->generic_class) {
7454 generic_inst = mono_class_get_context (klass);
7455 klass = klass->generic_class->container_class;
7461 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7462 if (!mono_error_ok (&error)) {
7463 mono_error_set_pending_exception (&error);
7468 if (klass == method->klass)
7471 /*This is possible if definition == FALSE.
7472 * Do it here to be really sure we don't read invalid memory.
7474 if (slot >= klass->vtable_size)
7477 mono_class_setup_vtable (klass);
7479 result = klass->vtable [slot];
7480 if (result == NULL) {
7481 /* It is an abstract method */
7482 gpointer iter = NULL;
7483 while ((result = mono_class_get_methods (klass, &iter)))
7484 if (result->slot == slot)
7491 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7492 mono_error_set_pending_exception (&error);
7496 ICALL_EXPORT MonoString*
7497 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7499 MonoMethod *method = m->method;
7501 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7506 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7508 iter->sig = *(MonoMethodSignature**)argsp;
7510 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7511 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7514 /* FIXME: it's not documented what start is exactly... */
7518 iter->args = argsp + sizeof (gpointer);
7520 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7522 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7525 ICALL_EXPORT MonoTypedRef
7526 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7528 guint32 i, arg_size;
7532 i = iter->sig->sentinelpos + iter->next_arg;
7534 g_assert (i < iter->sig->param_count);
7536 res.type = iter->sig->params [i];
7537 res.klass = mono_class_from_mono_type (res.type);
7538 arg_size = mono_type_stack_size (res.type, &align);
7539 #if defined(__arm__) || defined(__mips__)
7540 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7542 res.value = iter->args;
7543 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7544 /* Values are stored as 8 byte register sized objects, but 'value'
7545 * is dereferenced as a pointer in other routines.
7547 res.value = (char*)res.value + 4;
7549 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7550 if (arg_size <= sizeof (gpointer)) {
7552 int padding = arg_size - mono_type_size (res.type, &dummy);
7553 res.value = (guint8*)res.value + padding;
7556 iter->args = (char*)iter->args + arg_size;
7559 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7564 ICALL_EXPORT MonoTypedRef
7565 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7567 guint32 i, arg_size;
7571 i = iter->sig->sentinelpos + iter->next_arg;
7573 g_assert (i < iter->sig->param_count);
7575 while (i < iter->sig->param_count) {
7576 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7578 res.type = iter->sig->params [i];
7579 res.klass = mono_class_from_mono_type (res.type);
7580 /* FIXME: endianess issue... */
7581 arg_size = mono_type_stack_size (res.type, &align);
7582 #if defined(__arm__) || defined(__mips__)
7583 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7585 res.value = iter->args;
7586 iter->args = (char*)iter->args + arg_size;
7588 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7591 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7599 ICALL_EXPORT MonoType*
7600 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7604 i = iter->sig->sentinelpos + iter->next_arg;
7606 g_assert (i < iter->sig->param_count);
7608 return iter->sig->params [i];
7611 ICALL_EXPORT MonoObject*
7612 mono_TypedReference_ToObject (MonoTypedRef* tref)
7615 MonoObject *result = NULL;
7616 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7617 MonoObject** objp = (MonoObject **)tref->value;
7621 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7622 mono_error_set_pending_exception (&error);
7626 ICALL_EXPORT MonoTypedRef
7627 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7630 MonoReflectionField *f;
7632 MonoType *ftype = NULL;
7636 memset (&res, 0, sizeof (res));
7639 g_assert (mono_array_length (fields) > 0);
7641 klass = target->vtable->klass;
7643 for (i = 0; i < mono_array_length (fields); ++i) {
7644 f = mono_array_get (fields, MonoReflectionField*, i);
7646 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7649 if (f->field->parent != klass) {
7650 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7654 p = (guint8*)target + f->field->offset;
7656 p += f->field->offset - sizeof (MonoObject);
7657 klass = mono_class_from_mono_type (f->field->type);
7658 ftype = f->field->type;
7662 res.klass = mono_class_from_mono_type (ftype);
7669 prelink_method (MonoMethod *method, MonoError *error)
7671 const char *exc_class, *exc_arg;
7673 mono_error_init (error);
7674 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7676 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7678 mono_error_set_exception_instance (error,
7679 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7682 /* create the wrapper, too? */
7686 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7690 prelink_method (method->method, &error);
7691 mono_error_set_pending_exception (&error);
7695 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7698 MonoClass *klass = mono_class_from_mono_type (type->type);
7700 gpointer iter = NULL;
7702 mono_class_init_checked (klass, &error);
7703 if (mono_error_set_pending_exception (&error))
7706 while ((m = mono_class_get_methods (klass, &iter))) {
7707 prelink_method (m, &error);
7708 if (mono_error_set_pending_exception (&error))
7713 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7715 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7716 gint32 const **exponents,
7717 gunichar2 const **digitLowerTable,
7718 gunichar2 const **digitUpperTable,
7719 gint64 const **tenPowersList,
7720 gint32 const **decHexDigits)
7722 *mantissas = Formatter_MantissaBitsTable;
7723 *exponents = Formatter_TensExponentTable;
7724 *digitLowerTable = Formatter_DigitLowerTable;
7725 *digitUpperTable = Formatter_DigitUpperTable;
7726 *tenPowersList = Formatter_TenPowersList;
7727 *decHexDigits = Formatter_DecHexDigits;
7731 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7732 * and avoid useless allocations.
7735 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7737 MonoReflectionType *rt;
7741 mono_error_init (error);
7742 for (i = 0; i < type->num_mods; ++i) {
7743 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7748 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7749 return_val_if_nok (error, NULL);
7751 for (i = 0; i < type->num_mods; ++i) {
7752 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7753 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7754 return_val_if_nok (error, NULL);
7756 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7757 return_val_if_nok (error, NULL);
7759 mono_array_setref (res, count, rt);
7766 ICALL_EXPORT MonoArray*
7767 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7770 MonoType *type = param->ClassImpl->type;
7771 MonoClass *member_class = mono_object_class (param->MemberImpl);
7772 MonoMethod *method = NULL;
7775 MonoMethodSignature *sig;
7778 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7779 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7780 method = rmethod->method;
7781 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7782 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7783 if (!(method = prop->property->get))
7784 method = prop->property->set;
7787 char *type_name = mono_type_get_full_name (member_class);
7788 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7789 MonoException *ex = mono_get_exception_not_supported (msg);
7792 mono_set_pending_exception (ex);
7796 image = method->klass->image;
7797 pos = param->PositionImpl;
7798 sig = mono_method_signature (method);
7802 type = sig->params [pos];
7804 res = type_array_from_modifiers (image, type, optional, &error);
7805 mono_error_set_pending_exception (&error);
7810 get_property_type (MonoProperty *prop)
7812 MonoMethodSignature *sig;
7814 sig = mono_method_signature (prop->get);
7816 } else if (prop->set) {
7817 sig = mono_method_signature (prop->set);
7818 return sig->params [sig->param_count - 1];
7823 ICALL_EXPORT MonoArray*
7824 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7827 MonoType *type = get_property_type (property->property);
7828 MonoImage *image = property->klass->image;
7833 res = type_array_from_modifiers (image, type, optional, &error);
7834 mono_error_set_pending_exception (&error);
7839 *Construct a MonoType suited to be used to decode a constant blob object.
7841 * @type is the target type which will be constructed
7842 * @blob_type is the blob type, for example, that comes from the constant table
7843 * @real_type is the expected constructed type.
7846 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7848 type->type = blob_type;
7849 type->data.klass = NULL;
7850 if (blob_type == MONO_TYPE_CLASS)
7851 type->data.klass = mono_defaults.object_class;
7852 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7853 /* For enums, we need to use the base type */
7854 type->type = MONO_TYPE_VALUETYPE;
7855 type->data.klass = mono_class_from_mono_type (real_type);
7857 type->data.klass = mono_class_from_mono_type (real_type);
7860 ICALL_EXPORT MonoObject*
7861 property_info_get_default_value (MonoReflectionProperty *property)
7865 MonoProperty *prop = property->property;
7866 MonoType *type = get_property_type (prop);
7867 MonoDomain *domain = mono_object_domain (property);
7868 MonoTypeEnum def_type;
7869 const char *def_value;
7872 mono_class_init (prop->parent);
7874 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7875 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7879 def_value = mono_class_get_property_default_value (prop, &def_type);
7881 mono_type_from_blob_type (&blob_type, def_type, type);
7882 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7884 mono_error_set_pending_exception (&error);
7888 ICALL_EXPORT MonoBoolean
7889 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7892 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7893 MonoCustomAttrInfo *cinfo;
7896 mono_class_init_checked (attr_class, &error);
7897 if (mono_error_set_pending_exception (&error))
7900 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7901 if (!is_ok (&error)) {
7902 mono_error_set_pending_exception (&error);
7907 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7909 mono_custom_attrs_free (cinfo);
7913 ICALL_EXPORT MonoArray*
7914 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7916 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7921 mono_class_init_checked (attr_class, &error);
7922 if (mono_error_set_pending_exception (&error))
7926 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7927 if (!mono_error_ok (&error)) {
7928 mono_error_set_pending_exception (&error);
7935 ICALL_EXPORT MonoArray*
7936 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7940 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7941 mono_error_set_pending_exception (&error);
7946 ICALL_EXPORT MonoString*
7947 ves_icall_Mono_Runtime_GetDisplayName (void)
7950 MonoString *display_name;
7952 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7953 display_name = mono_string_new (mono_domain_get (), info);
7955 return display_name;
7958 ICALL_EXPORT MonoString*
7959 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7962 MonoString *message;
7966 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7967 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7970 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7972 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7973 if (mono_error_set_pending_exception (&error))
7980 ICALL_EXPORT gpointer
7981 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7983 return GetCurrentProcess ();
7986 ICALL_EXPORT MonoBoolean
7987 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7989 return GetExitCodeProcess (handle, (guint32*) exitcode);
7992 ICALL_EXPORT MonoBoolean
7993 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7995 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7996 return CloseHandle (handle);
7998 return CloseProcess (handle);
8002 ICALL_EXPORT MonoBoolean
8003 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8005 return TerminateProcess (handle, exitcode);
8009 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8012 return WaitForInputIdle (handle, milliseconds);
8014 /*TODO: Not implemented*/
8015 return WAIT_TIMEOUT;
8019 ICALL_EXPORT MonoBoolean
8020 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8022 return GetProcessWorkingSetSize (handle, min, max);
8025 ICALL_EXPORT MonoBoolean
8026 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8028 return SetProcessWorkingSetSize (handle, min, max);
8031 ICALL_EXPORT MonoBoolean
8032 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8034 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8038 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8040 return mono_process_current_pid ();
8044 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8046 return GetPriorityClass (handle);
8049 ICALL_EXPORT MonoBoolean
8050 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8052 return SetPriorityClass (handle, priorityClass);
8055 #ifndef DISABLE_ICALL_TABLES
8057 #define ICALL_TYPE(id,name,first)
8058 #define ICALL(id,name,func) Icall_ ## id,
8059 #define HANDLES(inner) inner
8062 #include "metadata/icall-def.h"
8068 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8069 #define ICALL(id,name,func)
8071 #define HANDLES(inner) inner
8073 #include "metadata/icall-def.h"
8079 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8080 #define ICALL(id,name,func)
8082 #define HANDLES(inner) inner
8084 guint16 first_icall;
8087 static const IcallTypeDesc
8088 icall_type_descs [] = {
8089 #include "metadata/icall-def.h"
8093 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8096 #define HANDLES(inner) inner
8098 #define ICALL_TYPE(id,name,first)
8101 #ifdef HAVE_ARRAY_ELEM_INIT
8102 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8103 #define MSGSTRFIELD1(line) str##line
8105 static const struct msgstrtn_t {
8106 #define ICALL(id,name,func)
8108 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8109 #include "metadata/icall-def.h"
8111 } icall_type_names_str = {
8112 #define ICALL_TYPE(id,name,first) (name),
8113 #include "metadata/icall-def.h"
8116 static const guint16 icall_type_names_idx [] = {
8117 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8118 #include "metadata/icall-def.h"
8121 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8123 static const struct msgstr_t {
8125 #define ICALL_TYPE(id,name,first)
8126 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8127 #include "metadata/icall-def.h"
8129 } icall_names_str = {
8130 #define ICALL(id,name,func) (name),
8131 #include "metadata/icall-def.h"
8134 static const guint16 icall_names_idx [] = {
8135 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8136 #include "metadata/icall-def.h"
8139 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8145 #define ICALL_TYPE(id,name,first) name,
8146 #define ICALL(id,name,func)
8147 static const char* const
8148 icall_type_names [] = {
8149 #include "metadata/icall-def.h"
8153 #define icall_type_name_get(id) (icall_type_names [(id)])
8157 #define ICALL_TYPE(id,name,first)
8158 #define ICALL(id,name,func) name,
8159 static const char* const
8161 #include "metadata/icall-def.h"
8164 #define icall_name_get(id) icall_names [(id)]
8166 #endif /* !HAVE_ARRAY_ELEM_INIT */
8169 #define HANDLES(inner) inner
8172 #define ICALL_TYPE(id,name,first)
8173 #define ICALL(id,name,func) func,
8174 static const gconstpointer
8175 icall_functions [] = {
8176 #include "metadata/icall-def.h"
8180 #ifdef ENABLE_ICALL_SYMBOL_MAP
8182 #define HANDLES(inner) inner
8185 #define ICALL_TYPE(id,name,first)
8186 #define ICALL(id,name,func) #func,
8187 static const gconstpointer
8188 icall_symbols [] = {
8189 #include "metadata/icall-def.h"
8196 #define ICALL_TYPE(id,name,first)
8197 #define ICALL(id,name,func) 0,
8199 #define HANDLES(inner) 1,
8201 icall_uses_handles [] = {
8202 #include "metadata/icall-def.h"
8207 #endif /* DISABLE_ICALL_TABLES */
8209 static mono_mutex_t icall_mutex;
8210 static GHashTable *icall_hash = NULL;
8211 static GHashTable *jit_icall_hash_name = NULL;
8212 static GHashTable *jit_icall_hash_addr = NULL;
8215 mono_icall_init (void)
8217 #ifndef DISABLE_ICALL_TABLES
8220 /* check that tables are sorted: disable in release */
8223 const char *prev_class = NULL;
8224 const char *prev_method;
8226 for (i = 0; i < Icall_type_num; ++i) {
8227 const IcallTypeDesc *desc;
8230 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8231 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8232 prev_class = icall_type_name_get (i);
8233 desc = &icall_type_descs [i];
8234 num_icalls = icall_desc_num_icalls (desc);
8235 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8236 for (j = 0; j < num_icalls; ++j) {
8237 const char *methodn = icall_name_get (desc->first_icall + j);
8238 if (prev_method && strcmp (prev_method, methodn) >= 0)
8239 g_print ("method %s should come before method %s\n", methodn, prev_method);
8240 prev_method = methodn;
8246 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8247 mono_os_mutex_init (&icall_mutex);
8251 mono_icall_lock (void)
8253 mono_locks_os_acquire (&icall_mutex, IcallLock);
8257 mono_icall_unlock (void)
8259 mono_locks_os_release (&icall_mutex, IcallLock);
8263 mono_icall_cleanup (void)
8265 g_hash_table_destroy (icall_hash);
8266 g_hash_table_destroy (jit_icall_hash_name);
8267 g_hash_table_destroy (jit_icall_hash_addr);
8268 mono_os_mutex_destroy (&icall_mutex);
8272 * mono_add_internal_call:
8273 * @name: method specification to surface to the managed world
8274 * @method: pointer to a C method to invoke when the method is called
8276 * This method surfaces the C function pointed by @method as a method
8277 * that has been surfaced in managed code with the method specified in
8278 * @name as an internal call.
8280 * Internal calls are surfaced to all app domains loaded and they are
8281 * accessibly by a type with the specified name.
8283 * You must provide a fully qualified type name, that is namespaces
8284 * and type name, followed by a colon and the method name, with an
8285 * optional signature to bind.
8287 * For example, the following are all valid declarations:
8289 * "MyApp.Services.ScriptService:Accelerate"
8290 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8292 * You use method parameters in cases where there might be more than
8293 * one surface method to managed code. That way you can register different
8294 * internal calls for different method overloads.
8296 * The internal calls are invoked with no marshalling. This means that .NET
8297 * types like System.String are exposed as `MonoString *` parameters. This is
8298 * different than the way that strings are surfaced in P/Invoke.
8300 * For more information on how the parameters are marshalled, see the
8301 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8304 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8305 * reference for more information on the format of method descriptions.
8308 mono_add_internal_call (const char *name, gconstpointer method)
8312 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8314 mono_icall_unlock ();
8317 #ifndef DISABLE_ICALL_TABLES
8319 #ifdef HAVE_ARRAY_ELEM_INIT
8321 compare_method_imap (const void *key, const void *elem)
8323 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8324 return strcmp (key, method_name);
8328 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8330 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);
8333 return (nameslot - &icall_names_idx [0]);
8337 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8339 gsize slotnum = find_slot_icall (imap, name);
8342 return (gboolean)icall_uses_handles [slotnum];
8346 find_method_icall (const IcallTypeDesc *imap, const char *name)
8348 gsize slotnum = find_slot_icall (imap, name);
8351 return (gpointer)icall_functions [slotnum];
8355 compare_class_imap (const void *key, const void *elem)
8357 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8358 return strcmp (key, class_name);
8361 static const IcallTypeDesc*
8362 find_class_icalls (const char *name)
8364 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);
8367 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8370 #else /* HAVE_ARRAY_ELEM_INIT */
8373 compare_method_imap (const void *key, const void *elem)
8375 const char** method_name = (const char**)elem;
8376 return strcmp (key, *method_name);
8380 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8382 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8385 return nameslot - icall_names;
8389 find_method_icall (const IcallTypeDesc *imap, const char *name)
8391 gsize slotnum = find_slot_icall (imap, name);
8394 return (gpointer)icall_functions [slotnum];
8398 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8400 gsize slotnum = find_slot_icall (imap, name);
8403 return (gboolean)icall_uses_handles [slotnum];
8407 compare_class_imap (const void *key, const void *elem)
8409 const char** class_name = (const char**)elem;
8410 return strcmp (key, *class_name);
8413 static const IcallTypeDesc*
8414 find_class_icalls (const char *name)
8416 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8419 return &icall_type_descs [nameslot - icall_type_names];
8422 #endif /* HAVE_ARRAY_ELEM_INIT */
8424 #endif /* DISABLE_ICALL_TABLES */
8427 * we should probably export this as an helper (handle nested types).
8428 * Returns the number of chars written in buf.
8431 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8433 int nspacelen, cnamelen;
8434 nspacelen = strlen (klass->name_space);
8435 cnamelen = strlen (klass->name);
8436 if (nspacelen + cnamelen + 2 > bufsize)
8439 memcpy (buf, klass->name_space, nspacelen);
8440 buf [nspacelen ++] = '.';
8442 memcpy (buf + nspacelen, klass->name, cnamelen);
8443 buf [nspacelen + cnamelen] = 0;
8444 return nspacelen + cnamelen;
8447 #ifdef DISABLE_ICALL_TABLES
8449 no_icall_table (void)
8451 g_assert_not_reached ();
8456 * mono_lookup_internal_call_full:
8457 * @method: the method to look up
8458 * @uses_handles: out argument if method needs handles around managed objects.
8460 * Returns a pointer to the icall code for the given method. If
8461 * uses_handles is not NULL, it will be set to TRUE if the method
8462 * needs managed objects wrapped using the infrastructure in handle.h
8464 * If the method is not found, warns and returns NULL.
8467 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8472 int typelen = 0, mlen, siglen;
8474 #ifndef DISABLE_ICALL_TABLES
8475 const IcallTypeDesc *imap = NULL;
8478 g_assert (method != NULL);
8480 if (method->is_inflated)
8481 method = ((MonoMethodInflated *) method)->declaring;
8483 if (method->klass->nested_in) {
8484 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8488 mname [pos++] = '/';
8491 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8497 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8502 #ifndef DISABLE_ICALL_TABLES
8503 imap = find_class_icalls (mname);
8506 mname [typelen] = ':';
8507 mname [typelen + 1] = ':';
8509 mlen = strlen (method->name);
8510 memcpy (mname + typelen + 2, method->name, mlen);
8511 sigstart = mname + typelen + 2 + mlen;
8514 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8515 siglen = strlen (tmpsig);
8516 if (typelen + mlen + siglen + 6 > sizeof (mname))
8519 memcpy (sigstart + 1, tmpsig, siglen);
8520 sigstart [siglen + 1] = ')';
8521 sigstart [siglen + 2] = 0;
8526 res = g_hash_table_lookup (icall_hash, mname);
8529 *uses_handles = FALSE;
8530 mono_icall_unlock ();;
8533 /* try without signature */
8535 res = g_hash_table_lookup (icall_hash, mname);
8538 *uses_handles = FALSE;
8539 mono_icall_unlock ();
8543 #ifdef DISABLE_ICALL_TABLES
8544 mono_icall_unlock ();
8545 /* Fail only when the result is actually used */
8546 /* mono_marshal_get_native_wrapper () depends on this */
8547 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8548 return ves_icall_System_String_ctor_RedirectToCreateString;
8550 return no_icall_table;
8552 /* it wasn't found in the static call tables */
8555 *uses_handles = FALSE;
8556 mono_icall_unlock ();
8559 res = find_method_icall (imap, sigstart - mlen);
8562 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8563 mono_icall_unlock ();
8566 /* try _with_ signature */
8568 res = find_method_icall (imap, sigstart - mlen);
8571 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8572 mono_icall_unlock ();
8576 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8577 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8578 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8579 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8580 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");
8581 g_print ("If you see other errors or faults after this message they are probably related\n");
8582 g_print ("and you need to fix your mono install first.\n");
8584 mono_icall_unlock ();
8591 mono_lookup_internal_call (MonoMethod *method)
8593 return mono_lookup_internal_call_full (method, NULL);
8596 #ifdef ENABLE_ICALL_SYMBOL_MAP
8598 func_cmp (gconstpointer key, gconstpointer p)
8600 return (gsize)key - (gsize)*(gsize*)p;
8605 * mono_lookup_icall_symbol:
8607 * Given the icall METHOD, returns its C symbol.
8610 mono_lookup_icall_symbol (MonoMethod *m)
8612 #ifdef DISABLE_ICALL_TABLES
8613 g_assert_not_reached ();
8616 #ifdef ENABLE_ICALL_SYMBOL_MAP
8620 static gconstpointer *functions_sorted;
8621 static const char**symbols_sorted;
8622 static gboolean inited;
8627 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8628 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8629 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8630 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8631 /* Bubble sort the two arrays */
8635 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8636 if (functions_sorted [i] > functions_sorted [i + 1]) {
8639 tmp = functions_sorted [i];
8640 functions_sorted [i] = functions_sorted [i + 1];
8641 functions_sorted [i + 1] = tmp;
8642 tmp = symbols_sorted [i];
8643 symbols_sorted [i] = symbols_sorted [i + 1];
8644 symbols_sorted [i + 1] = tmp;
8651 func = mono_lookup_internal_call (m);
8654 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8658 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8660 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8661 g_assert_not_reached ();
8668 type_from_typename (char *type_name)
8670 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8672 if (!strcmp (type_name, "int"))
8673 klass = mono_defaults.int_class;
8674 else if (!strcmp (type_name, "ptr"))
8675 klass = mono_defaults.int_class;
8676 else if (!strcmp (type_name, "void"))
8677 klass = mono_defaults.void_class;
8678 else if (!strcmp (type_name, "int32"))
8679 klass = mono_defaults.int32_class;
8680 else if (!strcmp (type_name, "uint32"))
8681 klass = mono_defaults.uint32_class;
8682 else if (!strcmp (type_name, "int8"))
8683 klass = mono_defaults.sbyte_class;
8684 else if (!strcmp (type_name, "uint8"))
8685 klass = mono_defaults.byte_class;
8686 else if (!strcmp (type_name, "int16"))
8687 klass = mono_defaults.int16_class;
8688 else if (!strcmp (type_name, "uint16"))
8689 klass = mono_defaults.uint16_class;
8690 else if (!strcmp (type_name, "long"))
8691 klass = mono_defaults.int64_class;
8692 else if (!strcmp (type_name, "ulong"))
8693 klass = mono_defaults.uint64_class;
8694 else if (!strcmp (type_name, "float"))
8695 klass = mono_defaults.single_class;
8696 else if (!strcmp (type_name, "double"))
8697 klass = mono_defaults.double_class;
8698 else if (!strcmp (type_name, "object"))
8699 klass = mono_defaults.object_class;
8700 else if (!strcmp (type_name, "obj"))
8701 klass = mono_defaults.object_class;
8702 else if (!strcmp (type_name, "string"))
8703 klass = mono_defaults.string_class;
8704 else if (!strcmp (type_name, "bool"))
8705 klass = mono_defaults.boolean_class;
8706 else if (!strcmp (type_name, "boolean"))
8707 klass = mono_defaults.boolean_class;
8709 g_error ("%s", type_name);
8710 g_assert_not_reached ();
8712 return &klass->byval_arg;
8716 * LOCKING: Take the corlib image lock.
8718 MonoMethodSignature*
8719 mono_create_icall_signature (const char *sigstr)
8724 MonoMethodSignature *res, *res2;
8725 MonoImage *corlib = mono_defaults.corlib;
8727 mono_image_lock (corlib);
8728 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8729 mono_image_unlock (corlib);
8734 parts = g_strsplit (sigstr, " ", 256);
8743 res = mono_metadata_signature_alloc (corlib, len - 1);
8748 * Under windows, the default pinvoke calling convention is STDCALL but
8751 res->call_convention = MONO_CALL_C;
8754 res->ret = type_from_typename (parts [0]);
8755 for (i = 1; i < len; ++i) {
8756 res->params [i - 1] = type_from_typename (parts [i]);
8761 mono_image_lock (corlib);
8762 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8764 res = res2; /*Value is allocated in the image pool*/
8766 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8767 mono_image_unlock (corlib);
8773 mono_find_jit_icall_by_name (const char *name)
8775 MonoJitICallInfo *info;
8776 g_assert (jit_icall_hash_name);
8779 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8780 mono_icall_unlock ();
8785 mono_find_jit_icall_by_addr (gconstpointer addr)
8787 MonoJitICallInfo *info;
8788 g_assert (jit_icall_hash_addr);
8791 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8792 mono_icall_unlock ();
8798 * mono_get_jit_icall_info:
8800 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8801 * caller should access it while holding the icall lock.
8804 mono_get_jit_icall_info (void)
8806 return jit_icall_hash_name;
8810 * mono_lookup_jit_icall_symbol:
8812 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8815 mono_lookup_jit_icall_symbol (const char *name)
8817 MonoJitICallInfo *info;
8818 const char *res = NULL;
8821 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8823 res = info->c_symbol;
8824 mono_icall_unlock ();
8829 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8832 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8833 mono_icall_unlock ();
8837 * 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
8838 * icalls without wrappers in some cases.
8841 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8843 MonoJitICallInfo *info;
8850 if (!jit_icall_hash_name) {
8851 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8852 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8855 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8856 g_warning ("jit icall already defined \"%s\"\n", name);
8857 g_assert_not_reached ();
8860 info = g_new0 (MonoJitICallInfo, 1);
8865 info->c_symbol = c_symbol;
8866 info->no_raise = no_raise;
8869 info->wrapper = func;
8871 info->wrapper = NULL;
8874 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8875 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8877 mono_icall_unlock ();
8882 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8884 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);