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/assembly.h>
47 #include <mono/metadata/tabledefs.h>
48 #include <mono/metadata/exception.h>
49 #include <mono/metadata/exception-internals.h>
50 #include <mono/metadata/file-io.h>
51 #include <mono/metadata/console-io.h>
52 #include <mono/metadata/mono-route.h>
53 #include <mono/metadata/socket-io.h>
54 #include <mono/metadata/mono-endian.h>
55 #include <mono/metadata/tokentype.h>
56 #include <mono/metadata/domain-internals.h>
57 #include <mono/metadata/metadata-internals.h>
58 #include <mono/metadata/class-internals.h>
59 #include <mono/metadata/reflection-internals.h>
60 #include <mono/metadata/marshal.h>
61 #include <mono/metadata/gc-internals.h>
62 #include <mono/metadata/mono-gc.h>
63 #include <mono/metadata/rand.h>
64 #include <mono/metadata/sysmath.h>
65 #include <mono/metadata/string-icalls.h>
66 #include <mono/metadata/debug-helpers.h>
67 #include <mono/metadata/process.h>
68 #include <mono/metadata/environment.h>
69 #include <mono/metadata/profiler-private.h>
70 #include <mono/metadata/locales.h>
71 #include <mono/metadata/filewatcher.h>
72 #include <mono/metadata/security.h>
73 #include <mono/metadata/mono-config.h>
74 #include <mono/metadata/cil-coff.h>
75 #include <mono/metadata/number-formatter.h>
76 #include <mono/metadata/security-manager.h>
77 #include <mono/metadata/security-core-clr.h>
78 #include <mono/metadata/mono-perfcounters.h>
79 #include <mono/metadata/mono-debug.h>
80 #include <mono/metadata/mono-ptr-array.h>
81 #include <mono/metadata/verify-internals.h>
82 #include <mono/metadata/runtime.h>
83 #include <mono/metadata/file-mmap.h>
84 #include <mono/metadata/seq-points-data.h>
85 #include <mono/metadata/handle.h>
86 #include <mono/io-layer/io-layer.h>
87 #include <mono/utils/monobitset.h>
88 #include <mono/utils/mono-time.h>
89 #include <mono/utils/mono-proclib.h>
90 #include <mono/utils/mono-string.h>
91 #include <mono/utils/mono-error-internals.h>
92 #include <mono/utils/mono-mmap.h>
93 #include <mono/utils/mono-io-portability.h>
94 #include <mono/utils/mono-digest.h>
95 #include <mono/utils/bsearch.h>
96 #include <mono/utils/mono-os-mutex.h>
97 #include <mono/utils/mono-threads.h>
99 #if defined (HOST_WIN32)
103 #include "decimal-ms.h"
104 #include "number-ms.h"
106 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
107 #include <sys/utsname.h>
110 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
112 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
114 /* Lazy class loading functions */
115 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
116 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
117 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
119 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
120 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
123 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
125 static inline MonoBoolean
126 is_generic_parameter (MonoType *type)
128 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
132 mono_class_init_checked (MonoClass *klass, MonoError *error)
134 mono_error_init (error);
136 if (!mono_class_init (klass))
137 mono_error_set_for_class_failure (error, klass);
140 ICALL_EXPORT MonoObject *
141 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
147 MonoObject *result = NULL;
149 ac = (MonoClass *)arr->obj.vtable->klass;
151 esize = mono_array_element_size (ac);
152 ea = (gpointer*)((char*)arr->vector + (pos * esize));
154 if (ac->element_class->valuetype) {
155 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
156 mono_error_set_pending_exception (&error);
158 result = (MonoObject *)*ea;
162 ICALL_EXPORT MonoObject *
163 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
169 MONO_CHECK_ARG_NULL (idxs, NULL);
172 ic = (MonoClass *)io->obj.vtable->klass;
174 ac = (MonoClass *)arr->obj.vtable->klass;
176 g_assert (ic->rank == 1);
177 if (io->bounds != NULL || io->max_length != ac->rank) {
178 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
182 ind = (gint32 *)io->vector;
184 if (arr->bounds == NULL) {
185 if (*ind < 0 || *ind >= arr->max_length) {
186 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
190 return ves_icall_System_Array_GetValueImpl (arr, *ind);
193 for (i = 0; i < ac->rank; i++) {
194 if ((ind [i] < arr->bounds [i].lower_bound) ||
195 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
196 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
201 pos = ind [0] - arr->bounds [0].lower_bound;
202 for (i = 1; i < ac->rank; i++)
203 pos = pos * arr->bounds [i].length + ind [i] -
204 arr->bounds [i].lower_bound;
206 return ves_icall_System_Array_GetValueImpl (arr, pos);
210 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
213 MonoClass *ac, *vc, *ec;
222 mono_error_init (&error);
225 vc = value->vtable->klass;
229 ac = arr->obj.vtable->klass;
230 ec = ac->element_class;
232 esize = mono_array_element_size (ac);
233 ea = (gpointer*)((char*)arr->vector + (pos * esize));
234 va = (gpointer*)((char*)value + sizeof (MonoObject));
236 if (mono_class_is_nullable (ec)) {
237 mono_nullable_init ((guint8*)ea, value, ec);
242 mono_gc_bzero_atomic (ea, esize);
246 #define NO_WIDENING_CONVERSION G_STMT_START{\
247 mono_set_pending_exception (mono_get_exception_argument ( \
248 "value", "not a widening conversion")); \
252 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
253 if (esize < vsize + (extra)) { \
254 mono_set_pending_exception (mono_get_exception_argument ( \
255 "value", "not a widening conversion")); \
260 #define INVALID_CAST G_STMT_START{ \
261 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
262 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
266 /* Check element (destination) type. */
267 switch (ec->byval_arg.type) {
268 case MONO_TYPE_STRING:
269 switch (vc->byval_arg.type) {
270 case MONO_TYPE_STRING:
276 case MONO_TYPE_BOOLEAN:
277 switch (vc->byval_arg.type) {
278 case MONO_TYPE_BOOLEAN:
291 NO_WIDENING_CONVERSION;
300 if (!ec->valuetype) {
301 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
302 if (mono_error_set_pending_exception (&error))
306 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
310 if (mono_object_isinst_checked (value, ec, &error)) {
311 if (ec->has_references)
312 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
314 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
317 if (mono_error_set_pending_exception (&error))
323 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
325 et = ec->byval_arg.type;
326 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
327 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
329 vt = vc->byval_arg.type;
330 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
331 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
333 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
339 case MONO_TYPE_CHAR: \
340 CHECK_WIDENING_CONVERSION(0); \
341 *(etype *) ea = (etype) u64; \
343 /* You can't assign a signed value to an unsigned array. */ \
348 /* You can't assign a floating point number to an integer array. */ \
351 NO_WIDENING_CONVERSION; \
355 #define ASSIGN_SIGNED(etype) G_STMT_START{\
361 CHECK_WIDENING_CONVERSION(0); \
362 *(etype *) ea = (etype) i64; \
364 /* You can assign an unsigned value to a signed array if the array's */ \
365 /* element size is larger than the value size. */ \
370 case MONO_TYPE_CHAR: \
371 CHECK_WIDENING_CONVERSION(1); \
372 *(etype *) ea = (etype) u64; \
374 /* You can't assign a floating point number to an integer array. */ \
377 NO_WIDENING_CONVERSION; \
381 #define ASSIGN_REAL(etype) G_STMT_START{\
385 CHECK_WIDENING_CONVERSION(0); \
386 *(etype *) ea = (etype) r64; \
388 /* All integer values fit into a floating point array, so we don't */ \
389 /* need to CHECK_WIDENING_CONVERSION here. */ \
394 *(etype *) ea = (etype) i64; \
400 case MONO_TYPE_CHAR: \
401 *(etype *) ea = (etype) u64; \
408 u64 = *(guint8 *) va;
411 u64 = *(guint16 *) va;
414 u64 = *(guint32 *) va;
417 u64 = *(guint64 *) va;
423 i64 = *(gint16 *) va;
426 i64 = *(gint32 *) va;
429 i64 = *(gint64 *) va;
432 r64 = *(gfloat *) va;
435 r64 = *(gdouble *) va;
438 u64 = *(guint16 *) va;
440 case MONO_TYPE_BOOLEAN:
441 /* Boolean is only compatible with itself. */
454 NO_WIDENING_CONVERSION;
461 /* If we can't do a direct copy, let's try a widening conversion. */
464 ASSIGN_UNSIGNED (guint16);
466 ASSIGN_UNSIGNED (guint8);
468 ASSIGN_UNSIGNED (guint16);
470 ASSIGN_UNSIGNED (guint32);
472 ASSIGN_UNSIGNED (guint64);
474 ASSIGN_SIGNED (gint8);
476 ASSIGN_SIGNED (gint16);
478 ASSIGN_SIGNED (gint32);
480 ASSIGN_SIGNED (gint64);
482 ASSIGN_REAL (gfloat);
484 ASSIGN_REAL (gdouble);
488 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
492 #undef NO_WIDENING_CONVERSION
493 #undef CHECK_WIDENING_CONVERSION
494 #undef ASSIGN_UNSIGNED
500 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
506 MONO_CHECK_ARG_NULL (idxs,);
508 ic = idxs->obj.vtable->klass;
509 ac = arr->obj.vtable->klass;
511 g_assert (ic->rank == 1);
512 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
513 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
517 ind = (gint32 *)idxs->vector;
519 if (arr->bounds == NULL) {
520 if (*ind < 0 || *ind >= arr->max_length) {
521 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
525 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
529 for (i = 0; i < ac->rank; i++)
530 if ((ind [i] < arr->bounds [i].lower_bound) ||
531 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
532 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
536 pos = ind [0] - arr->bounds [0].lower_bound;
537 for (i = 1; i < ac->rank; i++)
538 pos = pos * arr->bounds [i].length + ind [i] -
539 arr->bounds [i].lower_bound;
541 ves_icall_System_Array_SetValueImpl (arr, value, pos);
544 ICALL_EXPORT MonoArray *
545 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
548 MonoClass *aklass, *klass;
551 gboolean bounded = FALSE;
553 MONO_CHECK_ARG_NULL (type, NULL);
554 MONO_CHECK_ARG_NULL (lengths, NULL);
556 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
558 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
560 for (i = 0; i < mono_array_length (lengths); i++) {
561 if (mono_array_get (lengths, gint32, i) < 0) {
562 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
567 klass = mono_class_from_mono_type (type->type);
568 mono_class_init_checked (klass, &error);
569 if (mono_error_set_pending_exception (&error))
572 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
573 /* vectors are not the same as one dimensional arrays with no-zero bounds */
578 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
580 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
581 for (i = 0; i < aklass->rank; ++i) {
582 sizes [i] = mono_array_get (lengths, guint32, i);
584 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
586 sizes [i + aklass->rank] = 0;
589 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
590 mono_error_set_pending_exception (&error);
595 ICALL_EXPORT MonoArray *
596 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
599 MonoClass *aklass, *klass;
602 gboolean bounded = FALSE;
604 MONO_CHECK_ARG_NULL (type, NULL);
605 MONO_CHECK_ARG_NULL (lengths, NULL);
607 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
609 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
611 for (i = 0; i < mono_array_length (lengths); i++) {
612 if ((mono_array_get (lengths, gint64, i) < 0) ||
613 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
614 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
619 klass = mono_class_from_mono_type (type->type);
620 mono_class_init_checked (klass, &error);
621 if (mono_error_set_pending_exception (&error))
624 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
625 /* vectors are not the same as one dimensional arrays with no-zero bounds */
630 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
632 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
633 for (i = 0; i < aklass->rank; ++i) {
634 sizes [i] = mono_array_get (lengths, guint64, i);
636 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
638 sizes [i + aklass->rank] = 0;
641 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
642 mono_error_set_pending_exception (&error);
648 ves_icall_System_Array_GetRank (MonoObject *arr)
650 return arr->vtable->klass->rank;
654 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
656 gint32 rank = arr->obj.vtable->klass->rank;
659 if ((dimension < 0) || (dimension >= rank)) {
660 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
664 if (arr->bounds == NULL)
665 length = arr->max_length;
667 length = arr->bounds [dimension].length;
669 #ifdef MONO_BIG_ARRAYS
670 if (length > G_MAXINT32) {
671 mono_set_pending_exception (mono_get_exception_overflow ());
679 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
681 gint32 rank = arr->obj.vtable->klass->rank;
683 if ((dimension < 0) || (dimension >= rank)) {
684 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
688 if (arr->bounds == NULL)
689 return arr->max_length;
691 return arr->bounds [dimension].length;
695 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
697 gint32 rank = arr->obj.vtable->klass->rank;
699 if ((dimension < 0) || (dimension >= rank)) {
700 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
704 if (arr->bounds == NULL)
707 return arr->bounds [dimension].lower_bound;
711 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
713 int sz = mono_array_element_size (mono_object_class (arr));
714 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
717 ICALL_EXPORT MonoArray*
718 ves_icall_System_Array_Clone (MonoArray *arr)
721 MonoArray *result = mono_array_clone_checked (arr, &error);
722 mono_error_set_pending_exception (&error);
726 ICALL_EXPORT gboolean
727 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
732 MonoVTable *src_vtable;
733 MonoVTable *dest_vtable;
734 MonoClass *src_class;
735 MonoClass *dest_class;
737 src_vtable = source->obj.vtable;
738 dest_vtable = dest->obj.vtable;
740 if (src_vtable->rank != dest_vtable->rank)
743 if (source->bounds || dest->bounds)
746 /* there's no integer overflow since mono_array_length returns an unsigned integer */
747 if ((dest_idx + length > mono_array_length_fast (dest)) ||
748 (source_idx + length > mono_array_length_fast (source)))
751 src_class = src_vtable->klass->element_class;
752 dest_class = dest_vtable->klass->element_class;
755 * Handle common cases.
758 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
759 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
761 if (src_class == mono_defaults.object_class && dest_class->valuetype)
764 /* Check if we're copying a char[] <==> (u)short[] */
765 if (src_class != dest_class) {
766 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
769 /* 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. */
770 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
774 if (dest_class->valuetype) {
775 element_size = mono_array_element_size (source->obj.vtable->klass);
776 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
777 if (dest_class->has_references) {
778 mono_value_copy_array (dest, dest_idx, source_addr, length);
780 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
781 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
784 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
791 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
797 ac = (MonoClass *)arr->obj.vtable->klass;
799 esize = mono_array_element_size (ac);
800 ea = (gpointer*)((char*)arr->vector + (pos * esize));
802 mono_gc_memmove_atomic (value, ea, esize);
806 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
812 ac = (MonoClass *)arr->obj.vtable->klass;
813 ec = ac->element_class;
815 esize = mono_array_element_size (ac);
816 ea = (gpointer*)((char*)arr->vector + (pos * esize));
818 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
819 g_assert (esize == sizeof (gpointer));
820 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
822 g_assert (ec->inited);
823 g_assert (esize == mono_class_value_size (ec, NULL));
824 if (ec->has_references)
825 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
827 mono_gc_memmove_atomic (ea, value, esize);
832 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
834 MonoClass *klass = array->obj.vtable->klass;
835 guint32 size = mono_array_element_size (klass);
836 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
838 const char *field_data;
840 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
841 MonoException *exc = mono_get_exception_argument("array",
842 "Cannot initialize array of non-primitive type.");
843 mono_set_pending_exception (exc);
847 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
848 MonoException *exc = mono_get_exception_argument("field_handle",
849 "Field doesn't have an RVA");
850 mono_set_pending_exception (exc);
854 size *= array->max_length;
855 field_data = mono_field_get_data (field_handle);
857 if (size > mono_type_size (field_handle->type, &align)) {
858 MonoException *exc = mono_get_exception_argument("field_handle",
859 "Field not large enough to fill array");
860 mono_set_pending_exception (exc);
864 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
866 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
867 guint ## n *src = (guint ## n *) field_data; \
869 nEnt = (size / sizeof(guint ## n)); \
871 for (i = 0; i < nEnt; i++) { \
872 data[i] = read ## n (&src[i]); \
876 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
878 switch (type->type) {
895 memcpy (mono_array_addr (array, char, 0), field_data, size);
899 memcpy (mono_array_addr (array, char, 0), field_data, size);
904 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
906 return offsetof (MonoString, chars);
909 ICALL_EXPORT MonoObject *
910 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
912 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
916 MonoObject *ret = mono_object_clone_checked (obj, &error);
917 mono_error_set_pending_exception (&error);
924 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
930 MONO_CHECK_ARG_NULL (handle,);
932 klass = mono_class_from_mono_type (handle);
933 MONO_CHECK_ARG (handle, klass,);
935 if (klass->generic_container)
938 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
939 if (!is_ok (&error)) {
940 mono_error_set_pending_exception (&error);
944 /* This will call the type constructor */
945 if (!mono_runtime_class_init_full (vtable, &error))
946 mono_error_set_pending_exception (&error);
950 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
954 mono_image_check_for_module_cctor (image);
955 if (image->has_module_cctor) {
956 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
957 if (!mono_error_ok (&error)) {
958 mono_error_set_pending_exception (&error);
961 /*It's fine to raise the exception here*/
962 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
963 if (!is_ok (&error)) {
964 mono_error_set_pending_exception (&error);
967 if (!mono_runtime_class_init_full (vtable, &error))
968 mono_error_set_pending_exception (&error);
972 ICALL_EXPORT MonoBoolean
973 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
978 /* later make this configurable and per-arch */
979 int min_size = 4096 * 4 * sizeof (void*);
980 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
981 /* if we have no info we are optimistic and assume there is enough room */
985 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
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 (assembly->assembly->image, file_idx);
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 (image, i + 1);
5033 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5034 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5037 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5038 if (mono_error_set_pending_exception (&error))
5040 mono_array_setref (res, j, rm);
5047 ICALL_EXPORT MonoReflectionMethod*
5048 ves_icall_GetCurrentMethod (void)
5050 MonoReflectionMethod *res = NULL;
5053 MonoMethod *m = mono_method_get_last_managed ();
5056 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5060 while (m->is_inflated)
5061 m = ((MonoMethodInflated*)m)->declaring;
5063 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5064 mono_error_set_pending_exception (&error);
5070 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5073 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5076 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5077 //method is inflated, we should inflate it on the other class
5078 MonoGenericContext ctx;
5079 ctx.method_inst = inflated->context.method_inst;
5080 ctx.class_inst = inflated->context.class_inst;
5081 if (klass->generic_class)
5082 ctx.class_inst = klass->generic_class->context.class_inst;
5083 else if (klass->generic_container)
5084 ctx.class_inst = klass->generic_container->context.class_inst;
5085 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5086 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5090 mono_class_setup_methods (method->klass);
5091 if (mono_class_has_failure (method->klass))
5093 for (i = 0; i < method->klass->method.count; ++i) {
5094 if (method->klass->methods [i] == method) {
5099 mono_class_setup_methods (klass);
5100 if (mono_class_has_failure (klass))
5102 g_assert (offset >= 0 && offset < klass->method.count);
5103 return klass->methods [offset];
5106 ICALL_EXPORT MonoReflectionMethod*
5107 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5109 MonoReflectionMethod *res = NULL;
5112 if (type && generic_check) {
5113 klass = mono_class_from_mono_type (type);
5114 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5117 if (method->klass != klass) {
5118 method = mono_method_get_equivalent_method (method, klass);
5123 klass = mono_class_from_mono_type (type);
5125 klass = method->klass;
5126 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5127 mono_error_set_pending_exception (&error);
5131 ICALL_EXPORT MonoReflectionMethodBody*
5132 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5135 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5136 mono_error_set_pending_exception (&error);
5140 ICALL_EXPORT MonoReflectionAssembly*
5141 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5144 MonoReflectionAssembly *result;
5145 MonoMethod *dest = NULL;
5147 mono_stack_walk_no_il (get_executing, &dest);
5149 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5151 mono_error_set_pending_exception (&error);
5156 ICALL_EXPORT MonoReflectionAssembly*
5157 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5160 MonoReflectionAssembly *result;
5161 MonoDomain* domain = mono_domain_get ();
5163 if (!domain->entry_assembly)
5166 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5168 mono_error_set_pending_exception (&error);
5172 ICALL_EXPORT MonoReflectionAssembly*
5173 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5178 MonoReflectionAssembly *result;
5181 mono_stack_walk_no_il (get_executing, &dest);
5183 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5187 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5190 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5192 mono_error_set_pending_exception (&error);
5196 ICALL_EXPORT MonoStringHandle
5197 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5198 gboolean assembly_qualified, MonoError *error)
5200 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5201 MonoType *type = MONO_HANDLE_RAW (object)->type;
5202 MonoTypeNameFormat format;
5203 MonoStringHandle res;
5207 format = assembly_qualified ?
5208 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5209 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5211 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5213 name = mono_type_get_name_full (type, format);
5215 return NULL_HANDLE_STRING;
5217 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5219 return NULL_HANDLE_STRING;
5222 res = mono_string_new_handle (domain, name, error);
5229 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5232 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5234 mono_class_init_checked (klass, &error);
5235 mono_error_set_pending_exception (&error);
5236 return mono_security_core_clr_class_level (klass);
5240 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5242 MonoClassField *field = rfield->field;
5243 return mono_security_core_clr_field_level (field, TRUE);
5247 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5249 MonoMethod *method = rfield->method;
5250 return mono_security_core_clr_method_level (method, TRUE);
5254 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)
5256 static MonoMethod *create_culture = NULL;
5260 const char *pkey_ptr;
5262 MonoBoolean assembly_ref = 0;
5264 mono_error_init (error);
5266 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5267 aname->major = name->major;
5268 aname->minor = name->minor;
5269 aname->build = name->build;
5270 aname->flags = name->flags;
5271 aname->revision = name->revision;
5272 aname->hashalg = name->hash_alg;
5273 aname->versioncompat = 1; /* SameMachine (default) */
5274 aname->processor_architecture = name->arch;
5276 if (by_default_version) {
5277 MonoObject *version;
5279 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5280 return_if_nok (error);
5282 MONO_OBJECT_SETREF (aname, version, version);
5286 if (absolute != NULL && *absolute != '\0') {
5287 const gchar *prepend = "file://";
5290 codebase = g_strdup (absolute);
5295 for (i = strlen (codebase) - 1; i >= 0; i--)
5296 if (codebase [i] == '\\')
5299 if (*codebase == '/' && *(codebase + 1) == '/') {
5302 prepend = "file:///";
5306 result = g_strconcat (prepend, codebase, NULL);
5312 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5316 if (!create_culture) {
5317 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5318 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5319 g_assert (create_culture);
5320 mono_method_desc_free (desc);
5323 if (name->culture) {
5324 args [0] = mono_string_new (domain, name->culture);
5325 args [1] = &assembly_ref;
5327 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5328 return_if_nok (error);
5330 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5333 if (name->public_key) {
5334 pkey_ptr = (char*)name->public_key;
5335 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5337 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5338 return_if_nok (error);
5339 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5340 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5341 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5342 } else if (default_publickey) {
5343 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5344 return_if_nok (error);
5345 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5346 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5349 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5350 if (name->public_key_token [0]) {
5354 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5355 return_if_nok (error);
5357 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5358 p = mono_array_addr (keyToken, char, 0);
5360 for (i = 0, j = 0; i < 8; i++) {
5361 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5362 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5365 } else if (default_token) {
5366 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5367 return_if_nok (error);
5368 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5372 ICALL_EXPORT MonoString *
5373 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5375 MonoDomain *domain = mono_object_domain (assembly);
5376 MonoAssembly *mass = assembly->assembly;
5380 name = mono_stringify_assembly_name (&mass->aname);
5381 res = mono_string_new (domain, name);
5387 ICALL_EXPORT MonoAssemblyName *
5388 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5390 return &mass->aname;
5394 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5398 MonoImageOpenStatus status = MONO_IMAGE_OK;
5401 MonoAssemblyName name;
5404 filename = mono_string_to_utf8_checked (fname, &error);
5405 if (mono_error_set_pending_exception (&error))
5408 dirname = g_path_get_dirname (filename);
5409 replace_shadow_path (mono_domain_get (), dirname, &filename);
5412 image = mono_image_open (filename, &status);
5418 if (status == MONO_IMAGE_IMAGE_INVALID)
5419 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5421 exc = mono_get_exception_file_not_found2 (NULL, fname);
5422 mono_set_pending_exception (exc);
5426 res = mono_assembly_fill_assembly_name (image, &name);
5428 mono_image_close (image);
5430 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5434 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5435 mono_error_set_pending_exception (&error);
5437 mono_image_close (image);
5441 ICALL_EXPORT MonoBoolean
5442 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5443 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5445 MonoBoolean result = FALSE;
5446 MonoDeclSecurityEntry entry;
5448 /* SecurityAction.RequestMinimum */
5449 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5450 *minimum = entry.blob;
5451 *minLength = entry.size;
5454 /* SecurityAction.RequestOptional */
5455 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5456 *optional = entry.blob;
5457 *optLength = entry.size;
5460 /* SecurityAction.RequestRefuse */
5461 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5462 *refused = entry.blob;
5463 *refLength = entry.size;
5471 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5473 guint32 attrs, visibility;
5475 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5476 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5477 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5480 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5486 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5488 MonoReflectionType *rt;
5491 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5494 mono_error_init (error);
5496 /* we start the count from 1 because we skip the special type <Module> */
5499 for (i = 1; i < tdef->rows; ++i) {
5500 if (mono_module_type_is_visible (tdef, image, i + 1))
5504 count = tdef->rows - 1;
5506 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5507 return_val_if_nok (error, NULL);
5508 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5509 return_val_if_nok (error, NULL);
5511 for (i = 1; i < tdef->rows; ++i) {
5512 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5513 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5516 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5517 return_val_if_nok (error, NULL);
5519 mono_array_setref (res, count, rt);
5521 MonoException *ex = mono_error_convert_to_exception (error);
5522 mono_array_setref (*exceptions, count, ex);
5531 ICALL_EXPORT MonoArray*
5532 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5535 MonoArray *res = NULL;
5536 MonoArray *exceptions = NULL;
5537 MonoImage *image = NULL;
5538 MonoTableInfo *table = NULL;
5541 int i, len, ex_count;
5543 domain = mono_object_domain (assembly);
5545 g_assert (!assembly_is_dynamic (assembly->assembly));
5546 image = assembly->assembly->image;
5547 table = &image->tables [MONO_TABLE_FILE];
5548 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5549 if (mono_error_set_pending_exception (&error))
5552 /* Append data from all modules in the assembly */
5553 for (i = 0; i < table->rows; ++i) {
5554 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5555 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5560 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5561 if (mono_error_set_pending_exception (&error))
5565 /* Append the new types to the end of the array */
5566 if (mono_array_length (res2) > 0) {
5568 MonoArray *res3, *ex3;
5570 len1 = mono_array_length (res);
5571 len2 = mono_array_length (res2);
5573 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5574 if (mono_error_set_pending_exception (&error))
5576 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5577 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5580 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5581 if (mono_error_set_pending_exception (&error))
5583 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5584 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5591 /* the ReflectionTypeLoadException must have all the types (Types property),
5592 * NULL replacing types which throws an exception. The LoaderException must
5593 * contain all exceptions for NULL items.
5596 len = mono_array_length (res);
5599 for (i = 0; i < len; i++) {
5600 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5604 klass = mono_type_get_class (t->type);
5605 if ((klass != NULL) && mono_class_has_failure (klass)) {
5606 /* keep the class in the list */
5607 list = g_list_append (list, klass);
5608 /* and replace Type with NULL */
5609 mono_array_setref (res, i, NULL);
5616 if (list || ex_count) {
5618 MonoException *exc = NULL;
5619 MonoArray *exl = NULL;
5620 int j, length = g_list_length (list) + ex_count;
5622 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5623 if (mono_error_set_pending_exception (&error)) {
5627 /* Types for which mono_class_get_checked () succeeded */
5628 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5629 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5630 mono_array_setref (exl, i, exc);
5632 /* Types for which it don't */
5633 for (j = 0; j < mono_array_length (exceptions); ++j) {
5634 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5636 g_assert (i < length);
5637 mono_array_setref (exl, i, exc);
5644 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5645 if (!is_ok (&error)) {
5646 mono_error_set_pending_exception (&error);
5649 mono_set_pending_exception (exc);
5657 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5659 mono_assembly_name_free (aname);
5662 ICALL_EXPORT gboolean
5663 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5665 *is_version_definited = *is_token_defined = FALSE;
5667 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5670 ICALL_EXPORT MonoReflectionType*
5671 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5674 MonoReflectionType *ret;
5675 MonoDomain *domain = mono_object_domain (module);
5678 g_assert (module->image);
5680 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5681 /* These images do not have a global type */
5684 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5685 if (!mono_error_ok (&error)) {
5686 mono_error_set_pending_exception (&error);
5690 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5691 if (!mono_error_ok (&error)) {
5692 mono_error_set_pending_exception (&error);
5700 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5702 /*if (module->image)
5703 mono_image_close (module->image);*/
5706 ICALL_EXPORT MonoStringHandle
5707 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModuleHandle refmodule, MonoError *error)
5709 MonoDomain *domain = MONO_HANDLE_DOMAIN (refmodule);
5710 MonoImage *image = MONO_HANDLE_RAW (refmodule)->image;
5713 return mono_string_new_handle (domain, image->guid, error);
5716 ICALL_EXPORT gpointer
5717 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5720 if (module->image && module->image->is_module_handle)
5721 return module->image->raw_data;
5724 return (gpointer) (-1);
5728 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5730 if (image_is_dynamic (image)) {
5731 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5732 *pe_kind = dyn->pe_kind;
5733 *machine = dyn->machine;
5736 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5737 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5742 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5744 return (image->md_version_major << 16) | (image->md_version_minor);
5747 ICALL_EXPORT MonoArray*
5748 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5751 MonoArray *exceptions;
5754 if (!module->image) {
5755 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5756 mono_error_set_pending_exception (&error);
5761 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5762 if (mono_error_set_pending_exception (&error))
5765 for (i = 0; i < mono_array_length (exceptions); ++i) {
5766 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5768 mono_set_pending_exception (ex);
5777 mono_memberref_is_method (MonoImage *image, guint32 token)
5779 if (!image_is_dynamic (image)) {
5780 guint32 cols [MONO_MEMBERREF_SIZE];
5782 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5783 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5784 mono_metadata_decode_blob_size (sig, &sig);
5785 return (*sig != 0x6);
5788 MonoClass *handle_class;
5790 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5791 mono_error_cleanup (&error); /* just probing, ignore error */
5795 return mono_defaults.methodhandle_class == handle_class;
5800 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5803 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5804 mono_array_addr (type_args, MonoType*, 0));
5806 context->class_inst = NULL;
5808 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5809 mono_array_addr (method_args, MonoType*, 0));
5811 context->method_inst = NULL;
5814 ICALL_EXPORT MonoType*
5815 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5818 int table = mono_metadata_token_table (token);
5819 int index = mono_metadata_token_index (token);
5820 MonoGenericContext context;
5823 *resolve_error = ResolveTokenError_Other;
5825 /* Validate token */
5826 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5827 (table != MONO_TABLE_TYPESPEC)) {
5828 *resolve_error = ResolveTokenError_BadTable;
5832 if (image_is_dynamic (image)) {
5833 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5834 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5835 mono_error_cleanup (&error);
5836 return klass ? &klass->byval_arg : NULL;
5839 init_generic_context_from_args (&context, type_args, method_args);
5840 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5841 mono_error_cleanup (&error);
5842 return klass ? &klass->byval_arg : NULL;
5845 if ((index <= 0) || (index > image->tables [table].rows)) {
5846 *resolve_error = ResolveTokenError_OutOfRange;
5850 init_generic_context_from_args (&context, type_args, method_args);
5851 klass = mono_class_get_checked (image, token, &error);
5853 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5854 if (!mono_error_ok (&error)) {
5855 mono_error_set_pending_exception (&error);
5860 return &klass->byval_arg;
5865 ICALL_EXPORT MonoMethod*
5866 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5869 int table = mono_metadata_token_table (token);
5870 int index = mono_metadata_token_index (token);
5871 MonoGenericContext context;
5874 *resolve_error = ResolveTokenError_Other;
5876 /* Validate token */
5877 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5878 (table != MONO_TABLE_MEMBERREF)) {
5879 *resolve_error = ResolveTokenError_BadTable;
5883 if (image_is_dynamic (image)) {
5884 if (table == MONO_TABLE_METHOD) {
5885 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5886 mono_error_cleanup (&error);
5890 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5891 *resolve_error = ResolveTokenError_BadTable;
5895 init_generic_context_from_args (&context, type_args, method_args);
5896 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5897 mono_error_cleanup (&error);
5901 if ((index <= 0) || (index > image->tables [table].rows)) {
5902 *resolve_error = ResolveTokenError_OutOfRange;
5905 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5906 *resolve_error = ResolveTokenError_BadTable;
5910 init_generic_context_from_args (&context, type_args, method_args);
5911 method = mono_get_method_checked (image, token, NULL, &context, &error);
5912 mono_error_set_pending_exception (&error);
5917 ICALL_EXPORT MonoString*
5918 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5921 int index = mono_metadata_token_index (token);
5923 *resolve_error = ResolveTokenError_Other;
5925 /* Validate token */
5926 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5927 *resolve_error = ResolveTokenError_BadTable;
5931 if (image_is_dynamic (image)) {
5932 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5933 mono_error_cleanup (&error);
5937 if ((index <= 0) || (index >= image->heap_us.size)) {
5938 *resolve_error = ResolveTokenError_OutOfRange;
5942 /* FIXME: What to do if the index points into the middle of a string ? */
5944 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5945 mono_error_set_pending_exception (&error);
5949 ICALL_EXPORT MonoClassField*
5950 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5954 int table = mono_metadata_token_table (token);
5955 int index = mono_metadata_token_index (token);
5956 MonoGenericContext context;
5957 MonoClassField *field;
5959 *resolve_error = ResolveTokenError_Other;
5961 /* Validate token */
5962 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5963 *resolve_error = ResolveTokenError_BadTable;
5967 if (image_is_dynamic (image)) {
5968 if (table == MONO_TABLE_FIELD) {
5969 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5970 mono_error_cleanup (&error);
5974 if (mono_memberref_is_method (image, token)) {
5975 *resolve_error = ResolveTokenError_BadTable;
5979 init_generic_context_from_args (&context, type_args, method_args);
5980 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5981 mono_error_cleanup (&error);
5985 if ((index <= 0) || (index > image->tables [table].rows)) {
5986 *resolve_error = ResolveTokenError_OutOfRange;
5989 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5990 *resolve_error = ResolveTokenError_BadTable;
5994 init_generic_context_from_args (&context, type_args, method_args);
5995 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5996 mono_error_set_pending_exception (&error);
6002 ICALL_EXPORT MonoObject*
6003 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6007 int table = mono_metadata_token_table (token);
6009 *error = ResolveTokenError_Other;
6012 case MONO_TABLE_TYPEDEF:
6013 case MONO_TABLE_TYPEREF:
6014 case MONO_TABLE_TYPESPEC: {
6015 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6017 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6018 mono_error_set_pending_exception (&merror);
6025 case MONO_TABLE_METHOD:
6026 case MONO_TABLE_METHODSPEC: {
6027 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6029 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6030 mono_error_set_pending_exception (&merror);
6036 case MONO_TABLE_FIELD: {
6037 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6039 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6040 mono_error_set_pending_exception (&merror);
6046 case MONO_TABLE_MEMBERREF:
6047 if (mono_memberref_is_method (image, token)) {
6048 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6050 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6051 mono_error_set_pending_exception (&merror);
6058 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6060 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6061 mono_error_set_pending_exception (&merror);
6070 *error = ResolveTokenError_BadTable;
6076 ICALL_EXPORT MonoArray*
6077 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6080 int table = mono_metadata_token_table (token);
6081 int idx = mono_metadata_token_index (token);
6082 MonoTableInfo *tables = image->tables;
6087 *resolve_error = ResolveTokenError_OutOfRange;
6089 /* FIXME: Support other tables ? */
6090 if (table != MONO_TABLE_STANDALONESIG)
6093 if (image_is_dynamic (image))
6096 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6099 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6101 ptr = mono_metadata_blob_heap (image, sig);
6102 len = mono_metadata_decode_blob_size (ptr, &ptr);
6104 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6105 if (mono_error_set_pending_exception (&error))
6107 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6111 ICALL_EXPORT MonoBoolean
6112 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6118 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6124 check_for_invalid_type (MonoClass *klass, MonoError *error)
6129 mono_error_init (error);
6131 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6134 name = mono_type_get_full_name (klass);
6135 str = mono_string_new (mono_domain_get (), name);
6137 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6140 ICALL_EXPORT MonoReflectionType *
6141 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6144 MonoReflectionType *ret;
6145 MonoClass *klass, *aklass;
6147 klass = mono_class_from_mono_type (type->type);
6148 check_for_invalid_type (klass, &error);
6149 mono_error_set_pending_exception (&error);
6151 if (rank == 0) //single dimentional array
6152 aklass = mono_array_class_get (klass, 1);
6154 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6156 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6157 mono_error_set_pending_exception (&error);
6162 ICALL_EXPORT MonoReflectionType *
6163 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6166 MonoReflectionType *ret;
6169 klass = mono_class_from_mono_type (type->type);
6170 mono_class_init_checked (klass, &error);
6171 if (mono_error_set_pending_exception (&error))
6174 check_for_invalid_type (klass, &error);
6175 if (mono_error_set_pending_exception (&error))
6178 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6179 mono_error_set_pending_exception (&error);
6184 ICALL_EXPORT MonoReflectionType *
6185 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6188 MonoReflectionType *ret;
6189 MonoClass *klass, *pklass;
6191 klass = mono_class_from_mono_type (type->type);
6192 mono_class_init_checked (klass, &error);
6193 if (mono_error_set_pending_exception (&error))
6195 check_for_invalid_type (klass, &error);
6196 if (mono_error_set_pending_exception (&error))
6199 pklass = mono_ptr_class_get (type->type);
6201 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6202 mono_error_set_pending_exception (&error);
6207 ICALL_EXPORT MonoObject *
6208 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6209 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6212 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6213 MonoObject *delegate;
6215 MonoMethod *method = info->method;
6216 MonoMethodSignature *sig = mono_method_signature(method);
6218 mono_class_init_checked (delegate_class, &error);
6219 if (mono_error_set_pending_exception (&error))
6222 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6223 /* FIXME improve this exception message */
6224 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6226 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6227 mono_error_set_pending_exception (&error);
6231 if (mono_security_core_clr_enabled ()) {
6232 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6233 if (throwOnBindFailure)
6234 mono_error_set_pending_exception (&error);
6236 mono_error_cleanup (&error);
6241 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6242 if (!method->is_inflated) {
6243 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"));
6248 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6249 if (mono_error_set_pending_exception (&error))
6252 if (method_is_dynamic (method)) {
6253 /* Creating a trampoline would leak memory */
6254 func = mono_compile_method_checked (method, &error);
6255 if (mono_error_set_pending_exception (&error))
6258 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6259 method = mono_object_get_virtual_method (target, method);
6260 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6261 if (mono_error_set_pending_exception (&error))
6263 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6266 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6267 if (mono_error_set_pending_exception (&error))
6272 ICALL_EXPORT MonoMulticastDelegate *
6273 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6276 MonoMulticastDelegate *ret;
6278 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6280 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6281 if (mono_error_set_pending_exception (&error))
6284 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6289 ICALL_EXPORT MonoReflectionMethod*
6290 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6292 MonoReflectionMethod *ret = NULL;
6294 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6295 mono_error_set_pending_exception (&error);
6301 static inline gint32
6302 mono_array_get_byte_length (MonoArray *array)
6308 klass = array->obj.vtable->klass;
6310 if (array->bounds == NULL)
6311 length = array->max_length;
6314 for (i = 0; i < klass->rank; ++ i)
6315 length *= array->bounds [i].length;
6318 switch (klass->element_class->byval_arg.type) {
6321 case MONO_TYPE_BOOLEAN:
6325 case MONO_TYPE_CHAR:
6333 return length * sizeof (gpointer);
6344 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6346 return mono_array_get_byte_length (array);
6350 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6352 return mono_array_get (array, gint8, idx);
6356 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6358 mono_array_set (array, gint8, idx, value);
6361 ICALL_EXPORT MonoBoolean
6362 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6364 guint8 *src_buf, *dest_buf;
6367 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6371 g_assert (count >= 0);
6373 /* This is called directly from the class libraries without going through the managed wrapper */
6374 MONO_CHECK_ARG_NULL (src, FALSE);
6375 MONO_CHECK_ARG_NULL (dest, FALSE);
6377 /* watch out for integer overflow */
6378 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6381 src_buf = (guint8 *)src->vector + src_offset;
6382 dest_buf = (guint8 *)dest->vector + dest_offset;
6385 memcpy (dest_buf, src_buf, count);
6387 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6392 #ifndef DISABLE_REMOTING
6393 ICALL_EXPORT MonoObject *
6394 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6397 MonoDomain *domain = mono_object_domain (this_obj);
6399 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6400 MonoTransparentProxy *tp;
6404 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6405 if (mono_error_set_pending_exception (&error))
6408 tp = (MonoTransparentProxy*) res;
6410 MONO_OBJECT_SETREF (tp, rp, rp);
6411 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6412 klass = mono_class_from_mono_type (type);
6414 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6415 mono_class_setup_vtable (klass);
6416 if (mono_class_has_failure (klass)) {
6417 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6421 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6422 if (mono_error_set_pending_exception (&error))
6424 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6425 if (mono_error_set_pending_exception (&error))
6428 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6429 if (mono_error_set_pending_exception (&error))
6434 ICALL_EXPORT MonoReflectionType *
6435 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6438 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6439 mono_error_set_pending_exception (&error);
6445 /* System.Environment */
6448 ves_icall_System_Environment_get_UserName (void)
6450 /* using glib is more portable */
6451 return mono_string_new (mono_domain_get (), g_get_user_name ());
6455 ICALL_EXPORT MonoString *
6456 ves_icall_System_Environment_get_MachineName (void)
6458 #if defined (HOST_WIN32)
6463 len = MAX_COMPUTERNAME_LENGTH + 1;
6464 buf = g_new (gunichar2, len);
6467 if (GetComputerName (buf, (PDWORD) &len)) {
6469 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6470 mono_error_set_pending_exception (&error);
6475 #elif !defined(DISABLE_SOCKETS)
6479 #if defined _SC_HOST_NAME_MAX
6480 n = sysconf (_SC_HOST_NAME_MAX);
6484 buf = g_malloc (n+1);
6486 if (gethostname (buf, n) == 0){
6488 result = mono_string_new (mono_domain_get (), buf);
6495 return mono_string_new (mono_domain_get (), "mono");
6500 ves_icall_System_Environment_get_Platform (void)
6502 #if defined (TARGET_WIN32)
6505 #elif defined(__MACH__)
6508 // Notice that the value is hidden from user code, and only exposed
6509 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6510 // define and making assumptions based on Unix/128/4 values before there
6511 // was a MacOS define. Lots of code would assume that not-Unix meant
6512 // Windows, but in this case, it would be OSX.
6521 ICALL_EXPORT MonoString *
6522 ves_icall_System_Environment_get_NewLine (void)
6524 #if defined (HOST_WIN32)
6525 return mono_string_new (mono_domain_get (), "\r\n");
6527 return mono_string_new (mono_domain_get (), "\n");
6531 ICALL_EXPORT MonoBoolean
6532 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6534 #if SIZEOF_VOID_P == 8
6538 gboolean isWow64Process = FALSE;
6539 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6540 return (MonoBoolean)isWow64Process;
6542 #elif defined(HAVE_SYS_UTSNAME_H)
6543 struct utsname name;
6545 if (uname (&name) >= 0) {
6546 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6553 ICALL_EXPORT MonoStringHandle
6554 ves_icall_System_Environment_GetEnvironmentVariable_native (const gchar *utf8_name, MonoError *error)
6558 if (utf8_name == NULL)
6559 return NULL_HANDLE_STRING;
6561 value = g_getenv (utf8_name);
6564 return NULL_HANDLE_STRING;
6566 return mono_string_new_handle (mono_domain_get (), value, error);
6570 * There is no standard way to get at environ.
6573 #ifndef __MINGW32_VERSION
6574 #if defined(__APPLE__)
6575 #if defined (TARGET_OSX)
6576 /* Apple defines this in crt_externs.h but doesn't provide that header for
6577 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6578 * in fact exist on all implementations (so far)
6580 gchar ***_NSGetEnviron(void);
6581 #define environ (*_NSGetEnviron())
6583 static char *mono_environ[1] = { NULL };
6584 #define environ mono_environ
6585 #endif /* defined (TARGET_OSX) */
6593 ICALL_EXPORT MonoArray *
6594 ves_icall_System_Environment_GetCoomandLineArgs (void)
6597 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6598 mono_error_set_pending_exception (&error);
6602 ICALL_EXPORT MonoArray *
6603 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6615 env_strings = GetEnvironmentStrings();
6618 env_string = env_strings;
6619 while (*env_string != '\0') {
6620 /* weird case that MS seems to skip */
6621 if (*env_string != '=')
6623 while (*env_string != '\0')
6629 domain = mono_domain_get ();
6630 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6631 if (mono_error_set_pending_exception (&error))
6636 env_string = env_strings;
6637 while (*env_string != '\0') {
6638 /* weird case that MS seems to skip */
6639 if (*env_string != '=') {
6640 equal_str = wcschr(env_string, '=');
6641 g_assert(equal_str);
6643 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6644 if (mono_error_set_pending_exception (&error))
6647 mono_array_setref (names, n, str);
6650 while (*env_string != '\0')
6655 FreeEnvironmentStrings (env_strings);
6669 for (e = environ; *e != 0; ++ e)
6672 domain = mono_domain_get ();
6673 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6674 if (mono_error_set_pending_exception (&error))
6678 for (e = environ; *e != 0; ++ e) {
6679 parts = g_strsplit (*e, "=", 2);
6681 str = mono_string_new (domain, *parts);
6682 mono_array_setref (names, n, str);
6695 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6698 gunichar2 *utf16_name, *utf16_value;
6700 gchar *utf8_name, *utf8_value;
6705 utf16_name = mono_string_to_utf16 (name);
6706 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6707 SetEnvironmentVariable (utf16_name, NULL);
6708 g_free (utf16_name);
6712 utf16_value = mono_string_to_utf16 (value);
6714 SetEnvironmentVariable (utf16_name, utf16_value);
6716 g_free (utf16_name);
6717 g_free (utf16_value);
6719 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6720 if (mono_error_set_pending_exception (&error))
6723 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6724 g_unsetenv (utf8_name);
6729 utf8_value = mono_string_to_utf8_checked (value, &error);
6730 if (!mono_error_ok (&error)) {
6732 mono_error_set_pending_exception (&error);
6735 g_setenv (utf8_name, utf8_value, TRUE);
6738 g_free (utf8_value);
6743 ves_icall_System_Environment_Exit (int result)
6745 mono_environment_exitcode_set (result);
6747 /* FIXME: There are some cleanup hangs that should be worked out, but
6748 * if the program is going to exit, everything will be cleaned up when
6749 * NaCl exits anyway.
6751 #ifndef __native_client__
6752 if (!mono_runtime_try_shutdown ())
6753 mono_thread_exit ();
6755 /* Suspend all managed threads since the runtime is going away */
6756 mono_thread_suspend_all_other_threads ();
6758 mono_runtime_quit ();
6761 /* we may need to do some cleanup here... */
6765 ICALL_EXPORT MonoStringHandle
6766 ves_icall_System_Environment_GetGacPath (MonoError *error)
6768 return mono_string_new_handle (mono_domain_get (), mono_assembly_getrootdir (), error);
6771 ICALL_EXPORT MonoString*
6772 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6774 #if defined (HOST_WIN32)
6775 #ifndef CSIDL_FLAG_CREATE
6776 #define CSIDL_FLAG_CREATE 0x8000
6779 WCHAR path [MAX_PATH];
6780 /* Create directory if no existing */
6781 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6786 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6787 mono_error_set_pending_exception (&error);
6791 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6793 return mono_string_new (mono_domain_get (), "");
6796 ICALL_EXPORT MonoArray *
6797 ves_icall_System_Environment_GetLogicalDrives (void)
6800 gunichar2 buf [256], *ptr, *dname;
6802 guint initial_size = 127, size = 128;
6805 MonoString *drivestr;
6806 MonoDomain *domain = mono_domain_get ();
6812 while (size > initial_size) {
6813 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6814 if (size > initial_size) {
6817 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6818 initial_size = size;
6832 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6833 if (mono_error_set_pending_exception (&error))
6840 while (*u16) { u16++; len ++; }
6841 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6842 if (mono_error_set_pending_exception (&error))
6845 mono_array_setref (result, ndrives++, drivestr);
6856 ICALL_EXPORT MonoString *
6857 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6860 gunichar2 volume_name [MAX_PATH + 1];
6862 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6864 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6865 mono_error_set_pending_exception (&error);
6869 ICALL_EXPORT MonoStringHandle
6870 ves_icall_System_Environment_InternalGetHome (MonoError *error)
6872 return mono_string_new_handle (mono_domain_get (), g_get_home_dir (), error);
6875 static const char *encodings [] = {
6877 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6878 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6879 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6881 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6882 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6883 "x_unicode_2_0_utf_7",
6885 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6886 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6888 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6891 "unicodefffe", "utf_16be",
6898 * Returns the internal codepage, if the value of "int_code_page" is
6899 * 1 at entry, and we can not compute a suitable code page number,
6900 * returns the code page as a string
6902 ICALL_EXPORT MonoString*
6903 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6908 char *codepage = NULL;
6910 int want_name = *int_code_page;
6913 *int_code_page = -1;
6915 g_get_charset (&cset);
6916 c = codepage = strdup (cset);
6917 for (c = codepage; *c; c++){
6918 if (isascii (*c) && isalpha (*c))
6923 /* g_print ("charset: %s\n", cset); */
6925 /* handle some common aliases */
6928 for (i = 0; p != 0; ){
6931 p = encodings [++i];
6934 if (strcmp (p, codepage) == 0){
6935 *int_code_page = code;
6938 p = encodings [++i];
6941 if (strstr (codepage, "utf_8") != NULL)
6942 *int_code_page |= 0x10000000;
6945 if (want_name && *int_code_page == -1)
6946 return mono_string_new (mono_domain_get (), cset);
6951 ICALL_EXPORT MonoBoolean
6952 ves_icall_System_Environment_get_HasShutdownStarted (void)
6954 if (mono_runtime_is_shutting_down ())
6957 if (mono_domain_is_unloading (mono_domain_get ()))
6964 ves_icall_System_Environment_BroadcastSettingChange (void)
6967 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6973 ves_icall_System_Environment_get_TickCount (void)
6975 /* this will overflow after ~24 days */
6976 return (gint32) (mono_msec_boottime () & 0xffffffff);
6980 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6985 #ifndef DISABLE_REMOTING
6986 ICALL_EXPORT MonoBoolean
6987 ves_icall_IsTransparentProxy (MonoObject *proxy)
6992 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6998 ICALL_EXPORT MonoReflectionMethod *
6999 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7000 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7002 MonoReflectionMethod *ret = NULL;
7007 MonoMethod **vtable;
7008 MonoMethod *res = NULL;
7010 MONO_CHECK_ARG_NULL (rtype, NULL);
7011 MONO_CHECK_ARG_NULL (rmethod, NULL);
7013 method = rmethod->method;
7014 klass = mono_class_from_mono_type (rtype->type);
7015 mono_class_init_checked (klass, &error);
7016 if (mono_error_set_pending_exception (&error))
7019 if (MONO_CLASS_IS_INTERFACE (klass))
7022 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7025 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7026 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7032 mono_class_setup_vtable (klass);
7033 vtable = klass->vtable;
7035 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7036 gboolean variance_used = FALSE;
7037 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7038 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7040 res = vtable [offs + method->slot];
7042 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7045 if (method->slot != -1)
7046 res = vtable [method->slot];
7052 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7053 mono_error_set_pending_exception (&error);
7058 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7064 klass = mono_class_from_mono_type (type->type);
7065 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7066 if (!is_ok (&error)) {
7067 mono_error_set_pending_exception (&error);
7071 mono_vtable_set_is_remote (vtable, enable);
7074 #else /* DISABLE_REMOTING */
7077 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7079 g_assert_not_reached ();
7084 ICALL_EXPORT MonoObject *
7085 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7092 domain = mono_object_domain (type);
7093 klass = mono_class_from_mono_type (type->type);
7094 mono_class_init_checked (klass, &error);
7095 if (mono_error_set_pending_exception (&error))
7098 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7099 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7103 if (klass->rank >= 1) {
7104 g_assert (klass->rank == 1);
7105 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7106 mono_error_set_pending_exception (&error);
7109 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7110 if (!is_ok (&error)) {
7111 mono_error_set_pending_exception (&error);
7114 /* Bypass remoting object creation check */
7115 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7116 mono_error_set_pending_exception (&error);
7122 ICALL_EXPORT MonoStringHandle
7123 ves_icall_System_IO_get_temp_path (MonoError *error)
7125 return mono_string_new_handle (mono_domain_get (), g_get_tmp_dir (), error);
7128 #ifndef PLATFORM_NO_DRIVEINFO
7129 ICALL_EXPORT MonoBoolean
7130 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7131 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7135 ULARGE_INTEGER wapi_free_bytes_avail;
7136 ULARGE_INTEGER wapi_total_number_of_bytes;
7137 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7139 *error = ERROR_SUCCESS;
7140 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7141 &wapi_total_number_of_free_bytes);
7144 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7145 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7146 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7148 *free_bytes_avail = 0;
7149 *total_number_of_bytes = 0;
7150 *total_number_of_free_bytes = 0;
7151 *error = GetLastError ();
7157 ICALL_EXPORT guint32
7158 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7160 return GetDriveType (mono_string_chars (root_path_name));
7164 ICALL_EXPORT gpointer
7165 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7168 gpointer result = mono_compile_method_checked (method, &error);
7169 mono_error_set_pending_exception (&error);
7173 ICALL_EXPORT MonoString *
7174 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7179 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7181 #if defined (HOST_WIN32)
7182 /* Avoid mixing '/' and '\\' */
7185 for (i = strlen (path) - 1; i >= 0; i--)
7186 if (path [i] == '/')
7190 mcpath = mono_string_new (mono_domain_get (), path);
7196 /* this is an icall */
7198 get_bundled_app_config (void)
7201 const gchar *app_config;
7204 gchar *config_file_name, *config_file_path;
7205 gsize len, config_file_path_length, config_ext_length;
7208 domain = mono_domain_get ();
7209 file = domain->setup->configuration_file;
7210 if (!file || file->length == 0)
7213 // Retrieve config file and remove the extension
7214 config_file_name = mono_string_to_utf8_checked (file, &error);
7215 if (mono_error_set_pending_exception (&error))
7217 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7218 if (!config_file_path)
7219 config_file_path = config_file_name;
7221 config_file_path_length = strlen (config_file_path);
7222 config_ext_length = strlen (".config");
7223 if (config_file_path_length <= config_ext_length)
7226 len = config_file_path_length - config_ext_length;
7227 module = (gchar *)g_malloc0 (len + 1);
7228 memcpy (module, config_file_path, len);
7229 // Get the config file from the module name
7230 app_config = mono_config_string_for_assembly_file (module);
7233 if (config_file_name != config_file_path)
7234 g_free (config_file_name);
7235 g_free (config_file_path);
7240 return mono_string_new (mono_domain_get (), app_config);
7243 /* this is an icall */
7244 static MonoStringHandle
7245 get_bundled_machine_config (MonoError *error)
7247 const gchar *machine_config;
7249 machine_config = mono_get_machine_config ();
7251 if (!machine_config)
7252 return NULL_HANDLE_STRING;
7254 return mono_string_new_handle (mono_domain_get (), machine_config, error);
7257 ICALL_EXPORT MonoString *
7258 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7263 path = g_path_get_dirname (mono_get_config_dir ());
7265 #if defined (HOST_WIN32)
7266 /* Avoid mixing '/' and '\\' */
7269 for (i = strlen (path) - 1; i >= 0; i--)
7270 if (path [i] == '/')
7274 ipath = mono_string_new (mono_domain_get (), path);
7280 ICALL_EXPORT gboolean
7281 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7283 MonoPEResourceDataEntry *entry;
7286 if (!assembly || !result || !size)
7291 image = assembly->assembly->image;
7292 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7296 *result = mono_image_rva_map (image, entry->rde_data_offset);
7301 *size = entry->rde_size;
7306 ICALL_EXPORT MonoBoolean
7307 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7309 return mono_is_debugger_attached ();
7312 ICALL_EXPORT MonoBoolean
7313 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7315 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7316 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7322 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7324 if (mono_get_runtime_callbacks ()->debug_log)
7325 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7329 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7331 #if defined (HOST_WIN32)
7332 OutputDebugString (mono_string_chars (message));
7334 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7338 /* Only used for value types */
7339 ICALL_EXPORT MonoObject *
7340 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7347 domain = mono_object_domain (type);
7348 klass = mono_class_from_mono_type (type->type);
7349 mono_class_init_checked (klass, &error);
7350 if (mono_error_set_pending_exception (&error))
7353 if (mono_class_is_nullable (klass))
7354 /* No arguments -> null */
7357 result = mono_object_new_checked (domain, klass, &error);
7358 mono_error_set_pending_exception (&error);
7362 ICALL_EXPORT MonoReflectionMethod *
7363 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7365 MonoReflectionMethod *ret = NULL;
7368 MonoClass *klass, *parent;
7369 MonoGenericContext *generic_inst = NULL;
7370 MonoMethod *method = m->method;
7371 MonoMethod *result = NULL;
7374 if (method->klass == NULL)
7377 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7378 MONO_CLASS_IS_INTERFACE (method->klass) ||
7379 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7382 slot = mono_method_get_vtable_slot (method);
7386 klass = method->klass;
7387 if (klass->generic_class) {
7388 generic_inst = mono_class_get_context (klass);
7389 klass = klass->generic_class->container_class;
7393 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7394 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7395 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7396 or klass is the generic container class and generic_inst is the instantiation.
7398 when we go to the parent, if the parent is an open constructed type, we need to
7399 replace the type parameters by the definitions from the generic_inst, and then take it
7400 apart again into the klass and the generic_inst.
7402 For cases like this:
7403 class C<T> : B<T, int> {
7404 public override void Foo () { ... }
7406 class B<U,V> : A<HashMap<U,V>> {
7407 public override void Foo () { ... }
7410 public virtual void Foo () { ... }
7413 if at each iteration the parent isn't open, we can skip inflating it. if at some
7414 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7417 MonoGenericContext *parent_inst = NULL;
7418 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7419 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7420 if (!mono_error_ok (&error)) {
7421 mono_error_set_pending_exception (&error);
7425 if (parent->generic_class) {
7426 parent_inst = mono_class_get_context (parent);
7427 parent = parent->generic_class->container_class;
7430 mono_class_setup_vtable (parent);
7431 if (parent->vtable_size <= slot)
7434 generic_inst = parent_inst;
7437 klass = klass->parent;
7440 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7441 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7442 if (!mono_error_ok (&error)) {
7443 mono_error_set_pending_exception (&error);
7447 generic_inst = NULL;
7449 if (klass->generic_class) {
7450 generic_inst = mono_class_get_context (klass);
7451 klass = klass->generic_class->container_class;
7457 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7458 if (!mono_error_ok (&error)) {
7459 mono_error_set_pending_exception (&error);
7464 if (klass == method->klass)
7467 /*This is possible if definition == FALSE.
7468 * Do it here to be really sure we don't read invalid memory.
7470 if (slot >= klass->vtable_size)
7473 mono_class_setup_vtable (klass);
7475 result = klass->vtable [slot];
7476 if (result == NULL) {
7477 /* It is an abstract method */
7478 gpointer iter = NULL;
7479 while ((result = mono_class_get_methods (klass, &iter)))
7480 if (result->slot == slot)
7487 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7488 mono_error_set_pending_exception (&error);
7492 ICALL_EXPORT MonoString*
7493 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7495 MonoMethod *method = m->method;
7497 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7502 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7504 iter->sig = *(MonoMethodSignature**)argsp;
7506 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7507 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7510 /* FIXME: it's not documented what start is exactly... */
7514 iter->args = argsp + sizeof (gpointer);
7516 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7518 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7521 ICALL_EXPORT MonoTypedRef
7522 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7524 guint32 i, arg_size;
7528 i = iter->sig->sentinelpos + iter->next_arg;
7530 g_assert (i < iter->sig->param_count);
7532 res.type = iter->sig->params [i];
7533 res.klass = mono_class_from_mono_type (res.type);
7534 arg_size = mono_type_stack_size (res.type, &align);
7535 #if defined(__arm__) || defined(__mips__)
7536 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7538 res.value = iter->args;
7539 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7540 /* Values are stored as 8 byte register sized objects, but 'value'
7541 * is dereferenced as a pointer in other routines.
7543 res.value = (char*)res.value + 4;
7545 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7546 if (arg_size <= sizeof (gpointer)) {
7548 int padding = arg_size - mono_type_size (res.type, &dummy);
7549 res.value = (guint8*)res.value + padding;
7552 iter->args = (char*)iter->args + arg_size;
7555 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7560 ICALL_EXPORT MonoTypedRef
7561 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7563 guint32 i, arg_size;
7567 i = iter->sig->sentinelpos + iter->next_arg;
7569 g_assert (i < iter->sig->param_count);
7571 while (i < iter->sig->param_count) {
7572 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7574 res.type = iter->sig->params [i];
7575 res.klass = mono_class_from_mono_type (res.type);
7576 /* FIXME: endianess issue... */
7577 arg_size = mono_type_stack_size (res.type, &align);
7578 #if defined(__arm__) || defined(__mips__)
7579 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7581 res.value = iter->args;
7582 iter->args = (char*)iter->args + arg_size;
7584 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7587 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7595 ICALL_EXPORT MonoType*
7596 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7600 i = iter->sig->sentinelpos + iter->next_arg;
7602 g_assert (i < iter->sig->param_count);
7604 return iter->sig->params [i];
7607 ICALL_EXPORT MonoObject*
7608 mono_TypedReference_ToObject (MonoTypedRef* tref)
7611 MonoObject *result = NULL;
7612 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7613 MonoObject** objp = (MonoObject **)tref->value;
7617 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7618 mono_error_set_pending_exception (&error);
7622 ICALL_EXPORT MonoTypedRef
7623 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7626 MonoReflectionField *f;
7628 MonoType *ftype = NULL;
7632 memset (&res, 0, sizeof (res));
7635 g_assert (mono_array_length (fields) > 0);
7637 klass = target->vtable->klass;
7639 for (i = 0; i < mono_array_length (fields); ++i) {
7640 f = mono_array_get (fields, MonoReflectionField*, i);
7642 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7645 if (f->field->parent != klass) {
7646 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7650 p = (guint8*)target + f->field->offset;
7652 p += f->field->offset - sizeof (MonoObject);
7653 klass = mono_class_from_mono_type (f->field->type);
7654 ftype = f->field->type;
7658 res.klass = mono_class_from_mono_type (ftype);
7665 prelink_method (MonoMethod *method, MonoError *error)
7667 const char *exc_class, *exc_arg;
7669 mono_error_init (error);
7670 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7672 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7674 mono_error_set_exception_instance (error,
7675 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7678 /* create the wrapper, too? */
7682 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7686 prelink_method (method->method, &error);
7687 mono_error_set_pending_exception (&error);
7691 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7694 MonoClass *klass = mono_class_from_mono_type (type->type);
7696 gpointer iter = NULL;
7698 mono_class_init_checked (klass, &error);
7699 if (mono_error_set_pending_exception (&error))
7702 while ((m = mono_class_get_methods (klass, &iter))) {
7703 prelink_method (m, &error);
7704 if (mono_error_set_pending_exception (&error))
7709 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7711 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7712 gint32 const **exponents,
7713 gunichar2 const **digitLowerTable,
7714 gunichar2 const **digitUpperTable,
7715 gint64 const **tenPowersList,
7716 gint32 const **decHexDigits)
7718 *mantissas = Formatter_MantissaBitsTable;
7719 *exponents = Formatter_TensExponentTable;
7720 *digitLowerTable = Formatter_DigitLowerTable;
7721 *digitUpperTable = Formatter_DigitUpperTable;
7722 *tenPowersList = Formatter_TenPowersList;
7723 *decHexDigits = Formatter_DecHexDigits;
7727 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7728 * and avoid useless allocations.
7731 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7733 MonoReflectionType *rt;
7737 mono_error_init (error);
7738 for (i = 0; i < type->num_mods; ++i) {
7739 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7744 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7745 return_val_if_nok (error, NULL);
7747 for (i = 0; i < type->num_mods; ++i) {
7748 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7749 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7750 return_val_if_nok (error, NULL);
7752 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7753 return_val_if_nok (error, NULL);
7755 mono_array_setref (res, count, rt);
7762 ICALL_EXPORT MonoArray*
7763 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7766 MonoType *type = param->ClassImpl->type;
7767 MonoClass *member_class = mono_object_class (param->MemberImpl);
7768 MonoMethod *method = NULL;
7771 MonoMethodSignature *sig;
7774 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7775 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7776 method = rmethod->method;
7777 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7778 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7779 if (!(method = prop->property->get))
7780 method = prop->property->set;
7783 char *type_name = mono_type_get_full_name (member_class);
7784 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7785 MonoException *ex = mono_get_exception_not_supported (msg);
7788 mono_set_pending_exception (ex);
7792 image = method->klass->image;
7793 pos = param->PositionImpl;
7794 sig = mono_method_signature (method);
7798 type = sig->params [pos];
7800 res = type_array_from_modifiers (image, type, optional, &error);
7801 mono_error_set_pending_exception (&error);
7806 get_property_type (MonoProperty *prop)
7808 MonoMethodSignature *sig;
7810 sig = mono_method_signature (prop->get);
7812 } else if (prop->set) {
7813 sig = mono_method_signature (prop->set);
7814 return sig->params [sig->param_count - 1];
7819 ICALL_EXPORT MonoArray*
7820 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7823 MonoType *type = get_property_type (property->property);
7824 MonoImage *image = property->klass->image;
7829 res = type_array_from_modifiers (image, type, optional, &error);
7830 mono_error_set_pending_exception (&error);
7835 *Construct a MonoType suited to be used to decode a constant blob object.
7837 * @type is the target type which will be constructed
7838 * @blob_type is the blob type, for example, that comes from the constant table
7839 * @real_type is the expected constructed type.
7842 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7844 type->type = blob_type;
7845 type->data.klass = NULL;
7846 if (blob_type == MONO_TYPE_CLASS)
7847 type->data.klass = mono_defaults.object_class;
7848 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7849 /* For enums, we need to use the base type */
7850 type->type = MONO_TYPE_VALUETYPE;
7851 type->data.klass = mono_class_from_mono_type (real_type);
7853 type->data.klass = mono_class_from_mono_type (real_type);
7856 ICALL_EXPORT MonoObject*
7857 property_info_get_default_value (MonoReflectionProperty *property)
7861 MonoProperty *prop = property->property;
7862 MonoType *type = get_property_type (prop);
7863 MonoDomain *domain = mono_object_domain (property);
7864 MonoTypeEnum def_type;
7865 const char *def_value;
7868 mono_class_init (prop->parent);
7870 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7871 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7875 def_value = mono_class_get_property_default_value (prop, &def_type);
7877 mono_type_from_blob_type (&blob_type, def_type, type);
7878 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7880 mono_error_set_pending_exception (&error);
7884 ICALL_EXPORT MonoBoolean
7885 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7888 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7889 MonoCustomAttrInfo *cinfo;
7892 mono_class_init_checked (attr_class, &error);
7893 if (mono_error_set_pending_exception (&error))
7896 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7897 if (!is_ok (&error)) {
7898 mono_error_set_pending_exception (&error);
7903 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7905 mono_custom_attrs_free (cinfo);
7909 ICALL_EXPORT MonoArray*
7910 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7912 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7917 mono_class_init_checked (attr_class, &error);
7918 if (mono_error_set_pending_exception (&error))
7922 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7923 if (!mono_error_ok (&error)) {
7924 mono_error_set_pending_exception (&error);
7931 ICALL_EXPORT MonoArray*
7932 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7936 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7937 mono_error_set_pending_exception (&error);
7942 ICALL_EXPORT MonoString*
7943 ves_icall_Mono_Runtime_GetDisplayName (void)
7946 MonoString *display_name;
7948 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7949 display_name = mono_string_new (mono_domain_get (), info);
7951 return display_name;
7954 ICALL_EXPORT MonoString*
7955 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7958 MonoString *message;
7962 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7963 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7966 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7968 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7969 if (mono_error_set_pending_exception (&error))
7976 ICALL_EXPORT gpointer
7977 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7979 return GetCurrentProcess ();
7982 ICALL_EXPORT MonoBoolean
7983 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7985 return GetExitCodeProcess (handle, (guint32*) exitcode);
7988 ICALL_EXPORT MonoBoolean
7989 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7991 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7992 return CloseHandle (handle);
7994 return CloseProcess (handle);
7998 ICALL_EXPORT MonoBoolean
7999 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8001 return TerminateProcess (handle, exitcode);
8005 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8008 return WaitForInputIdle (handle, milliseconds);
8010 /*TODO: Not implemented*/
8011 return WAIT_TIMEOUT;
8015 ICALL_EXPORT MonoBoolean
8016 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8018 return GetProcessWorkingSetSize (handle, min, max);
8021 ICALL_EXPORT MonoBoolean
8022 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8024 return SetProcessWorkingSetSize (handle, min, max);
8027 ICALL_EXPORT MonoBoolean
8028 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8030 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8034 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8036 return mono_process_current_pid ();
8040 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8042 return GetPriorityClass (handle);
8045 ICALL_EXPORT MonoBoolean
8046 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8048 return SetPriorityClass (handle, priorityClass);
8051 #ifndef DISABLE_ICALL_TABLES
8053 #define ICALL_TYPE(id,name,first)
8054 #define ICALL(id,name,func) Icall_ ## id,
8055 #define HANDLES(inner) inner
8058 #include "metadata/icall-def.h"
8064 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8065 #define ICALL(id,name,func)
8067 #define HANDLES(inner) inner
8069 #include "metadata/icall-def.h"
8075 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8076 #define ICALL(id,name,func)
8078 #define HANDLES(inner) inner
8080 guint16 first_icall;
8083 static const IcallTypeDesc
8084 icall_type_descs [] = {
8085 #include "metadata/icall-def.h"
8089 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8092 #define HANDLES(inner) inner
8094 #define ICALL_TYPE(id,name,first)
8097 #ifdef HAVE_ARRAY_ELEM_INIT
8098 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8099 #define MSGSTRFIELD1(line) str##line
8101 static const struct msgstrtn_t {
8102 #define ICALL(id,name,func)
8104 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8105 #include "metadata/icall-def.h"
8107 } icall_type_names_str = {
8108 #define ICALL_TYPE(id,name,first) (name),
8109 #include "metadata/icall-def.h"
8112 static const guint16 icall_type_names_idx [] = {
8113 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8114 #include "metadata/icall-def.h"
8117 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8119 static const struct msgstr_t {
8121 #define ICALL_TYPE(id,name,first)
8122 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8123 #include "metadata/icall-def.h"
8125 } icall_names_str = {
8126 #define ICALL(id,name,func) (name),
8127 #include "metadata/icall-def.h"
8130 static const guint16 icall_names_idx [] = {
8131 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8132 #include "metadata/icall-def.h"
8135 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8141 #define ICALL_TYPE(id,name,first) name,
8142 #define ICALL(id,name,func)
8143 static const char* const
8144 icall_type_names [] = {
8145 #include "metadata/icall-def.h"
8149 #define icall_type_name_get(id) (icall_type_names [(id)])
8153 #define ICALL_TYPE(id,name,first)
8154 #define ICALL(id,name,func) name,
8155 static const char* const
8157 #include "metadata/icall-def.h"
8160 #define icall_name_get(id) icall_names [(id)]
8162 #endif /* !HAVE_ARRAY_ELEM_INIT */
8165 #define HANDLES(inner) inner
8168 #define ICALL_TYPE(id,name,first)
8169 #define ICALL(id,name,func) func,
8170 static const gconstpointer
8171 icall_functions [] = {
8172 #include "metadata/icall-def.h"
8176 #ifdef ENABLE_ICALL_SYMBOL_MAP
8178 #define HANDLES(inner) inner
8181 #define ICALL_TYPE(id,name,first)
8182 #define ICALL(id,name,func) #func,
8183 static const gconstpointer
8184 icall_symbols [] = {
8185 #include "metadata/icall-def.h"
8192 #define ICALL_TYPE(id,name,first)
8193 #define ICALL(id,name,func) 0,
8195 #define HANDLES(inner) 1,
8197 icall_uses_handles [] = {
8198 #include "metadata/icall-def.h"
8203 #endif /* DISABLE_ICALL_TABLES */
8205 static mono_mutex_t icall_mutex;
8206 static GHashTable *icall_hash = NULL;
8207 static GHashTable *jit_icall_hash_name = NULL;
8208 static GHashTable *jit_icall_hash_addr = NULL;
8211 mono_icall_init (void)
8213 #ifndef DISABLE_ICALL_TABLES
8216 /* check that tables are sorted: disable in release */
8219 const char *prev_class = NULL;
8220 const char *prev_method;
8222 for (i = 0; i < Icall_type_num; ++i) {
8223 const IcallTypeDesc *desc;
8226 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8227 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8228 prev_class = icall_type_name_get (i);
8229 desc = &icall_type_descs [i];
8230 num_icalls = icall_desc_num_icalls (desc);
8231 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8232 for (j = 0; j < num_icalls; ++j) {
8233 const char *methodn = icall_name_get (desc->first_icall + j);
8234 if (prev_method && strcmp (prev_method, methodn) >= 0)
8235 g_print ("method %s should come before method %s\n", methodn, prev_method);
8236 prev_method = methodn;
8242 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8243 mono_os_mutex_init (&icall_mutex);
8247 mono_icall_lock (void)
8249 mono_locks_os_acquire (&icall_mutex, IcallLock);
8253 mono_icall_unlock (void)
8255 mono_locks_os_release (&icall_mutex, IcallLock);
8259 mono_icall_cleanup (void)
8261 g_hash_table_destroy (icall_hash);
8262 g_hash_table_destroy (jit_icall_hash_name);
8263 g_hash_table_destroy (jit_icall_hash_addr);
8264 mono_os_mutex_destroy (&icall_mutex);
8268 * mono_add_internal_call:
8269 * @name: method specification to surface to the managed world
8270 * @method: pointer to a C method to invoke when the method is called
8272 * This method surfaces the C function pointed by @method as a method
8273 * that has been surfaced in managed code with the method specified in
8274 * @name as an internal call.
8276 * Internal calls are surfaced to all app domains loaded and they are
8277 * accessibly by a type with the specified name.
8279 * You must provide a fully qualified type name, that is namespaces
8280 * and type name, followed by a colon and the method name, with an
8281 * optional signature to bind.
8283 * For example, the following are all valid declarations:
8285 * "MyApp.Services.ScriptService:Accelerate"
8286 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8288 * You use method parameters in cases where there might be more than
8289 * one surface method to managed code. That way you can register different
8290 * internal calls for different method overloads.
8292 * The internal calls are invoked with no marshalling. This means that .NET
8293 * types like System.String are exposed as `MonoString *` parameters. This is
8294 * different than the way that strings are surfaced in P/Invoke.
8296 * For more information on how the parameters are marshalled, see the
8297 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8300 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8301 * reference for more information on the format of method descriptions.
8304 mono_add_internal_call (const char *name, gconstpointer method)
8308 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8310 mono_icall_unlock ();
8313 #ifndef DISABLE_ICALL_TABLES
8315 #ifdef HAVE_ARRAY_ELEM_INIT
8317 compare_method_imap (const void *key, const void *elem)
8319 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8320 return strcmp (key, method_name);
8324 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8326 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);
8329 return (nameslot - &icall_names_idx [0]);
8333 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8335 gsize slotnum = find_slot_icall (imap, name);
8338 return (gboolean)icall_uses_handles [slotnum];
8342 find_method_icall (const IcallTypeDesc *imap, const char *name)
8344 gsize slotnum = find_slot_icall (imap, name);
8347 return (gpointer)icall_functions [slotnum];
8351 compare_class_imap (const void *key, const void *elem)
8353 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8354 return strcmp (key, class_name);
8357 static const IcallTypeDesc*
8358 find_class_icalls (const char *name)
8360 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);
8363 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8366 #else /* HAVE_ARRAY_ELEM_INIT */
8369 compare_method_imap (const void *key, const void *elem)
8371 const char** method_name = (const char**)elem;
8372 return strcmp (key, *method_name);
8376 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8378 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8381 return nameslot - icall_names;
8385 find_method_icall (const IcallTypeDesc *imap, const char *name)
8387 gsize slotnum = find_slot_icall (imap, name);
8390 return (gpointer)icall_functions [slotnum];
8394 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8396 gsize slotnum = find_slot_icall (imap, name);
8399 return (gboolean)icall_uses_handles [slotnum];
8403 compare_class_imap (const void *key, const void *elem)
8405 const char** class_name = (const char**)elem;
8406 return strcmp (key, *class_name);
8409 static const IcallTypeDesc*
8410 find_class_icalls (const char *name)
8412 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8415 return &icall_type_descs [nameslot - icall_type_names];
8418 #endif /* HAVE_ARRAY_ELEM_INIT */
8420 #endif /* DISABLE_ICALL_TABLES */
8423 * we should probably export this as an helper (handle nested types).
8424 * Returns the number of chars written in buf.
8427 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8429 int nspacelen, cnamelen;
8430 nspacelen = strlen (klass->name_space);
8431 cnamelen = strlen (klass->name);
8432 if (nspacelen + cnamelen + 2 > bufsize)
8435 memcpy (buf, klass->name_space, nspacelen);
8436 buf [nspacelen ++] = '.';
8438 memcpy (buf + nspacelen, klass->name, cnamelen);
8439 buf [nspacelen + cnamelen] = 0;
8440 return nspacelen + cnamelen;
8443 #ifdef DISABLE_ICALL_TABLES
8445 no_icall_table (void)
8447 g_assert_not_reached ();
8452 * mono_lookup_internal_call_full:
8453 * @method: the method to look up
8454 * @uses_handles: out argument if method needs handles around managed objects.
8456 * Returns a pointer to the icall code for the given method. If
8457 * uses_handles is not NULL, it will be set to TRUE if the method
8458 * needs managed objects wrapped using the infrastructure in handle.h
8460 * If the method is not found, warns and returns NULL.
8463 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8468 int typelen = 0, mlen, siglen;
8470 #ifndef DISABLE_ICALL_TABLES
8471 const IcallTypeDesc *imap = NULL;
8474 g_assert (method != NULL);
8476 if (method->is_inflated)
8477 method = ((MonoMethodInflated *) method)->declaring;
8479 if (method->klass->nested_in) {
8480 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8484 mname [pos++] = '/';
8487 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8493 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8498 #ifndef DISABLE_ICALL_TABLES
8499 imap = find_class_icalls (mname);
8502 mname [typelen] = ':';
8503 mname [typelen + 1] = ':';
8505 mlen = strlen (method->name);
8506 memcpy (mname + typelen + 2, method->name, mlen);
8507 sigstart = mname + typelen + 2 + mlen;
8510 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8511 siglen = strlen (tmpsig);
8512 if (typelen + mlen + siglen + 6 > sizeof (mname))
8515 memcpy (sigstart + 1, tmpsig, siglen);
8516 sigstart [siglen + 1] = ')';
8517 sigstart [siglen + 2] = 0;
8522 res = g_hash_table_lookup (icall_hash, mname);
8525 *uses_handles = FALSE;
8526 mono_icall_unlock ();;
8529 /* try without signature */
8531 res = g_hash_table_lookup (icall_hash, mname);
8534 *uses_handles = FALSE;
8535 mono_icall_unlock ();
8539 #ifdef DISABLE_ICALL_TABLES
8540 mono_icall_unlock ();
8541 /* Fail only when the result is actually used */
8542 /* mono_marshal_get_native_wrapper () depends on this */
8543 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8544 return ves_icall_System_String_ctor_RedirectToCreateString;
8546 return no_icall_table;
8548 /* it wasn't found in the static call tables */
8551 *uses_handles = FALSE;
8552 mono_icall_unlock ();
8555 res = find_method_icall (imap, sigstart - mlen);
8558 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8559 mono_icall_unlock ();
8562 /* try _with_ signature */
8564 res = find_method_icall (imap, sigstart - mlen);
8567 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8568 mono_icall_unlock ();
8572 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8573 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8574 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8575 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8576 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");
8577 g_print ("If you see other errors or faults after this message they are probably related\n");
8578 g_print ("and you need to fix your mono install first.\n");
8580 mono_icall_unlock ();
8587 mono_lookup_internal_call (MonoMethod *method)
8589 return mono_lookup_internal_call_full (method, NULL);
8592 #ifdef ENABLE_ICALL_SYMBOL_MAP
8594 func_cmp (gconstpointer key, gconstpointer p)
8596 return (gsize)key - (gsize)*(gsize*)p;
8601 * mono_lookup_icall_symbol:
8603 * Given the icall METHOD, returns its C symbol.
8606 mono_lookup_icall_symbol (MonoMethod *m)
8608 #ifdef DISABLE_ICALL_TABLES
8609 g_assert_not_reached ();
8612 #ifdef ENABLE_ICALL_SYMBOL_MAP
8616 static gconstpointer *functions_sorted;
8617 static const char**symbols_sorted;
8618 static gboolean inited;
8623 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8624 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8625 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8626 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8627 /* Bubble sort the two arrays */
8631 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8632 if (functions_sorted [i] > functions_sorted [i + 1]) {
8635 tmp = functions_sorted [i];
8636 functions_sorted [i] = functions_sorted [i + 1];
8637 functions_sorted [i + 1] = tmp;
8638 tmp = symbols_sorted [i];
8639 symbols_sorted [i] = symbols_sorted [i + 1];
8640 symbols_sorted [i + 1] = tmp;
8647 func = mono_lookup_internal_call (m);
8650 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8654 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8656 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8657 g_assert_not_reached ();
8664 type_from_typename (char *type_name)
8666 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8668 if (!strcmp (type_name, "int"))
8669 klass = mono_defaults.int_class;
8670 else if (!strcmp (type_name, "ptr"))
8671 klass = mono_defaults.int_class;
8672 else if (!strcmp (type_name, "void"))
8673 klass = mono_defaults.void_class;
8674 else if (!strcmp (type_name, "int32"))
8675 klass = mono_defaults.int32_class;
8676 else if (!strcmp (type_name, "uint32"))
8677 klass = mono_defaults.uint32_class;
8678 else if (!strcmp (type_name, "int8"))
8679 klass = mono_defaults.sbyte_class;
8680 else if (!strcmp (type_name, "uint8"))
8681 klass = mono_defaults.byte_class;
8682 else if (!strcmp (type_name, "int16"))
8683 klass = mono_defaults.int16_class;
8684 else if (!strcmp (type_name, "uint16"))
8685 klass = mono_defaults.uint16_class;
8686 else if (!strcmp (type_name, "long"))
8687 klass = mono_defaults.int64_class;
8688 else if (!strcmp (type_name, "ulong"))
8689 klass = mono_defaults.uint64_class;
8690 else if (!strcmp (type_name, "float"))
8691 klass = mono_defaults.single_class;
8692 else if (!strcmp (type_name, "double"))
8693 klass = mono_defaults.double_class;
8694 else if (!strcmp (type_name, "object"))
8695 klass = mono_defaults.object_class;
8696 else if (!strcmp (type_name, "obj"))
8697 klass = mono_defaults.object_class;
8698 else if (!strcmp (type_name, "string"))
8699 klass = mono_defaults.string_class;
8700 else if (!strcmp (type_name, "bool"))
8701 klass = mono_defaults.boolean_class;
8702 else if (!strcmp (type_name, "boolean"))
8703 klass = mono_defaults.boolean_class;
8705 g_error ("%s", type_name);
8706 g_assert_not_reached ();
8708 return &klass->byval_arg;
8712 * LOCKING: Take the corlib image lock.
8714 MonoMethodSignature*
8715 mono_create_icall_signature (const char *sigstr)
8720 MonoMethodSignature *res, *res2;
8721 MonoImage *corlib = mono_defaults.corlib;
8723 mono_image_lock (corlib);
8724 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8725 mono_image_unlock (corlib);
8730 parts = g_strsplit (sigstr, " ", 256);
8739 res = mono_metadata_signature_alloc (corlib, len - 1);
8744 * Under windows, the default pinvoke calling convention is STDCALL but
8747 res->call_convention = MONO_CALL_C;
8750 res->ret = type_from_typename (parts [0]);
8751 for (i = 1; i < len; ++i) {
8752 res->params [i - 1] = type_from_typename (parts [i]);
8757 mono_image_lock (corlib);
8758 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8760 res = res2; /*Value is allocated in the image pool*/
8762 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8763 mono_image_unlock (corlib);
8769 mono_find_jit_icall_by_name (const char *name)
8771 MonoJitICallInfo *info;
8772 g_assert (jit_icall_hash_name);
8775 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8776 mono_icall_unlock ();
8781 mono_find_jit_icall_by_addr (gconstpointer addr)
8783 MonoJitICallInfo *info;
8784 g_assert (jit_icall_hash_addr);
8787 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8788 mono_icall_unlock ();
8794 * mono_get_jit_icall_info:
8796 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8797 * caller should access it while holding the icall lock.
8800 mono_get_jit_icall_info (void)
8802 return jit_icall_hash_name;
8806 * mono_lookup_jit_icall_symbol:
8808 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8811 mono_lookup_jit_icall_symbol (const char *name)
8813 MonoJitICallInfo *info;
8814 const char *res = NULL;
8817 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8819 res = info->c_symbol;
8820 mono_icall_unlock ();
8825 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8828 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8829 mono_icall_unlock ();
8833 * 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
8834 * icalls without wrappers in some cases.
8837 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8839 MonoJitICallInfo *info;
8846 if (!jit_icall_hash_name) {
8847 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8848 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8851 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8852 g_warning ("jit icall already defined \"%s\"\n", name);
8853 g_assert_not_reached ();
8856 info = g_new0 (MonoJitICallInfo, 1);
8861 info->c_symbol = c_symbol;
8862 info->no_raise = no_raise;
8865 info->wrapper = func;
8867 info->wrapper = NULL;
8870 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8871 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8873 mono_icall_unlock ();
8878 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8880 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);