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 TYPED_HANDLE_DECL (MonoReflectionType);
116 /* Lazy class loading functions */
117 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
118 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
119 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
120 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
121 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
122 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
125 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
127 static inline MonoBoolean
128 is_generic_parameter (MonoType *type)
130 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
134 mono_class_init_checked (MonoClass *klass, MonoError *error)
136 mono_error_init (error);
138 if (!mono_class_init (klass))
139 mono_error_set_for_class_failure (error, klass);
142 ICALL_EXPORT MonoObject *
143 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
149 MonoObject *result = NULL;
151 ac = (MonoClass *)arr->obj.vtable->klass;
153 esize = mono_array_element_size (ac);
154 ea = (gpointer*)((char*)arr->vector + (pos * esize));
156 if (ac->element_class->valuetype) {
157 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
158 mono_error_set_pending_exception (&error);
160 result = (MonoObject *)*ea;
164 ICALL_EXPORT MonoObject *
165 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
171 MONO_CHECK_ARG_NULL (idxs, NULL);
174 ic = (MonoClass *)io->obj.vtable->klass;
176 ac = (MonoClass *)arr->obj.vtable->klass;
178 g_assert (ic->rank == 1);
179 if (io->bounds != NULL || io->max_length != ac->rank) {
180 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
184 ind = (gint32 *)io->vector;
186 if (arr->bounds == NULL) {
187 if (*ind < 0 || *ind >= arr->max_length) {
188 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
192 return ves_icall_System_Array_GetValueImpl (arr, *ind);
195 for (i = 0; i < ac->rank; i++) {
196 if ((ind [i] < arr->bounds [i].lower_bound) ||
197 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
198 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
203 pos = ind [0] - arr->bounds [0].lower_bound;
204 for (i = 1; i < ac->rank; i++)
205 pos = pos * arr->bounds [i].length + ind [i] -
206 arr->bounds [i].lower_bound;
208 return ves_icall_System_Array_GetValueImpl (arr, pos);
212 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
215 MonoClass *ac, *vc, *ec;
224 mono_error_init (&error);
227 vc = value->vtable->klass;
231 ac = arr->obj.vtable->klass;
232 ec = ac->element_class;
234 esize = mono_array_element_size (ac);
235 ea = (gpointer*)((char*)arr->vector + (pos * esize));
236 va = (gpointer*)((char*)value + sizeof (MonoObject));
238 if (mono_class_is_nullable (ec)) {
239 mono_nullable_init ((guint8*)ea, value, ec);
244 mono_gc_bzero_atomic (ea, esize);
248 #define NO_WIDENING_CONVERSION G_STMT_START{\
249 mono_set_pending_exception (mono_get_exception_argument ( \
250 "value", "not a widening conversion")); \
254 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
255 if (esize < vsize + (extra)) { \
256 mono_set_pending_exception (mono_get_exception_argument ( \
257 "value", "not a widening conversion")); \
262 #define INVALID_CAST G_STMT_START{ \
263 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
264 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
268 /* Check element (destination) type. */
269 switch (ec->byval_arg.type) {
270 case MONO_TYPE_STRING:
271 switch (vc->byval_arg.type) {
272 case MONO_TYPE_STRING:
278 case MONO_TYPE_BOOLEAN:
279 switch (vc->byval_arg.type) {
280 case MONO_TYPE_BOOLEAN:
293 NO_WIDENING_CONVERSION;
302 if (!ec->valuetype) {
303 gboolean castOk = (NULL != mono_object_isinst_checked (value, ec, &error));
304 if (mono_error_set_pending_exception (&error))
308 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
312 if (mono_object_isinst_checked (value, ec, &error)) {
313 if (ec->has_references)
314 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
316 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
319 if (mono_error_set_pending_exception (&error))
325 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
327 et = ec->byval_arg.type;
328 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
329 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
331 vt = vc->byval_arg.type;
332 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
333 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
335 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
341 case MONO_TYPE_CHAR: \
342 CHECK_WIDENING_CONVERSION(0); \
343 *(etype *) ea = (etype) u64; \
345 /* You can't assign a signed value to an unsigned array. */ \
350 /* You can't assign a floating point number to an integer array. */ \
353 NO_WIDENING_CONVERSION; \
357 #define ASSIGN_SIGNED(etype) G_STMT_START{\
363 CHECK_WIDENING_CONVERSION(0); \
364 *(etype *) ea = (etype) i64; \
366 /* You can assign an unsigned value to a signed array if the array's */ \
367 /* element size is larger than the value size. */ \
372 case MONO_TYPE_CHAR: \
373 CHECK_WIDENING_CONVERSION(1); \
374 *(etype *) ea = (etype) u64; \
376 /* You can't assign a floating point number to an integer array. */ \
379 NO_WIDENING_CONVERSION; \
383 #define ASSIGN_REAL(etype) G_STMT_START{\
387 CHECK_WIDENING_CONVERSION(0); \
388 *(etype *) ea = (etype) r64; \
390 /* All integer values fit into a floating point array, so we don't */ \
391 /* need to CHECK_WIDENING_CONVERSION here. */ \
396 *(etype *) ea = (etype) i64; \
402 case MONO_TYPE_CHAR: \
403 *(etype *) ea = (etype) u64; \
410 u64 = *(guint8 *) va;
413 u64 = *(guint16 *) va;
416 u64 = *(guint32 *) va;
419 u64 = *(guint64 *) va;
425 i64 = *(gint16 *) va;
428 i64 = *(gint32 *) va;
431 i64 = *(gint64 *) va;
434 r64 = *(gfloat *) va;
437 r64 = *(gdouble *) va;
440 u64 = *(guint16 *) va;
442 case MONO_TYPE_BOOLEAN:
443 /* Boolean is only compatible with itself. */
456 NO_WIDENING_CONVERSION;
463 /* If we can't do a direct copy, let's try a widening conversion. */
466 ASSIGN_UNSIGNED (guint16);
468 ASSIGN_UNSIGNED (guint8);
470 ASSIGN_UNSIGNED (guint16);
472 ASSIGN_UNSIGNED (guint32);
474 ASSIGN_UNSIGNED (guint64);
476 ASSIGN_SIGNED (gint8);
478 ASSIGN_SIGNED (gint16);
480 ASSIGN_SIGNED (gint32);
482 ASSIGN_SIGNED (gint64);
484 ASSIGN_REAL (gfloat);
486 ASSIGN_REAL (gdouble);
490 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
494 #undef NO_WIDENING_CONVERSION
495 #undef CHECK_WIDENING_CONVERSION
496 #undef ASSIGN_UNSIGNED
502 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
508 MONO_CHECK_ARG_NULL (idxs,);
510 ic = idxs->obj.vtable->klass;
511 ac = arr->obj.vtable->klass;
513 g_assert (ic->rank == 1);
514 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
515 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
519 ind = (gint32 *)idxs->vector;
521 if (arr->bounds == NULL) {
522 if (*ind < 0 || *ind >= arr->max_length) {
523 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
527 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
531 for (i = 0; i < ac->rank; i++)
532 if ((ind [i] < arr->bounds [i].lower_bound) ||
533 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
534 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
538 pos = ind [0] - arr->bounds [0].lower_bound;
539 for (i = 1; i < ac->rank; i++)
540 pos = pos * arr->bounds [i].length + ind [i] -
541 arr->bounds [i].lower_bound;
543 ves_icall_System_Array_SetValueImpl (arr, value, pos);
546 ICALL_EXPORT MonoArray *
547 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
550 MonoClass *aklass, *klass;
553 gboolean bounded = FALSE;
555 MONO_CHECK_ARG_NULL (type, NULL);
556 MONO_CHECK_ARG_NULL (lengths, NULL);
558 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
560 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
562 for (i = 0; i < mono_array_length (lengths); i++) {
563 if (mono_array_get (lengths, gint32, i) < 0) {
564 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
569 klass = mono_class_from_mono_type (type->type);
570 mono_class_init_checked (klass, &error);
571 if (mono_error_set_pending_exception (&error))
574 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
575 /* vectors are not the same as one dimensional arrays with no-zero bounds */
580 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
582 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
583 for (i = 0; i < aklass->rank; ++i) {
584 sizes [i] = mono_array_get (lengths, guint32, i);
586 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
588 sizes [i + aklass->rank] = 0;
591 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
592 mono_error_set_pending_exception (&error);
597 ICALL_EXPORT MonoArray *
598 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
601 MonoClass *aklass, *klass;
604 gboolean bounded = FALSE;
606 MONO_CHECK_ARG_NULL (type, NULL);
607 MONO_CHECK_ARG_NULL (lengths, NULL);
609 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
611 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
613 for (i = 0; i < mono_array_length (lengths); i++) {
614 if ((mono_array_get (lengths, gint64, i) < 0) ||
615 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
616 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
621 klass = mono_class_from_mono_type (type->type);
622 mono_class_init_checked (klass, &error);
623 if (mono_error_set_pending_exception (&error))
626 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
627 /* vectors are not the same as one dimensional arrays with no-zero bounds */
632 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
634 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
635 for (i = 0; i < aklass->rank; ++i) {
636 sizes [i] = mono_array_get (lengths, guint64, i);
638 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
640 sizes [i + aklass->rank] = 0;
643 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
644 mono_error_set_pending_exception (&error);
650 ves_icall_System_Array_GetRank (MonoObject *arr)
652 return arr->vtable->klass->rank;
656 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
658 gint32 rank = arr->obj.vtable->klass->rank;
661 if ((dimension < 0) || (dimension >= rank)) {
662 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
666 if (arr->bounds == NULL)
667 length = arr->max_length;
669 length = arr->bounds [dimension].length;
671 #ifdef MONO_BIG_ARRAYS
672 if (length > G_MAXINT32) {
673 mono_set_pending_exception (mono_get_exception_overflow ());
681 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
683 gint32 rank = arr->obj.vtable->klass->rank;
685 if ((dimension < 0) || (dimension >= rank)) {
686 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
690 if (arr->bounds == NULL)
691 return arr->max_length;
693 return arr->bounds [dimension].length;
697 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
699 gint32 rank = arr->obj.vtable->klass->rank;
701 if ((dimension < 0) || (dimension >= rank)) {
702 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
706 if (arr->bounds == NULL)
709 return arr->bounds [dimension].lower_bound;
713 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
715 int sz = mono_array_element_size (mono_object_class (arr));
716 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
719 ICALL_EXPORT MonoArray*
720 ves_icall_System_Array_Clone (MonoArray *arr)
723 MonoArray *result = mono_array_clone_checked (arr, &error);
724 mono_error_set_pending_exception (&error);
728 ICALL_EXPORT gboolean
729 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
734 MonoVTable *src_vtable;
735 MonoVTable *dest_vtable;
736 MonoClass *src_class;
737 MonoClass *dest_class;
739 src_vtable = source->obj.vtable;
740 dest_vtable = dest->obj.vtable;
742 if (src_vtable->rank != dest_vtable->rank)
745 if (source->bounds || dest->bounds)
748 /* there's no integer overflow since mono_array_length returns an unsigned integer */
749 if ((dest_idx + length > mono_array_length_fast (dest)) ||
750 (source_idx + length > mono_array_length_fast (source)))
753 src_class = src_vtable->klass->element_class;
754 dest_class = dest_vtable->klass->element_class;
757 * Handle common cases.
760 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
761 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
763 if (src_class == mono_defaults.object_class && dest_class->valuetype)
766 /* Check if we're copying a char[] <==> (u)short[] */
767 if (src_class != dest_class) {
768 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
771 /* 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. */
772 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
776 if (dest_class->valuetype) {
777 element_size = mono_array_element_size (source->obj.vtable->klass);
778 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
779 if (dest_class->has_references) {
780 mono_value_copy_array (dest, dest_idx, source_addr, length);
782 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
783 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
786 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
793 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
799 ac = (MonoClass *)arr->obj.vtable->klass;
801 esize = mono_array_element_size (ac);
802 ea = (gpointer*)((char*)arr->vector + (pos * esize));
804 mono_gc_memmove_atomic (value, ea, esize);
808 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
814 ac = (MonoClass *)arr->obj.vtable->klass;
815 ec = ac->element_class;
817 esize = mono_array_element_size (ac);
818 ea = (gpointer*)((char*)arr->vector + (pos * esize));
820 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
821 g_assert (esize == sizeof (gpointer));
822 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
824 g_assert (ec->inited);
825 g_assert (esize == mono_class_value_size (ec, NULL));
826 if (ec->has_references)
827 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
829 mono_gc_memmove_atomic (ea, value, esize);
834 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
836 MonoClass *klass = array->obj.vtable->klass;
837 guint32 size = mono_array_element_size (klass);
838 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
840 const char *field_data;
842 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
843 MonoException *exc = mono_get_exception_argument("array",
844 "Cannot initialize array of non-primitive type.");
845 mono_set_pending_exception (exc);
849 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
850 MonoException *exc = mono_get_exception_argument("field_handle",
851 "Field doesn't have an RVA");
852 mono_set_pending_exception (exc);
856 size *= array->max_length;
857 field_data = mono_field_get_data (field_handle);
859 if (size > mono_type_size (field_handle->type, &align)) {
860 MonoException *exc = mono_get_exception_argument("field_handle",
861 "Field not large enough to fill array");
862 mono_set_pending_exception (exc);
866 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
868 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
869 guint ## n *src = (guint ## n *) field_data; \
871 nEnt = (size / sizeof(guint ## n)); \
873 for (i = 0; i < nEnt; i++) { \
874 data[i] = read ## n (&src[i]); \
878 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
880 switch (type->type) {
897 memcpy (mono_array_addr (array, char, 0), field_data, size);
901 memcpy (mono_array_addr (array, char, 0), field_data, size);
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
908 return offsetof (MonoString, chars);
911 ICALL_EXPORT MonoObject *
912 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
914 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
918 MonoObject *ret = mono_object_clone_checked (obj, &error);
919 mono_error_set_pending_exception (&error);
926 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
932 MONO_CHECK_ARG_NULL (handle,);
934 klass = mono_class_from_mono_type (handle);
935 MONO_CHECK_ARG (handle, klass,);
937 if (klass->generic_container)
940 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
941 if (!is_ok (&error)) {
942 mono_error_set_pending_exception (&error);
946 /* This will call the type constructor */
947 if (!mono_runtime_class_init_full (vtable, &error))
948 mono_error_set_pending_exception (&error);
952 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
956 mono_image_check_for_module_cctor (image);
957 if (image->has_module_cctor) {
958 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
959 if (!mono_error_ok (&error)) {
960 mono_error_set_pending_exception (&error);
963 /*It's fine to raise the exception here*/
964 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
965 if (!is_ok (&error)) {
966 mono_error_set_pending_exception (&error);
969 if (!mono_runtime_class_init_full (vtable, &error))
970 mono_error_set_pending_exception (&error);
974 ICALL_EXPORT MonoBoolean
975 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
980 /* later make this configurable and per-arch */
981 int min_size = 4096 * 4 * sizeof (void*);
982 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
983 /* if we have no info we are optimistic and assume there is enough room */
987 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
991 current = (guint8 *)&stack_addr;
992 if (current > stack_addr) {
993 if ((current - stack_addr) < min_size)
996 if (current - (stack_addr - stack_size) < min_size)
1002 ICALL_EXPORT MonoObject *
1003 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
1006 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
1007 mono_error_set_pending_exception (&error);
1013 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
1017 MonoObject **values = NULL;
1020 gint32 result = (int)(gsize)mono_defaults.int32_class;
1021 MonoClassField* field;
1024 klass = mono_object_class (this_obj);
1026 if (mono_class_num_fields (klass) == 0)
1030 * Compute the starting value of the hashcode for fields of primitive
1031 * types, and return the remaining fields in an array to the managed side.
1032 * This way, we can avoid costly reflection operations in managed code.
1035 while ((field = mono_class_get_fields (klass, &iter))) {
1036 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1038 if (mono_field_is_deleted (field))
1040 /* FIXME: Add more types */
1041 switch (field->type->type) {
1043 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1045 case MONO_TYPE_STRING: {
1047 s = *(MonoString**)((guint8*)this_obj + field->offset);
1049 result ^= mono_string_hash (s);
1054 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1055 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1056 if (!is_ok (&error)) {
1057 mono_error_set_pending_exception (&error);
1060 values [count++] = o;
1066 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1067 if (mono_error_set_pending_exception (&error))
1069 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1070 for (i = 0; i < count; ++i)
1071 mono_array_setref (*fields, i, values [i]);
1078 ICALL_EXPORT MonoBoolean
1079 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1083 MonoObject **values = NULL;
1085 MonoClassField* field;
1089 MONO_CHECK_ARG_NULL (that, FALSE);
1091 if (this_obj->vtable != that->vtable)
1094 klass = mono_object_class (this_obj);
1096 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1097 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1100 * Do the comparison for fields of primitive type and return a result if
1101 * possible. Otherwise, return the remaining fields in an array to the
1102 * managed side. This way, we can avoid costly reflection operations in
1107 while ((field = mono_class_get_fields (klass, &iter))) {
1108 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1110 if (mono_field_is_deleted (field))
1112 /* FIXME: Add more types */
1113 switch (field->type->type) {
1116 case MONO_TYPE_BOOLEAN:
1117 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1122 case MONO_TYPE_CHAR:
1123 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1128 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1133 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1137 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1141 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1146 case MONO_TYPE_STRING: {
1147 MonoString *s1, *s2;
1148 guint32 s1len, s2len;
1149 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1150 s2 = *(MonoString**)((guint8*)that + field->offset);
1153 if ((s1 == NULL) || (s2 == NULL))
1155 s1len = mono_string_length (s1);
1156 s2len = mono_string_length (s2);
1160 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1166 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1167 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1168 if (!is_ok (&error)) {
1169 mono_error_set_pending_exception (&error);
1172 values [count++] = o;
1173 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1174 if (!is_ok (&error)) {
1175 mono_error_set_pending_exception (&error);
1178 values [count++] = o;
1181 if (klass->enumtype)
1182 /* enums only have one non-static field */
1188 MonoArray *fields_arr = mono_array_new_checked (mono_domain_get (), mono_defaults.object_class, count, &error);
1189 if (mono_error_set_pending_exception (&error))
1191 mono_gc_wbarrier_generic_store (fields, (MonoObject*) fields_arr);
1192 for (i = 0; i < count; ++i)
1193 mono_array_setref_fast (*fields, i, values [i]);
1200 ICALL_EXPORT MonoReflectionType *
1201 ves_icall_System_Object_GetType (MonoObject *obj)
1204 MonoReflectionType *ret;
1205 #ifndef DISABLE_REMOTING
1206 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1207 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1210 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1212 mono_error_set_pending_exception (&error);
1217 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1219 MonoMethod **dest = (MonoMethod **)data;
1221 /* skip unmanaged frames */
1226 if (!strcmp (m->klass->name_space, "System.Reflection"))
1235 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1237 MonoMethod **dest = (MonoMethod **)data;
1239 /* skip unmanaged frames */
1243 if (m->wrapper_type != MONO_WRAPPER_NONE)
1251 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1262 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1264 MonoMethod **dest = (MonoMethod **)data;
1266 /* skip unmanaged frames */
1270 if (m->wrapper_type != MONO_WRAPPER_NONE)
1278 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1279 || (!strcmp (m->klass->name_space, "System"))))
1289 static MonoReflectionType *
1290 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1292 MonoMethod *m, *dest;
1294 MonoType *type = NULL;
1295 MonoAssembly *assembly = NULL;
1296 gboolean type_resolve = FALSE;
1297 MonoImage *rootimage = NULL;
1299 mono_error_init (error);
1302 * We must compute the calling assembly as type loading must happen under a metadata context.
1303 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1304 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1306 m = mono_method_get_last_managed ();
1308 if (m && m->klass->image != mono_defaults.corlib) {
1309 /* Happens with inlining */
1311 /* Ugly hack: type_from_parsed_name is called from
1312 * System.Type.internal_from_name, which is called most
1313 * directly from System.Type.GetType(string,bool,bool) but
1314 * also indirectly from places such as
1315 * System.Type.GetType(string,func,func) (via
1316 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1317 * so we need to skip over all of those to find the true caller.
1319 * It would be nice if we had stack marks.
1321 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1327 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1328 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1329 * to crash. This only seems to happen in some strange remoting
1330 * scenarios and I was unable to figure out what's happening there.
1331 * Dec 10, 2005 - Martin.
1335 assembly = dest->klass->image->assembly;
1336 type_resolve = TRUE;
1337 rootimage = assembly->image;
1339 g_warning (G_STRLOC);
1342 if (info->assembly.name)
1343 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1346 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1347 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1348 return_val_if_nok (error, NULL);
1352 // Say we're looking for System.Generic.Dict<int, Local>
1353 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1354 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1355 // is messed up when we go to construct the Local as the type arg...
1357 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1358 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1359 if (!info->assembly.name && !type) {
1361 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1362 return_val_if_nok (error, NULL);
1364 if (assembly && !type && type_resolve) {
1365 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1366 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1367 return_val_if_nok (error, NULL);
1373 return mono_type_get_object_checked (mono_domain_get (), type, error);
1376 ICALL_EXPORT MonoReflectionType*
1377 ves_icall_System_Type_internal_from_name (MonoString *name,
1378 MonoBoolean throwOnError,
1379 MonoBoolean ignoreCase)
1382 MonoTypeNameParse info;
1383 MonoReflectionType *type = NULL;
1386 char *str = mono_string_to_utf8_checked (name, &error);
1387 if (!is_ok (&error))
1390 parsedOk = mono_reflection_parse_type (str, &info);
1392 /* mono_reflection_parse_type() mangles the string */
1394 mono_reflection_free_type_info (&info);
1396 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1400 type = type_from_parsed_name (&info, ignoreCase, &error);
1402 mono_reflection_free_type_info (&info);
1404 if (!is_ok (&error))
1409 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1416 if (!is_ok (&error)) {
1418 mono_error_set_pending_exception (&error);
1420 mono_error_cleanup (&error);
1428 ICALL_EXPORT MonoReflectionType*
1429 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1432 MonoReflectionType *ret;
1433 MonoDomain *domain = mono_domain_get ();
1435 ret = mono_type_get_object_checked (domain, handle, &error);
1436 mono_error_set_pending_exception (&error);
1441 ICALL_EXPORT MonoType*
1442 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1444 return mono_class_get_type (klass);
1448 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1450 g_ptr_array_free (ptr_array, TRUE);
1454 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1460 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1463 char *res = mono_string_to_utf8_checked (s, &error);
1464 mono_error_set_pending_exception (&error);
1468 /* System.TypeCode */
1487 TYPECODE_STRING = 18
1490 ICALL_EXPORT guint32
1491 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1493 int t = type->type->type;
1495 if (type->type->byref)
1496 return TYPECODE_OBJECT;
1500 case MONO_TYPE_VOID:
1501 return TYPECODE_OBJECT;
1502 case MONO_TYPE_BOOLEAN:
1503 return TYPECODE_BOOLEAN;
1505 return TYPECODE_BYTE;
1507 return TYPECODE_SBYTE;
1509 return TYPECODE_UINT16;
1511 return TYPECODE_INT16;
1512 case MONO_TYPE_CHAR:
1513 return TYPECODE_CHAR;
1517 return TYPECODE_OBJECT;
1519 return TYPECODE_UINT32;
1521 return TYPECODE_INT32;
1523 return TYPECODE_UINT64;
1525 return TYPECODE_INT64;
1527 return TYPECODE_SINGLE;
1529 return TYPECODE_DOUBLE;
1530 case MONO_TYPE_VALUETYPE: {
1531 MonoClass *klass = type->type->data.klass;
1533 if (klass->enumtype) {
1534 t = mono_class_enum_basetype (klass)->type;
1536 } else if (mono_is_corlib_image (klass->image)) {
1537 if (strcmp (klass->name_space, "System") == 0) {
1538 if (strcmp (klass->name, "Decimal") == 0)
1539 return TYPECODE_DECIMAL;
1540 else if (strcmp (klass->name, "DateTime") == 0)
1541 return TYPECODE_DATETIME;
1544 return TYPECODE_OBJECT;
1546 case MONO_TYPE_STRING:
1547 return TYPECODE_STRING;
1548 case MONO_TYPE_SZARRAY:
1549 case MONO_TYPE_ARRAY:
1550 case MONO_TYPE_OBJECT:
1552 case MONO_TYPE_MVAR:
1553 case MONO_TYPE_TYPEDBYREF:
1554 return TYPECODE_OBJECT;
1555 case MONO_TYPE_CLASS:
1557 MonoClass *klass = type->type->data.klass;
1558 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1559 if (strcmp (klass->name, "DBNull") == 0)
1560 return TYPECODE_DBNULL;
1563 return TYPECODE_OBJECT;
1564 case MONO_TYPE_GENERICINST:
1565 return TYPECODE_OBJECT;
1567 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1573 mono_type_is_primitive (MonoType *type)
1575 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1576 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1580 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1582 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1583 return mono_class_enum_basetype (type->data.klass);
1584 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1585 return mono_class_enum_basetype (type->data.generic_class->container_class);
1589 ICALL_EXPORT guint32
1590 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1595 g_assert (type != NULL);
1597 klass = mono_class_from_mono_type (type->type);
1598 klassc = mono_class_from_mono_type (c->type);
1600 if (type->type->byref ^ c->type->byref)
1603 if (type->type->byref) {
1604 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1605 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1607 klass = mono_class_from_mono_type (t);
1608 klassc = mono_class_from_mono_type (ot);
1610 if (mono_type_is_primitive (t)) {
1611 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1612 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1613 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1614 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1615 return t->type == ot->type;
1617 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1620 if (klass->valuetype)
1621 return klass == klassc;
1622 return klass->valuetype == klassc->valuetype;
1625 return mono_class_is_assignable_from (klass, klassc);
1628 ICALL_EXPORT guint32
1629 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1632 MonoClass *klass = mono_class_from_mono_type (type->type);
1633 mono_class_init_checked (klass, &error);
1634 if (!is_ok (&error)) {
1635 mono_error_set_pending_exception (&error);
1638 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1639 mono_error_set_pending_exception (&error);
1643 ICALL_EXPORT guint32
1644 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1646 MonoClass *klass = mono_class_from_mono_type (type->type);
1647 return klass->flags;
1650 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1651 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1654 MonoClass *klass = field->field->parent;
1655 MonoMarshalType *info;
1659 if (klass->generic_container ||
1660 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1663 ftype = mono_field_get_type (field->field);
1664 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1667 info = mono_marshal_load_type_info (klass);
1669 for (i = 0; i < info->num_fields; ++i) {
1670 if (info->fields [i].field == field->field) {
1671 if (!info->fields [i].mspec)
1674 MonoReflectionMarshalAsAttribute* obj;
1675 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1676 if (!mono_error_ok (&error))
1677 mono_error_set_pending_exception (&error);
1686 ICALL_EXPORT MonoReflectionField*
1687 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1690 gboolean found = FALSE;
1696 klass = handle->parent;
1698 klass = mono_class_from_mono_type (type);
1700 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1703 /* The managed code will throw the exception */
1707 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1708 mono_error_set_pending_exception (&error);
1712 ICALL_EXPORT MonoReflectionEvent*
1713 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1721 klass = handle->parent;
1723 klass = mono_class_from_mono_type (type);
1725 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1727 /* Managed code will throw an exception */
1731 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1732 mono_error_set_pending_exception (&error);
1737 ICALL_EXPORT MonoReflectionProperty*
1738 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1746 klass = handle->parent;
1748 klass = mono_class_from_mono_type (type);
1750 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1752 /* Managed code will throw an exception */
1756 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1757 mono_error_set_pending_exception (&error);
1761 ICALL_EXPORT MonoArray*
1762 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1765 MonoType *type = mono_field_get_type_checked (field->field, &error);
1768 if (!mono_error_ok (&error)) {
1769 mono_error_set_pending_exception (&error);
1773 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1774 mono_error_set_pending_exception (&error);
1779 vell_icall_get_method_attributes (MonoMethod *method)
1781 return method->flags;
1785 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1788 MonoReflectionType *rt;
1789 MonoDomain *domain = mono_domain_get ();
1790 MonoMethodSignature* sig;
1792 sig = mono_method_signature_checked (method, &error);
1793 if (!mono_error_ok (&error)) {
1794 mono_error_set_pending_exception (&error);
1798 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1799 if (!mono_error_ok (&error)) {
1800 mono_error_set_pending_exception (&error);
1804 MONO_STRUCT_SETREF (info, parent, rt);
1806 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1807 if (!mono_error_ok (&error)) {
1808 mono_error_set_pending_exception (&error);
1812 MONO_STRUCT_SETREF (info, ret, rt);
1814 info->attrs = method->flags;
1815 info->implattrs = method->iflags;
1816 if (sig->call_convention == MONO_CALL_DEFAULT)
1817 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1819 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1824 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1827 ICALL_EXPORT MonoArray*
1828 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1831 MonoDomain *domain = mono_domain_get ();
1833 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1834 mono_error_set_pending_exception (&error);
1838 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1839 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1842 MonoDomain *domain = mono_domain_get ();
1843 MonoReflectionMarshalAsAttribute* res = NULL;
1844 MonoMarshalSpec **mspecs;
1847 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1848 mono_method_get_marshal_info (method, mspecs);
1851 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1852 if (!mono_error_ok (&error)) {
1853 mono_error_set_pending_exception (&error);
1858 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1860 mono_metadata_free_marshal_spec (mspecs [i]);
1867 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1869 MonoClass *parent = field->field->parent;
1870 if (!parent->size_inited)
1871 mono_class_init (parent);
1872 mono_class_setup_fields_locking (parent);
1874 return field->field->offset - sizeof (MonoObject);
1877 ICALL_EXPORT MonoReflectionType*
1878 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1881 MonoReflectionType *ret;
1884 parent = declaring? field->field->parent: field->klass;
1886 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1887 mono_error_set_pending_exception (&error);
1893 ICALL_EXPORT MonoObject *
1894 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1897 MonoClass *fklass = field->klass;
1898 MonoClassField *cf = field->field;
1899 MonoDomain *domain = mono_object_domain (field);
1901 if (fklass->image->assembly->ref_only) {
1902 mono_set_pending_exception (mono_get_exception_invalid_operation (
1903 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1907 if (mono_security_core_clr_enabled () &&
1908 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1909 mono_error_set_pending_exception (&error);
1913 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1914 mono_error_set_pending_exception (&error);
1919 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1922 MonoClassField *cf = field->field;
1926 if (field->klass->image->assembly->ref_only) {
1927 mono_set_pending_exception (mono_get_exception_invalid_operation (
1928 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1932 if (mono_security_core_clr_enabled () &&
1933 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
1934 mono_error_set_pending_exception (&error);
1938 type = mono_field_get_type_checked (cf, &error);
1939 if (!mono_error_ok (&error)) {
1940 mono_error_set_pending_exception (&error);
1944 v = (gchar *) value;
1946 switch (type->type) {
1949 case MONO_TYPE_BOOLEAN:
1952 case MONO_TYPE_CHAR:
1961 case MONO_TYPE_VALUETYPE:
1964 v += sizeof (MonoObject);
1966 case MONO_TYPE_STRING:
1967 case MONO_TYPE_OBJECT:
1968 case MONO_TYPE_CLASS:
1969 case MONO_TYPE_ARRAY:
1970 case MONO_TYPE_SZARRAY:
1973 case MONO_TYPE_GENERICINST: {
1974 MonoGenericClass *gclass = type->data.generic_class;
1975 g_assert (!gclass->context.class_inst->is_open);
1977 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1978 MonoClass *nklass = mono_class_from_mono_type (type);
1979 MonoObject *nullable;
1982 * Convert the boxed vtype into a Nullable structure.
1983 * This is complicated by the fact that Nullables have
1984 * a variable structure.
1986 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1987 if (!mono_error_ok (&error)) {
1988 mono_error_set_pending_exception (&error);
1992 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1994 v = (gchar *)mono_object_unbox (nullable);
1997 if (gclass->container_class->valuetype && (v != NULL))
1998 v += sizeof (MonoObject);
2002 g_error ("type 0x%x not handled in "
2003 "ves_icall_FieldInfo_SetValueInternal", type->type);
2008 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2009 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2010 if (!is_ok (&error)) {
2011 mono_error_set_pending_exception (&error);
2014 if (!vtable->initialized) {
2015 if (!mono_runtime_class_init_full (vtable, &error)) {
2016 mono_error_set_pending_exception (&error);
2020 mono_field_static_set_value (vtable, cf, v);
2022 mono_field_set_value (obj, cf, v);
2027 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2036 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2037 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2041 if (MONO_TYPE_IS_REFERENCE (f->type))
2042 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2044 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2047 ICALL_EXPORT MonoObject *
2048 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2050 MonoObject *o = NULL;
2051 MonoClassField *field = rfield->field;
2053 MonoDomain *domain = mono_object_domain (rfield);
2055 MonoTypeEnum def_type;
2056 const char *def_value;
2060 mono_class_init (field->parent);
2062 t = mono_field_get_type_checked (field, &error);
2063 if (!mono_error_ok (&error)) {
2064 mono_error_set_pending_exception (&error);
2068 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2069 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2073 if (image_is_dynamic (field->parent->image)) {
2074 MonoClass *klass = field->parent;
2075 int fidx = field - klass->fields;
2077 g_assert (fidx >= 0 && fidx < klass->field.count);
2078 g_assert (klass->ext);
2079 g_assert (klass->ext->field_def_values);
2080 def_type = klass->ext->field_def_values [fidx].def_type;
2081 def_value = klass->ext->field_def_values [fidx].data;
2082 if (def_type == MONO_TYPE_END) {
2083 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2087 def_value = mono_class_get_field_default_value (field, &def_type);
2088 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2090 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2095 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2099 case MONO_TYPE_BOOLEAN:
2102 case MONO_TYPE_CHAR:
2110 case MONO_TYPE_R8: {
2113 /* boxed value type */
2114 t = g_new0 (MonoType, 1);
2116 klass = mono_class_from_mono_type (t);
2118 o = mono_object_new_checked (domain, klass, &error);
2119 if (!mono_error_ok (&error)) {
2120 mono_error_set_pending_exception (&error);
2123 v = ((gchar *) o) + sizeof (MonoObject);
2124 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2125 if (mono_error_set_pending_exception (&error))
2129 case MONO_TYPE_STRING:
2130 case MONO_TYPE_CLASS:
2131 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2132 if (mono_error_set_pending_exception (&error))
2136 g_assert_not_reached ();
2142 ICALL_EXPORT MonoReflectionType*
2143 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2146 MonoReflectionType *ret;
2149 type = mono_field_get_type_checked (ref_field->field, &error);
2150 if (!mono_error_ok (&error)) {
2151 mono_error_set_pending_exception (&error);
2155 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2156 if (!mono_error_ok (&error)) {
2157 mono_error_set_pending_exception (&error);
2164 /* From MonoProperty.cs */
2166 PInfo_Attributes = 1,
2167 PInfo_GetMethod = 1 << 1,
2168 PInfo_SetMethod = 1 << 2,
2169 PInfo_ReflectedType = 1 << 3,
2170 PInfo_DeclaringType = 1 << 4,
2175 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2178 MonoReflectionType *rt;
2179 MonoReflectionMethod *rm;
2180 MonoDomain *domain = mono_object_domain (property);
2181 const MonoProperty *pproperty = property->property;
2183 if ((req_info & PInfo_ReflectedType) != 0) {
2184 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2185 if (mono_error_set_pending_exception (&error))
2188 MONO_STRUCT_SETREF (info, parent, rt);
2190 if ((req_info & PInfo_DeclaringType) != 0) {
2191 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2192 if (mono_error_set_pending_exception (&error))
2195 MONO_STRUCT_SETREF (info, declaring_type, rt);
2198 if ((req_info & PInfo_Name) != 0)
2199 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2201 if ((req_info & PInfo_Attributes) != 0)
2202 info->attrs = pproperty->attrs;
2204 if ((req_info & PInfo_GetMethod) != 0) {
2205 if (pproperty->get &&
2206 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2207 pproperty->get->klass == property->klass)) {
2208 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2209 if (mono_error_set_pending_exception (&error))
2215 MONO_STRUCT_SETREF (info, get, rm);
2217 if ((req_info & PInfo_SetMethod) != 0) {
2218 if (pproperty->set &&
2219 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2220 pproperty->set->klass == property->klass)) {
2221 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2222 if (mono_error_set_pending_exception (&error))
2228 MONO_STRUCT_SETREF (info, set, rm);
2231 * There may be other methods defined for properties, though, it seems they are not exposed
2232 * in the reflection API
2237 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2240 MonoReflectionType *rt;
2241 MonoReflectionMethod *rm;
2242 MonoDomain *domain = mono_object_domain (event);
2244 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2245 if (mono_error_set_pending_exception (&error))
2248 MONO_STRUCT_SETREF (info, reflected_type, rt);
2250 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2251 if (mono_error_set_pending_exception (&error))
2254 MONO_STRUCT_SETREF (info, declaring_type, rt);
2256 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2257 info->attrs = event->event->attrs;
2259 if (event->event->add) {
2260 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2261 if (mono_error_set_pending_exception (&error))
2267 MONO_STRUCT_SETREF (info, add_method, rm);
2269 if (event->event->remove) {
2270 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2271 if (mono_error_set_pending_exception (&error))
2277 MONO_STRUCT_SETREF (info, remove_method, rm);
2279 if (event->event->raise) {
2280 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2281 if (mono_error_set_pending_exception (&error))
2287 MONO_STRUCT_SETREF (info, raise_method, rm);
2289 #ifndef MONO_SMALL_CONFIG
2290 if (event->event->other) {
2292 while (event->event->other [n])
2294 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2295 if (mono_error_set_pending_exception (&error))
2297 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2299 for (i = 0; i < n; i++) {
2300 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2301 if (mono_error_set_pending_exception (&error))
2303 mono_array_setref (info->other_methods, i, rm);
2310 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2315 mono_class_setup_interfaces (klass, error);
2316 if (!mono_error_ok (error))
2319 for (i = 0; i < klass->interface_count; i++) {
2320 ic = klass->interfaces [i];
2321 g_hash_table_insert (ifaces, ic, ic);
2323 collect_interfaces (ic, ifaces, error);
2324 if (!mono_error_ok (error))
2330 MonoArray *iface_array;
2331 MonoGenericContext *context;
2335 } FillIfaceArrayData;
2338 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2340 MonoReflectionType *rt;
2341 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2342 MonoClass *ic = (MonoClass *)key;
2343 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2345 if (!mono_error_ok (data->error))
2348 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2349 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2350 if (!mono_error_ok (data->error))
2354 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2355 if (!mono_error_ok (data->error))
2358 mono_array_setref (data->iface_array, data->next_idx++, rt);
2361 mono_metadata_free_type (inflated);
2365 get_interfaces_hash (gconstpointer v1)
2367 MonoClass *k = (MonoClass*)v1;
2369 return k->type_token;
2372 ICALL_EXPORT MonoArray*
2373 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2376 MonoClass *klass = mono_class_from_mono_type (type->type);
2378 FillIfaceArrayData data = { 0 };
2381 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2383 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2384 data.context = mono_class_get_context (klass);
2385 klass = klass->generic_class->container_class;
2388 for (parent = klass; parent; parent = parent->parent) {
2389 mono_class_setup_interfaces (parent, &error);
2390 if (!mono_error_ok (&error))
2392 collect_interfaces (parent, iface_hash, &error);
2393 if (!mono_error_ok (&error))
2397 data.error = &error;
2398 data.domain = mono_object_domain (type);
2400 len = g_hash_table_size (iface_hash);
2402 g_hash_table_destroy (iface_hash);
2403 if (!data.domain->empty_types) {
2404 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2405 if (!is_ok (&error))
2408 return data.domain->empty_types;
2411 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2412 if (!is_ok (&error))
2414 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2415 if (!mono_error_ok (&error))
2418 g_hash_table_destroy (iface_hash);
2419 return data.iface_array;
2422 g_hash_table_destroy (iface_hash);
2423 mono_error_set_pending_exception (&error);
2428 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2430 gboolean variance_used;
2431 MonoClass *klass = mono_class_from_mono_type (type->type);
2432 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2433 MonoReflectionMethod *member;
2436 int i = 0, len, ioffset;
2440 mono_class_init_checked (klass, &error);
2441 if (mono_error_set_pending_exception (&error))
2443 mono_class_init_checked (iclass, &error);
2444 if (mono_error_set_pending_exception (&error))
2447 mono_class_setup_vtable (klass);
2449 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2453 len = mono_class_num_methods (iclass);
2454 domain = mono_object_domain (type);
2455 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2456 if (mono_error_set_pending_exception (&error))
2458 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2459 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2460 if (mono_error_set_pending_exception (&error))
2462 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2464 while ((method = mono_class_get_methods (iclass, &iter))) {
2465 member = mono_method_get_object_checked (domain, method, iclass, &error);
2466 if (mono_error_set_pending_exception (&error))
2468 mono_array_setref (*methods, i, member);
2469 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2470 if (mono_error_set_pending_exception (&error))
2472 mono_array_setref (*targets, i, member);
2479 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2482 MonoClass *klass = mono_class_from_mono_type (type->type);
2484 mono_class_init_checked (klass, &error);
2485 if (mono_error_set_pending_exception (&error))
2488 if (image_is_dynamic (klass->image)) {
2489 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2490 *packing = tb->packing_size;
2491 *size = tb->class_size;
2493 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2497 ICALL_EXPORT MonoReflectionType*
2498 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2501 MonoReflectionType *ret;
2504 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2505 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2506 mono_error_set_pending_exception (&error);
2510 klass = mono_class_from_mono_type (type->type);
2511 mono_class_init_checked (klass, &error);
2512 if (mono_error_set_pending_exception (&error))
2516 // GetElementType should only return a type for:
2517 // Array Pointer PassedByRef
2518 if (type->type->byref)
2519 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2520 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2521 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2522 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2523 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2527 mono_error_set_pending_exception (&error);
2532 ICALL_EXPORT MonoReflectionType*
2533 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2536 MonoReflectionType *ret;
2538 if (type->type->byref)
2541 MonoClass *klass = mono_class_from_mono_type (type->type);
2545 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2546 mono_error_set_pending_exception (&error);
2551 ICALL_EXPORT MonoBoolean
2552 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2554 return type->type->type == MONO_TYPE_PTR;
2557 ICALL_EXPORT MonoBoolean
2558 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2560 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)));
2563 ICALL_EXPORT MonoBoolean
2564 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2566 return type->type->byref;
2569 ICALL_EXPORT MonoBoolean
2570 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2573 MonoClass *klass = mono_class_from_mono_type (type->type);
2574 mono_class_init_checked (klass, &error);
2575 if (mono_error_set_pending_exception (&error))
2578 return mono_class_is_com_object (klass);
2581 ICALL_EXPORT guint32
2582 ves_icall_reflection_get_token (MonoObject* obj)
2585 guint32 result = mono_reflection_get_token_checked (obj, &error);
2586 mono_error_set_pending_exception (&error);
2590 ICALL_EXPORT MonoReflectionModule*
2591 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2594 MonoReflectionModule *result = NULL;
2595 MonoClass *klass = mono_class_from_mono_type (type->type);
2596 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2597 mono_error_set_pending_exception (&error);
2601 ICALL_EXPORT MonoReflectionAssembly*
2602 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2605 MonoDomain *domain = mono_domain_get ();
2606 MonoClass *klass = mono_class_from_mono_type (type->type);
2607 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2608 mono_error_set_pending_exception (&error);
2612 ICALL_EXPORT MonoReflectionType*
2613 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2616 MonoReflectionType *ret;
2617 MonoDomain *domain = mono_domain_get ();
2620 if (type->type->byref)
2622 if (type->type->type == MONO_TYPE_VAR) {
2623 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2624 klass = param ? param->owner.klass : NULL;
2625 } else if (type->type->type == MONO_TYPE_MVAR) {
2626 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2627 klass = param ? param->owner.method->klass : NULL;
2629 klass = mono_class_from_mono_type (type->type)->nested_in;
2635 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2636 mono_error_set_pending_exception (&error);
2641 ICALL_EXPORT MonoString*
2642 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2644 MonoDomain *domain = mono_domain_get ();
2645 MonoClass *klass = mono_class_from_mono_type (type->type);
2647 if (type->type->byref) {
2648 char *n = g_strdup_printf ("%s&", klass->name);
2649 MonoString *res = mono_string_new (domain, n);
2655 return mono_string_new (domain, klass->name);
2659 ICALL_EXPORT MonoString*
2660 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2662 MonoDomain *domain = mono_domain_get ();
2663 MonoClass *klass = mono_class_from_mono_type (type->type);
2665 while (klass->nested_in)
2666 klass = klass->nested_in;
2668 if (klass->name_space [0] == '\0')
2671 return mono_string_new (domain, klass->name_space);
2675 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2679 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2680 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2684 klass = mono_class_from_mono_type (type->type);
2690 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2692 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2695 ICALL_EXPORT MonoArray*
2696 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2699 MonoReflectionType *rt;
2701 MonoClass *klass, *pklass;
2702 MonoDomain *domain = mono_object_domain (type);
2705 klass = mono_class_from_mono_type (type->type);
2707 if (klass->generic_container) {
2708 MonoGenericContainer *container = klass->generic_container;
2709 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2710 if (mono_error_set_pending_exception (&error))
2712 for (i = 0; i < container->type_argc; ++i) {
2713 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2715 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2716 if (mono_error_set_pending_exception (&error))
2719 mono_array_setref (res, i, rt);
2721 } else if (klass->generic_class) {
2722 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2723 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2724 if (mono_error_set_pending_exception (&error))
2726 for (i = 0; i < inst->type_argc; ++i) {
2727 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2728 if (mono_error_set_pending_exception (&error))
2731 mono_array_setref (res, i, rt);
2739 ICALL_EXPORT gboolean
2740 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2744 if (!IS_MONOTYPE (type))
2747 if (type->type->byref)
2750 klass = mono_class_from_mono_type (type->type);
2751 return klass->generic_container != NULL;
2754 ICALL_EXPORT MonoReflectionType*
2755 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2758 MonoReflectionType *ret;
2761 if (type->type->byref)
2764 klass = mono_class_from_mono_type (type->type);
2766 if (klass->generic_container) {
2767 return type; /* check this one */
2769 if (klass->generic_class) {
2770 MonoClass *generic_class = klass->generic_class->container_class;
2773 tb = mono_class_get_ref_info (generic_class);
2775 if (generic_class->wastypebuilder && tb)
2776 return (MonoReflectionType *)tb;
2778 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2779 mono_error_set_pending_exception (&error);
2787 ICALL_EXPORT MonoReflectionType*
2788 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2791 MonoReflectionType *ret;
2793 MonoType *geninst, **types;
2796 g_assert (IS_MONOTYPE (type));
2797 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2798 if (mono_error_set_pending_exception (&error))
2801 count = mono_array_length (type_array);
2802 types = g_new0 (MonoType *, count);
2804 for (i = 0; i < count; i++) {
2805 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2806 types [i] = t->type;
2809 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2812 mono_error_set_pending_exception (&error);
2816 klass = mono_class_from_mono_type (geninst);
2818 /*we might inflate to the GTD*/
2819 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2820 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2824 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2825 mono_error_set_pending_exception (&error);
2830 ICALL_EXPORT gboolean
2831 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2835 if (!IS_MONOTYPE (type))
2838 if (type->type->byref)
2841 klass = mono_class_from_mono_type (type->type);
2842 return klass->generic_class != NULL || klass->generic_container != NULL;
2846 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2848 if (!IS_MONOTYPE (type))
2851 if (is_generic_parameter (type->type))
2852 return mono_type_get_generic_param_num (type->type);
2856 ICALL_EXPORT MonoGenericParamInfo *
2857 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2859 return mono_generic_param_info (type->type->data.generic_param);
2862 ICALL_EXPORT MonoBoolean
2863 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2865 return is_generic_parameter (type->type);
2868 ICALL_EXPORT MonoReflectionMethod*
2869 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2870 MonoReflectionMethod* generic)
2877 MonoReflectionMethod *ret = NULL;
2879 domain = ((MonoObject *)type)->vtable->domain;
2881 klass = mono_class_from_mono_type (type->type);
2882 mono_class_init_checked (klass, &error);
2883 if (mono_error_set_pending_exception (&error))
2887 while ((method = mono_class_get_methods (klass, &iter))) {
2888 if (method->token == generic->method->token) {
2889 ret = mono_method_get_object_checked (domain, method, klass, &error);
2890 if (mono_error_set_pending_exception (&error))
2898 ICALL_EXPORT MonoReflectionMethod *
2899 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
2902 MonoType *type = ref_type->type;
2904 MonoReflectionMethod *ret = NULL;
2906 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2907 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2910 if (type->type == MONO_TYPE_VAR)
2913 method = mono_type_get_generic_param_owner (type)->owner.method;
2916 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2917 if (!mono_error_ok (&error))
2918 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2922 ICALL_EXPORT MonoBoolean
2923 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2925 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2929 ICALL_EXPORT MonoBoolean
2930 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2932 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2937 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2939 MonoDomain *domain = mono_domain_get ();
2940 MonoImage *image = method->method->klass->image;
2941 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2942 MonoTableInfo *tables = image->tables;
2943 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2944 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2945 guint32 im_cols [MONO_IMPLMAP_SIZE];
2946 guint32 scope_token;
2947 const char *import = NULL;
2948 const char *scope = NULL;
2950 if (image_is_dynamic (image)) {
2951 MonoReflectionMethodAux *method_aux =
2952 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2954 import = method_aux->dllentry;
2955 scope = method_aux->dll;
2958 if (!import || !scope) {
2959 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2964 if (piinfo->implmap_idx) {
2965 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2967 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2968 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2969 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2970 scope = mono_metadata_string_heap (image, scope_token);
2974 *flags = piinfo->piflags;
2975 *entry_point = mono_string_new (domain, import);
2976 *dll_name = mono_string_new (domain, scope);
2979 ICALL_EXPORT MonoReflectionMethod *
2980 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2982 MonoMethodInflated *imethod;
2984 MonoReflectionMethod *ret = NULL;
2987 if (method->method->is_generic)
2990 if (!method->method->is_inflated)
2993 imethod = (MonoMethodInflated *) method->method;
2995 result = imethod->declaring;
2996 /* Not a generic method. */
2997 if (!result->is_generic)
3000 if (image_is_dynamic (method->method->klass->image)) {
3001 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3002 MonoReflectionMethod *res;
3005 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3006 * the dynamic case as well ?
3008 mono_image_lock ((MonoImage*)image);
3009 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3010 mono_image_unlock ((MonoImage*)image);
3016 if (imethod->context.class_inst) {
3017 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3018 /*Generic methods gets the context of the GTD.*/
3019 if (mono_class_get_context (klass)) {
3020 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3021 if (!mono_error_ok (&error))
3026 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3028 if (!mono_error_ok (&error))
3029 mono_error_set_pending_exception (&error);
3033 ICALL_EXPORT gboolean
3034 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3036 return mono_method_signature (method->method)->generic_param_count != 0;
3039 ICALL_EXPORT gboolean
3040 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3042 return method->method->is_generic;
3045 ICALL_EXPORT MonoArray*
3046 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3049 MonoReflectionType *rt;
3054 domain = mono_object_domain (method);
3056 if (method->method->is_inflated) {
3057 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3060 count = inst->type_argc;
3061 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3062 if (mono_error_set_pending_exception (&error))
3065 for (i = 0; i < count; i++) {
3066 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3067 if (mono_error_set_pending_exception (&error))
3070 mono_array_setref (res, i, rt);
3077 count = mono_method_signature (method->method)->generic_param_count;
3078 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3079 if (mono_error_set_pending_exception (&error))
3082 for (i = 0; i < count; i++) {
3083 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3084 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3085 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3087 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3088 if (mono_error_set_pending_exception (&error))
3091 mono_array_setref (res, i, rt);
3097 ICALL_EXPORT MonoObject *
3098 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3102 * Invoke from reflection is supposed to always be a virtual call (the API
3103 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3104 * greater flexibility.
3106 MonoMethod *m = method->method;
3107 MonoMethodSignature *sig = mono_method_signature (m);
3110 void *obj = this_arg;
3114 if (mono_security_core_clr_enabled () &&
3115 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3116 mono_error_set_pending_exception (&error);
3120 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3121 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3122 mono_error_cleanup (&error); /* FIXME does this make sense? */
3123 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3128 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3129 if (!is_ok (&error)) {
3130 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3133 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3134 char *target_name = mono_type_get_full_name (m->klass);
3135 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3136 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3138 g_free (target_name);
3142 m = mono_object_get_virtual_method (this_arg, m);
3143 /* must pass the pointer to the value for valuetype methods */
3144 if (m->klass->valuetype)
3145 obj = mono_object_unbox (this_arg);
3146 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3147 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3152 if (sig->ret->byref) {
3153 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"));
3157 pcount = params? mono_array_length (params): 0;
3158 if (pcount != sig->param_count) {
3159 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3163 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3164 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."));
3168 image = m->klass->image;
3169 if (image->assembly->ref_only) {
3170 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."));
3174 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3175 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3179 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3183 intptr_t *lower_bounds;
3184 pcount = mono_array_length (params);
3185 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3186 /* Note: the synthetized array .ctors have int32 as argument type */
3187 for (i = 0; i < pcount; ++i)
3188 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3190 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3191 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3192 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3193 if (!mono_error_ok (&error)) {
3194 mono_error_set_pending_exception (&error);
3198 for (i = 0; i < mono_array_length (arr); ++i) {
3199 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3200 if (!mono_error_ok (&error)) {
3201 mono_error_set_pending_exception (&error);
3204 mono_array_setref_fast (arr, i, subarray);
3206 return (MonoObject*)arr;
3209 if (m->klass->rank == pcount) {
3210 /* Only lengths provided. */
3211 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3212 if (!mono_error_ok (&error)) {
3213 mono_error_set_pending_exception (&error);
3217 return (MonoObject*)arr;
3219 g_assert (pcount == (m->klass->rank * 2));
3220 /* The arguments are lower-bound-length pairs */
3221 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3223 for (i = 0; i < pcount / 2; ++i) {
3224 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3225 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3228 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3229 if (!mono_error_ok (&error)) {
3230 mono_error_set_pending_exception (&error);
3234 return (MonoObject*)arr;
3237 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3238 mono_error_set_pending_exception (&error);
3242 #ifndef DISABLE_REMOTING
3243 ICALL_EXPORT MonoObject *
3244 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3247 MonoDomain *domain = mono_object_domain (method);
3248 MonoMethod *m = method->method;
3249 MonoMethodSignature *sig = mono_method_signature (m);
3250 MonoArray *out_args;
3252 int i, j, outarg_count = 0;
3254 if (m->klass == mono_defaults.object_class) {
3255 if (!strcmp (m->name, "FieldGetter")) {
3256 MonoClass *k = this_arg->vtable->klass;
3260 /* If this is a proxy, then it must be a CBO */
3261 if (k == mono_defaults.transparent_proxy_class) {
3262 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3263 this_arg = tp->rp->unwrapped_server;
3264 g_assert (this_arg);
3265 k = this_arg->vtable->klass;
3268 name = mono_array_get (params, MonoString *, 1);
3269 str = mono_string_to_utf8_checked (name, &error);
3270 if (mono_error_set_pending_exception (&error))
3274 MonoClassField* field = mono_class_get_field_from_name (k, str);
3277 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3278 if (field_klass->valuetype) {
3279 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3280 if (mono_error_set_pending_exception (&error))
3283 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3285 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3286 if (mono_error_set_pending_exception (&error))
3288 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3289 mono_array_setref (out_args, 0, result);
3296 g_assert_not_reached ();
3298 } else if (!strcmp (m->name, "FieldSetter")) {
3299 MonoClass *k = this_arg->vtable->klass;
3305 /* If this is a proxy, then it must be a CBO */
3306 if (k == mono_defaults.transparent_proxy_class) {
3307 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3308 this_arg = tp->rp->unwrapped_server;
3309 g_assert (this_arg);
3310 k = this_arg->vtable->klass;
3313 name = mono_array_get (params, MonoString *, 1);
3314 str = mono_string_to_utf8_checked (name, &error);
3315 if (mono_error_set_pending_exception (&error))
3319 MonoClassField* field = mono_class_get_field_from_name (k, str);
3322 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3323 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3325 if (field_klass->valuetype) {
3326 size = mono_type_size (field->type, &align);
3327 g_assert (size == mono_class_value_size (field_klass, NULL));
3328 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3330 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3333 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3334 if (mono_error_set_pending_exception (&error))
3336 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3345 g_assert_not_reached ();
3350 for (i = 0; i < mono_array_length (params); i++) {
3351 if (sig->params [i]->byref)
3355 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3356 if (mono_error_set_pending_exception (&error))
3359 /* handle constructors only for objects already allocated */
3360 if (!strcmp (method->method->name, ".ctor"))
3361 g_assert (this_arg);
3363 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3364 g_assert (!method->method->klass->valuetype);
3365 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3366 if (mono_error_set_pending_exception (&error))
3369 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3370 if (sig->params [i]->byref) {
3372 arg = mono_array_get (params, gpointer, i);
3373 mono_array_setref (out_args, j, arg);
3378 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3385 read_enum_value (const char *mem, int type)
3388 case MONO_TYPE_BOOLEAN:
3390 return *(guint8*)mem;
3392 return *(gint8*)mem;
3393 case MONO_TYPE_CHAR:
3395 return read16 (mem);
3397 return (gint16) read16 (mem);
3399 return read32 (mem);
3401 return (gint32) read32 (mem);
3404 return read64 (mem);
3406 g_assert_not_reached ();
3412 write_enum_value (char *mem, int type, guint64 value)
3416 case MONO_TYPE_I1: {
3417 guint8 *p = (guint8*)mem;
3423 case MONO_TYPE_CHAR: {
3424 guint16 *p = (guint16 *)mem;
3429 case MONO_TYPE_I4: {
3430 guint32 *p = (guint32 *)mem;
3435 case MONO_TYPE_I8: {
3436 guint64 *p = (guint64 *)mem;
3441 g_assert_not_reached ();
3446 ICALL_EXPORT MonoObject *
3447 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3455 domain = mono_object_domain (enumType);
3456 enumc = mono_class_from_mono_type (enumType->type);
3458 mono_class_init_checked (enumc, &error);
3459 if (mono_error_set_pending_exception (&error))
3462 etype = mono_class_enum_basetype (enumc);
3464 res = mono_object_new_checked (domain, enumc, &error);
3465 if (mono_error_set_pending_exception (&error))
3467 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3472 ICALL_EXPORT MonoBoolean
3473 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3475 int size = mono_class_value_size (a->vtable->klass, NULL);
3476 guint64 a_val = 0, b_val = 0;
3478 memcpy (&a_val, mono_object_unbox (a), size);
3479 memcpy (&b_val, mono_object_unbox (b), size);
3481 return (a_val & b_val) == b_val;
3484 ICALL_EXPORT MonoObject *
3485 ves_icall_System_Enum_get_value (MonoObject *eobj)
3497 g_assert (eobj->vtable->klass->enumtype);
3499 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3500 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3501 if (mono_error_set_pending_exception (&error))
3503 dst = (char *)res + sizeof (MonoObject);
3504 src = (char *)eobj + sizeof (MonoObject);
3505 size = mono_class_value_size (enumc, NULL);
3507 memcpy (dst, src, size);
3512 ICALL_EXPORT MonoReflectionType *
3513 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3516 MonoReflectionType *ret;
3520 klass = mono_class_from_mono_type (type->type);
3521 mono_class_init_checked (klass, &error);
3522 if (mono_error_set_pending_exception (&error))
3525 etype = mono_class_enum_basetype (klass);
3527 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3531 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3532 mono_error_set_pending_exception (&error);
3538 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3540 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3541 gpointer odata = (char *)other + sizeof (MonoObject);
3542 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3543 g_assert (basetype);
3548 if (eobj->vtable->klass != other->vtable->klass)
3551 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3552 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3553 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3556 return me > other ? 1 : -1; \
3559 switch (basetype->type) {
3561 COMPARE_ENUM_VALUES (guint8);
3563 COMPARE_ENUM_VALUES (gint8);
3564 case MONO_TYPE_CHAR:
3566 COMPARE_ENUM_VALUES (guint16);
3568 COMPARE_ENUM_VALUES (gint16);
3570 COMPARE_ENUM_VALUES (guint32);
3572 COMPARE_ENUM_VALUES (gint32);
3574 COMPARE_ENUM_VALUES (guint64);
3576 COMPARE_ENUM_VALUES (gint64);
3580 #undef COMPARE_ENUM_VALUES
3581 /* indicates that the enum was of an unsupported unerlying type */
3586 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3588 gpointer data = (char *)eobj + sizeof (MonoObject);
3589 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3590 g_assert (basetype);
3592 switch (basetype->type) {
3593 case MONO_TYPE_I1: {
3594 gint8 value = *((gint8*)data);
3595 return ((int)value ^ (int)value << 8);
3598 return *((guint8*)data);
3599 case MONO_TYPE_CHAR:
3601 return *((guint16*)data);
3603 case MONO_TYPE_I2: {
3604 gint16 value = *((gint16*)data);
3605 return ((int)(guint16)value | (((int)value) << 16));
3608 return *((guint32*)data);
3610 return *((gint32*)data);
3612 case MONO_TYPE_I8: {
3613 gint64 value = *((gint64*)data);
3614 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3617 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3622 ICALL_EXPORT MonoBoolean
3623 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3626 MonoDomain *domain = mono_object_domain (type);
3627 MonoClass *enumc = mono_class_from_mono_type (type->type);
3628 guint j = 0, nvalues;
3630 MonoClassField *field;
3632 guint64 field_value, previous_value = 0;
3633 gboolean sorted = TRUE;
3635 mono_class_init_checked (enumc, &error);
3636 if (mono_error_set_pending_exception (&error))
3640 if (!enumc->enumtype) {
3641 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3645 base_type = mono_class_enum_basetype (enumc)->type;
3647 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3648 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3649 if (mono_error_set_pending_exception (&error))
3651 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3652 if (mono_error_set_pending_exception (&error))
3656 while ((field = mono_class_get_fields (enumc, &iter))) {
3658 MonoTypeEnum def_type;
3660 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3662 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3664 if (mono_field_is_deleted (field))
3666 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3668 p = mono_class_get_field_default_value (field, &def_type);
3669 /* len = */ mono_metadata_decode_blob_size (p, &p);
3671 field_value = read_enum_value (p, base_type);
3672 mono_array_set (*values, guint64, j, field_value);
3674 if (previous_value > field_value)
3677 previous_value = field_value;
3685 BFLAGS_IgnoreCase = 1,
3686 BFLAGS_DeclaredOnly = 2,
3687 BFLAGS_Instance = 4,
3689 BFLAGS_Public = 0x10,
3690 BFLAGS_NonPublic = 0x20,
3691 BFLAGS_FlattenHierarchy = 0x40,
3692 BFLAGS_InvokeMethod = 0x100,
3693 BFLAGS_CreateInstance = 0x200,
3694 BFLAGS_GetField = 0x400,
3695 BFLAGS_SetField = 0x800,
3696 BFLAGS_GetProperty = 0x1000,
3697 BFLAGS_SetProperty = 0x2000,
3698 BFLAGS_ExactBinding = 0x10000,
3699 BFLAGS_SuppressChangeType = 0x20000,
3700 BFLAGS_OptionalParamBinding = 0x40000
3703 ICALL_EXPORT GPtrArray*
3704 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3707 MonoClass *startklass, *klass;
3710 int (*compare_func) (const char *s1, const char *s2) = NULL;
3711 MonoClassField *field;
3713 if (type->type->byref) {
3714 return g_ptr_array_new ();
3717 mono_error_init (&error);
3719 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3721 klass = startklass = mono_class_from_mono_type (type->type);
3723 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3726 if (mono_class_has_failure (klass)) {
3727 mono_error_set_for_class_failure (&error, klass);
3732 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3733 guint32 flags = mono_field_get_flags (field);
3735 if (mono_field_is_deleted_with_flags (field, flags))
3737 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3738 if (bflags & BFLAGS_Public)
3740 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3741 if (bflags & BFLAGS_NonPublic) {
3748 if (flags & FIELD_ATTRIBUTE_STATIC) {
3749 if (bflags & BFLAGS_Static)
3750 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3753 if (bflags & BFLAGS_Instance)
3760 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3763 g_ptr_array_add (ptr_array, field);
3765 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3771 g_ptr_array_free (ptr_array, TRUE);
3772 mono_error_set_pending_exception (&error);
3777 method_nonpublic (MonoMethod* method, gboolean start_klass)
3779 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3780 case METHOD_ATTRIBUTE_ASSEM:
3781 return (start_klass || mono_defaults.generic_ilist_class);
3782 case METHOD_ATTRIBUTE_PRIVATE:
3784 case METHOD_ATTRIBUTE_PUBLIC:
3792 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3795 MonoClass *startklass;
3799 /*FIXME, use MonoBitSet*/
3800 guint32 method_slots_default [8];
3801 guint32 *method_slots = NULL;
3802 int (*compare_func) (const char *s1, const char *s2) = NULL;
3804 array = g_ptr_array_new ();
3806 mono_error_init (error);
3809 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3811 /* An optimization for calls made from Delegate:CreateDelegate () */
3812 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3813 method = mono_get_delegate_invoke (klass);
3816 g_ptr_array_add (array, method);
3820 mono_class_setup_methods (klass);
3821 mono_class_setup_vtable (klass);
3822 if (mono_class_has_failure (klass))
3825 if (is_generic_parameter (&klass->byval_arg))
3826 nslots = mono_class_get_vtable_size (klass->parent);
3828 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3829 if (nslots >= sizeof (method_slots_default) * 8) {
3830 method_slots = g_new0 (guint32, nslots / 32 + 1);
3832 method_slots = method_slots_default;
3833 memset (method_slots, 0, sizeof (method_slots_default));
3836 mono_class_setup_methods (klass);
3837 mono_class_setup_vtable (klass);
3838 if (mono_class_has_failure (klass))
3842 while ((method = mono_class_get_methods (klass, &iter))) {
3844 if (method->slot != -1) {
3845 g_assert (method->slot < nslots);
3846 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3848 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3849 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3852 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3854 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3855 if (bflags & BFLAGS_Public)
3857 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3863 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3864 if (bflags & BFLAGS_Static)
3865 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3868 if (bflags & BFLAGS_Instance)
3876 if (compare_func (name, method->name))
3881 g_ptr_array_add (array, method);
3883 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3885 if (method_slots != method_slots_default)
3886 g_free (method_slots);
3891 if (method_slots != method_slots_default)
3892 g_free (method_slots);
3893 g_ptr_array_free (array, TRUE);
3895 g_assert (mono_class_has_failure (klass));
3896 mono_error_set_for_class_failure (error, klass);
3900 ICALL_EXPORT GPtrArray*
3901 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
3904 GPtrArray *method_array;
3907 klass = mono_class_from_mono_type (type->type);
3908 if (type->type->byref) {
3909 return g_ptr_array_new ();
3912 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
3913 mono_error_set_pending_exception (&error);
3914 return method_array;
3917 ICALL_EXPORT GPtrArray*
3918 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
3920 MonoClass *startklass, *klass;
3923 gpointer iter = NULL;
3924 GPtrArray *res_array;
3927 if (type->type->byref) {
3928 return g_ptr_array_new ();
3931 klass = startklass = mono_class_from_mono_type (type->type);
3933 mono_class_setup_methods (klass);
3934 if (mono_class_has_failure (klass)) {
3935 mono_error_init (&error);
3936 mono_error_set_for_class_failure (&error, klass);
3937 mono_error_set_pending_exception (&error);
3941 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
3944 while ((method = mono_class_get_methods (klass, &iter))) {
3946 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3948 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3949 if (bflags & BFLAGS_Public)
3952 if (bflags & BFLAGS_NonPublic)
3958 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3959 if (bflags & BFLAGS_Static)
3960 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3963 if (bflags & BFLAGS_Instance)
3969 g_ptr_array_add (res_array, method);
3976 property_hash (gconstpointer data)
3978 MonoProperty *prop = (MonoProperty*)data;
3980 return g_str_hash (prop->name);
3984 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
3986 if (method1->slot != -1 && method1->slot == method2->slot)
3989 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
3990 if (method1->is_inflated)
3991 method1 = ((MonoMethodInflated*) method1)->declaring;
3992 if (method2->is_inflated)
3993 method2 = ((MonoMethodInflated*) method2)->declaring;
3996 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4000 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4002 // Properties are hide-by-name-and-signature
4003 if (!g_str_equal (prop1->name, prop2->name))
4006 /* If we see a property in a generic method, we want to
4007 compare the generic signatures, not the inflated signatures
4008 because we might conflate two properties that were
4012 public T this[T t] { getter { return t; } } // method 1
4013 public U this[U u] { getter { return u; } } // method 2
4016 If we see int Foo<int,int>::Item[int] we need to know if
4017 the indexer came from method 1 or from method 2, and we
4018 shouldn't conflate them. (Bugzilla 36283)
4020 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4023 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4030 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4035 return method_nonpublic (accessor, start_klass);
4038 ICALL_EXPORT GPtrArray*
4039 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4042 MonoClass *startklass, *klass;
4047 int (*compare_func) (const char *s1, const char *s2) = NULL;
4049 GHashTable *properties = NULL;
4050 GPtrArray *res_array;
4052 if (type->type->byref) {
4053 return g_ptr_array_new ();
4056 mono_error_init (&error);
4058 klass = startklass = mono_class_from_mono_type (type->type);
4060 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4062 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4064 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4066 mono_class_setup_methods (klass);
4067 mono_class_setup_vtable (klass);
4068 if (mono_class_has_failure (klass)) {
4069 mono_error_set_for_class_failure (&error, klass);
4074 while ((prop = mono_class_get_properties (klass, &iter))) {
4080 flags = method->flags;
4083 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4084 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4085 if (bflags & BFLAGS_Public)
4087 } else if (bflags & BFLAGS_NonPublic) {
4088 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4089 property_accessor_nonpublic(prop->set, startklass == klass)) {
4096 if (flags & METHOD_ATTRIBUTE_STATIC) {
4097 if (bflags & BFLAGS_Static)
4098 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4101 if (bflags & BFLAGS_Instance)
4109 if (propname != NULL && compare_func (propname, prop->name))
4112 if (g_hash_table_lookup (properties, prop))
4115 g_ptr_array_add (res_array, prop);
4117 g_hash_table_insert (properties, prop, prop);
4119 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4122 g_hash_table_destroy (properties);
4129 g_hash_table_destroy (properties);
4130 g_ptr_array_free (res_array, TRUE);
4132 mono_error_set_pending_exception (&error);
4138 event_hash (gconstpointer data)
4140 MonoEvent *event = (MonoEvent*)data;
4142 return g_str_hash (event->name);
4146 event_equal (MonoEvent *event1, MonoEvent *event2)
4148 // Events are hide-by-name
4149 return g_str_equal (event1->name, event2->name);
4152 ICALL_EXPORT GPtrArray*
4153 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4156 MonoClass *startklass, *klass;
4161 int (*compare_func) (const char *s1, const char *s2) = NULL;
4162 GHashTable *events = NULL;
4163 GPtrArray *res_array;
4165 if (type->type->byref) {
4166 return g_ptr_array_new ();
4169 mono_error_init (&error);
4171 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4173 res_array = g_ptr_array_sized_new (4);
4175 klass = startklass = mono_class_from_mono_type (type->type);
4177 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4179 mono_class_setup_methods (klass);
4180 mono_class_setup_vtable (klass);
4181 if (mono_class_has_failure (klass)) {
4182 mono_error_set_for_class_failure (&error, klass);
4187 while ((event = mono_class_get_events (klass, &iter))) {
4189 method = event->add;
4191 method = event->remove;
4193 method = event->raise;
4195 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4196 if (bflags & BFLAGS_Public)
4198 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4199 if (bflags & BFLAGS_NonPublic)
4204 if (bflags & BFLAGS_NonPublic)
4210 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4211 if (bflags & BFLAGS_Static)
4212 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4215 if (bflags & BFLAGS_Instance)
4220 if (bflags & BFLAGS_Instance)
4225 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4228 if (g_hash_table_lookup (events, event))
4231 g_ptr_array_add (res_array, event);
4233 g_hash_table_insert (events, event, event);
4235 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4238 g_hash_table_destroy (events);
4244 g_hash_table_destroy (events);
4246 g_ptr_array_free (res_array, TRUE);
4248 mono_error_set_pending_exception (&error);
4252 ICALL_EXPORT GPtrArray *
4253 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4259 GPtrArray *res_array;
4261 if (type->type->byref) {
4262 return g_ptr_array_new ();
4265 klass = mono_class_from_mono_type (type->type);
4268 * If a nested type is generic, return its generic type definition.
4269 * Note that this means that the return value is essentially the set
4270 * of nested types of the generic type definition of @klass.
4272 * A note in MSDN claims that a generic type definition can have
4273 * nested types that aren't generic. In any case, the container of that
4274 * nested type would be the generic type definition.
4276 if (klass->generic_class)
4277 klass = klass->generic_class->container_class;
4279 res_array = g_ptr_array_new ();
4282 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4284 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4285 if (bflags & BFLAGS_Public)
4288 if (bflags & BFLAGS_NonPublic)
4294 if (str != NULL && strcmp (nested->name, str))
4297 g_ptr_array_add (res_array, &nested->byval_arg);
4303 ICALL_EXPORT MonoReflectionType*
4304 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4307 MonoReflectionType *ret;
4309 MonoType *type = NULL;
4310 MonoTypeNameParse info;
4311 gboolean type_resolve;
4313 /* On MS.NET, this does not fire a TypeResolve event */
4314 type_resolve = TRUE;
4315 str = mono_string_to_utf8_checked (name, &error);
4316 if (mono_error_set_pending_exception (&error))
4318 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4319 if (!mono_reflection_parse_type (str, &info)) {
4321 mono_reflection_free_type_info (&info);
4323 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4326 /*g_print ("failed parse\n");*/
4330 if (info.assembly.name) {
4332 mono_reflection_free_type_info (&info);
4334 /* 1.0 and 2.0 throw different exceptions */
4335 if (mono_defaults.generic_ilist_class)
4336 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4338 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4344 if (module != NULL) {
4345 if (module->image) {
4346 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4347 if (!is_ok (&error)) {
4349 mono_reflection_free_type_info (&info);
4350 mono_error_set_pending_exception (&error);
4357 if (assembly_is_dynamic (assembly->assembly)) {
4358 /* Enumerate all modules */
4359 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4363 if (abuilder->modules) {
4364 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4365 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4366 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4367 if (!is_ok (&error)) {
4369 mono_reflection_free_type_info (&info);
4370 mono_error_set_pending_exception (&error);
4378 if (!type && abuilder->loaded_modules) {
4379 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4380 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4381 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4382 if (!is_ok (&error)) {
4384 mono_reflection_free_type_info (&info);
4385 mono_error_set_pending_exception (&error);
4394 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4395 if (!is_ok (&error)) {
4397 mono_reflection_free_type_info (&info);
4398 mono_error_set_pending_exception (&error);
4403 mono_reflection_free_type_info (&info);
4405 MonoException *e = NULL;
4408 e = mono_get_exception_type_load (name, NULL);
4411 mono_set_pending_exception (e);
4415 if (type->type == MONO_TYPE_CLASS) {
4416 MonoClass *klass = mono_type_get_class (type);
4418 /* need to report exceptions ? */
4419 if (throwOnError && mono_class_has_failure (klass)) {
4420 /* report SecurityException (or others) that occured when loading the assembly */
4421 MonoException *exc = mono_class_get_exception_for_failure (klass);
4422 mono_set_pending_exception (exc);
4427 /* g_print ("got it\n"); */
4428 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4429 mono_error_set_pending_exception (&error);
4435 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4438 gchar *shadow_ini_file;
4441 /* Check for shadow-copied assembly */
4442 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4443 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4445 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4446 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4452 g_free (shadow_ini_file);
4453 if (content != NULL) {
4456 *filename = content;
4463 ICALL_EXPORT MonoString *
4464 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4466 MonoDomain *domain = mono_object_domain (assembly);
4467 MonoAssembly *mass = assembly->assembly;
4468 MonoString *res = NULL;
4473 if (g_path_is_absolute (mass->image->name)) {
4474 absolute = g_strdup (mass->image->name);
4475 dirname = g_path_get_dirname (absolute);
4477 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4478 dirname = g_strdup (mass->basedir);
4481 replace_shadow_path (domain, dirname, &absolute);
4486 for (i = strlen (absolute) - 1; i >= 0; i--)
4487 if (absolute [i] == '\\')
4492 uri = g_filename_to_uri (absolute, NULL, NULL);
4494 const char *prepend = "file://";
4496 if (*absolute == '/' && *(absolute + 1) == '/') {
4499 prepend = "file:///";
4502 uri = g_strconcat (prepend, absolute, NULL);
4506 res = mono_string_new (domain, uri);
4513 ICALL_EXPORT MonoBoolean
4514 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4516 MonoAssembly *mass = assembly->assembly;
4518 return mass->in_gac;
4521 ICALL_EXPORT MonoReflectionAssembly*
4522 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4527 MonoImageOpenStatus status;
4528 MonoReflectionAssembly* result = NULL;
4530 name = mono_string_to_utf8_checked (mname, &error);
4531 if (mono_error_set_pending_exception (&error))
4533 res = mono_assembly_load_with_partial_name (name, &status);
4539 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4541 mono_error_set_pending_exception (&error);
4545 ICALL_EXPORT MonoString *
4546 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4548 MonoDomain *domain = mono_object_domain (assembly);
4551 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4556 ICALL_EXPORT MonoBoolean
4557 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4559 return assembly->assembly->ref_only;
4562 ICALL_EXPORT MonoString *
4563 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4565 MonoDomain *domain = mono_object_domain (assembly);
4567 return mono_string_new (domain, assembly->assembly->image->version);
4570 ICALL_EXPORT MonoReflectionMethod*
4571 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4574 MonoReflectionMethod *res = NULL;
4577 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4581 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4582 if (!mono_error_ok (&error))
4585 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4588 if (!mono_error_ok (&error))
4589 mono_error_set_pending_exception (&error);
4593 ICALL_EXPORT MonoReflectionModule*
4594 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4597 MonoReflectionModule *result = NULL;
4598 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4599 if (!mono_error_ok (&error))
4600 mono_error_set_pending_exception (&error);
4604 ICALL_EXPORT MonoArray*
4605 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4608 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4609 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4610 if (mono_error_set_pending_exception (&error))
4615 for (i = 0; i < table->rows; ++i) {
4616 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4617 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4622 ICALL_EXPORT MonoString*
4623 ves_icall_System_Reflection_Assembly_GetAotId ()
4626 guint8 aotid_sum = 0;
4627 MonoDomain* domain = mono_domain_get ();
4629 if (!domain->entry_assembly || !domain->entry_assembly->image)
4632 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4634 for (i = 0; i < 16; ++i)
4635 aotid_sum |= (*aotid)[i];
4640 return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
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);
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 MonoString*
5707 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5709 MonoDomain *domain = mono_object_domain (module);
5711 g_assert (module->image);
5712 return mono_string_new (domain, module->image->guid);
5715 ICALL_EXPORT gpointer
5716 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5719 if (module->image && module->image->is_module_handle)
5720 return module->image->raw_data;
5723 return (gpointer) (-1);
5727 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5729 if (image_is_dynamic (image)) {
5730 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5731 *pe_kind = dyn->pe_kind;
5732 *machine = dyn->machine;
5735 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5736 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5741 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5743 return (image->md_version_major << 16) | (image->md_version_minor);
5746 ICALL_EXPORT MonoArray*
5747 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5750 MonoArray *exceptions;
5753 if (!module->image) {
5754 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5755 mono_error_set_pending_exception (&error);
5760 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5761 if (mono_error_set_pending_exception (&error))
5764 for (i = 0; i < mono_array_length (exceptions); ++i) {
5765 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5767 mono_set_pending_exception (ex);
5776 mono_memberref_is_method (MonoImage *image, guint32 token)
5778 if (!image_is_dynamic (image)) {
5779 guint32 cols [MONO_MEMBERREF_SIZE];
5781 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5782 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5783 mono_metadata_decode_blob_size (sig, &sig);
5784 return (*sig != 0x6);
5787 MonoClass *handle_class;
5789 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5790 mono_error_cleanup (&error); /* just probing, ignore error */
5794 return mono_defaults.methodhandle_class == handle_class;
5799 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5802 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5803 mono_array_addr (type_args, MonoType*, 0));
5805 context->class_inst = NULL;
5807 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5808 mono_array_addr (method_args, MonoType*, 0));
5810 context->method_inst = NULL;
5813 ICALL_EXPORT MonoType*
5814 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5817 int table = mono_metadata_token_table (token);
5818 int index = mono_metadata_token_index (token);
5819 MonoGenericContext context;
5822 *resolve_error = ResolveTokenError_Other;
5824 /* Validate token */
5825 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5826 (table != MONO_TABLE_TYPESPEC)) {
5827 *resolve_error = ResolveTokenError_BadTable;
5831 if (image_is_dynamic (image)) {
5832 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5833 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5834 mono_error_cleanup (&error);
5835 return klass ? &klass->byval_arg : NULL;
5838 init_generic_context_from_args (&context, type_args, method_args);
5839 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5840 mono_error_cleanup (&error);
5841 return klass ? &klass->byval_arg : NULL;
5844 if ((index <= 0) || (index > image->tables [table].rows)) {
5845 *resolve_error = ResolveTokenError_OutOfRange;
5849 init_generic_context_from_args (&context, type_args, method_args);
5850 klass = mono_class_get_checked (image, token, &error);
5852 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5853 if (!mono_error_ok (&error)) {
5854 mono_error_set_pending_exception (&error);
5859 return &klass->byval_arg;
5864 ICALL_EXPORT MonoMethod*
5865 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5868 int table = mono_metadata_token_table (token);
5869 int index = mono_metadata_token_index (token);
5870 MonoGenericContext context;
5873 *resolve_error = ResolveTokenError_Other;
5875 /* Validate token */
5876 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5877 (table != MONO_TABLE_MEMBERREF)) {
5878 *resolve_error = ResolveTokenError_BadTable;
5882 if (image_is_dynamic (image)) {
5883 if (table == MONO_TABLE_METHOD) {
5884 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5885 mono_error_cleanup (&error);
5889 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5890 *resolve_error = ResolveTokenError_BadTable;
5894 init_generic_context_from_args (&context, type_args, method_args);
5895 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5896 mono_error_cleanup (&error);
5900 if ((index <= 0) || (index > image->tables [table].rows)) {
5901 *resolve_error = ResolveTokenError_OutOfRange;
5904 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5905 *resolve_error = ResolveTokenError_BadTable;
5909 init_generic_context_from_args (&context, type_args, method_args);
5910 method = mono_get_method_checked (image, token, NULL, &context, &error);
5911 mono_error_set_pending_exception (&error);
5916 ICALL_EXPORT MonoString*
5917 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
5920 int index = mono_metadata_token_index (token);
5922 *resolve_error = ResolveTokenError_Other;
5924 /* Validate token */
5925 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5926 *resolve_error = ResolveTokenError_BadTable;
5930 if (image_is_dynamic (image)) {
5931 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5932 mono_error_cleanup (&error);
5936 if ((index <= 0) || (index >= image->heap_us.size)) {
5937 *resolve_error = ResolveTokenError_OutOfRange;
5941 /* FIXME: What to do if the index points into the middle of a string ? */
5943 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
5944 mono_error_set_pending_exception (&error);
5948 ICALL_EXPORT MonoClassField*
5949 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5953 int table = mono_metadata_token_table (token);
5954 int index = mono_metadata_token_index (token);
5955 MonoGenericContext context;
5956 MonoClassField *field;
5958 *resolve_error = ResolveTokenError_Other;
5960 /* Validate token */
5961 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5962 *resolve_error = ResolveTokenError_BadTable;
5966 if (image_is_dynamic (image)) {
5967 if (table == MONO_TABLE_FIELD) {
5968 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5969 mono_error_cleanup (&error);
5973 if (mono_memberref_is_method (image, token)) {
5974 *resolve_error = ResolveTokenError_BadTable;
5978 init_generic_context_from_args (&context, type_args, method_args);
5979 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5980 mono_error_cleanup (&error);
5984 if ((index <= 0) || (index > image->tables [table].rows)) {
5985 *resolve_error = ResolveTokenError_OutOfRange;
5988 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5989 *resolve_error = ResolveTokenError_BadTable;
5993 init_generic_context_from_args (&context, type_args, method_args);
5994 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5995 mono_error_set_pending_exception (&error);
6001 ICALL_EXPORT MonoObject*
6002 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6006 int table = mono_metadata_token_table (token);
6008 *error = ResolveTokenError_Other;
6011 case MONO_TABLE_TYPEDEF:
6012 case MONO_TABLE_TYPEREF:
6013 case MONO_TABLE_TYPESPEC: {
6014 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6016 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6017 mono_error_set_pending_exception (&merror);
6024 case MONO_TABLE_METHOD:
6025 case MONO_TABLE_METHODSPEC: {
6026 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6028 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6029 mono_error_set_pending_exception (&merror);
6035 case MONO_TABLE_FIELD: {
6036 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6038 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6039 mono_error_set_pending_exception (&merror);
6045 case MONO_TABLE_MEMBERREF:
6046 if (mono_memberref_is_method (image, token)) {
6047 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6049 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6050 mono_error_set_pending_exception (&merror);
6057 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6059 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6060 mono_error_set_pending_exception (&merror);
6069 *error = ResolveTokenError_BadTable;
6075 ICALL_EXPORT MonoArray*
6076 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6079 int table = mono_metadata_token_table (token);
6080 int idx = mono_metadata_token_index (token);
6081 MonoTableInfo *tables = image->tables;
6086 *resolve_error = ResolveTokenError_OutOfRange;
6088 /* FIXME: Support other tables ? */
6089 if (table != MONO_TABLE_STANDALONESIG)
6092 if (image_is_dynamic (image))
6095 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6098 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6100 ptr = mono_metadata_blob_heap (image, sig);
6101 len = mono_metadata_decode_blob_size (ptr, &ptr);
6103 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6104 if (mono_error_set_pending_exception (&error))
6106 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6110 ICALL_EXPORT MonoBoolean
6111 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6117 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6123 check_for_invalid_type (MonoClass *klass, MonoError *error)
6128 mono_error_init (error);
6130 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6133 name = mono_type_get_full_name (klass);
6134 str = mono_string_new (mono_domain_get (), name);
6136 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6139 ICALL_EXPORT MonoReflectionType *
6140 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6143 MonoReflectionType *ret;
6144 MonoClass *klass, *aklass;
6146 klass = mono_class_from_mono_type (type->type);
6147 check_for_invalid_type (klass, &error);
6148 mono_error_set_pending_exception (&error);
6150 if (rank == 0) //single dimentional array
6151 aklass = mono_array_class_get (klass, 1);
6153 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6155 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6156 mono_error_set_pending_exception (&error);
6161 ICALL_EXPORT MonoReflectionType *
6162 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6165 MonoReflectionType *ret;
6168 klass = mono_class_from_mono_type (type->type);
6169 mono_class_init_checked (klass, &error);
6170 if (mono_error_set_pending_exception (&error))
6173 check_for_invalid_type (klass, &error);
6174 if (mono_error_set_pending_exception (&error))
6177 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6178 mono_error_set_pending_exception (&error);
6183 ICALL_EXPORT MonoReflectionType *
6184 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6187 MonoReflectionType *ret;
6188 MonoClass *klass, *pklass;
6190 klass = mono_class_from_mono_type (type->type);
6191 mono_class_init_checked (klass, &error);
6192 if (mono_error_set_pending_exception (&error))
6194 check_for_invalid_type (klass, &error);
6195 if (mono_error_set_pending_exception (&error))
6198 pklass = mono_ptr_class_get (type->type);
6200 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6201 mono_error_set_pending_exception (&error);
6206 ICALL_EXPORT MonoObject *
6207 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6208 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6211 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6212 MonoObject *delegate;
6214 MonoMethod *method = info->method;
6215 MonoMethodSignature *sig = mono_method_signature(method);
6217 mono_class_init_checked (delegate_class, &error);
6218 if (mono_error_set_pending_exception (&error))
6221 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6222 /* FIXME improve this exception message */
6223 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6225 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6226 mono_error_set_pending_exception (&error);
6230 if (mono_security_core_clr_enabled ()) {
6231 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6232 if (throwOnBindFailure)
6233 mono_error_set_pending_exception (&error);
6235 mono_error_cleanup (&error);
6240 if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
6241 if (!method->is_inflated) {
6242 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"));
6247 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6248 if (mono_error_set_pending_exception (&error))
6251 if (method_is_dynamic (method)) {
6252 /* Creating a trampoline would leak memory */
6253 func = mono_compile_method_checked (method, &error);
6254 if (mono_error_set_pending_exception (&error))
6257 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6258 method = mono_object_get_virtual_method (target, method);
6259 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6260 if (mono_error_set_pending_exception (&error))
6262 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6265 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6266 if (mono_error_set_pending_exception (&error))
6271 ICALL_EXPORT MonoMulticastDelegate *
6272 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6275 MonoMulticastDelegate *ret;
6277 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6279 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6280 if (mono_error_set_pending_exception (&error))
6283 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6288 ICALL_EXPORT MonoReflectionMethod*
6289 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6291 MonoReflectionMethod *ret = NULL;
6293 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6294 mono_error_set_pending_exception (&error);
6300 static inline gint32
6301 mono_array_get_byte_length (MonoArray *array)
6307 klass = array->obj.vtable->klass;
6309 if (array->bounds == NULL)
6310 length = array->max_length;
6313 for (i = 0; i < klass->rank; ++ i)
6314 length *= array->bounds [i].length;
6317 switch (klass->element_class->byval_arg.type) {
6320 case MONO_TYPE_BOOLEAN:
6324 case MONO_TYPE_CHAR:
6332 return length * sizeof (gpointer);
6343 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6345 return mono_array_get_byte_length (array);
6349 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6351 return mono_array_get (array, gint8, idx);
6355 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6357 mono_array_set (array, gint8, idx, value);
6360 ICALL_EXPORT MonoBoolean
6361 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6363 guint8 *src_buf, *dest_buf;
6366 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6370 g_assert (count >= 0);
6372 /* This is called directly from the class libraries without going through the managed wrapper */
6373 MONO_CHECK_ARG_NULL (src, FALSE);
6374 MONO_CHECK_ARG_NULL (dest, FALSE);
6376 /* watch out for integer overflow */
6377 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6380 src_buf = (guint8 *)src->vector + src_offset;
6381 dest_buf = (guint8 *)dest->vector + dest_offset;
6384 memcpy (dest_buf, src_buf, count);
6386 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6391 #ifndef DISABLE_REMOTING
6392 ICALL_EXPORT MonoObject *
6393 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6396 MonoDomain *domain = mono_object_domain (this_obj);
6398 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6399 MonoTransparentProxy *tp;
6403 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6404 if (mono_error_set_pending_exception (&error))
6407 tp = (MonoTransparentProxy*) res;
6409 MONO_OBJECT_SETREF (tp, rp, rp);
6410 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6411 klass = mono_class_from_mono_type (type);
6413 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6414 mono_class_setup_vtable (klass);
6415 if (mono_class_has_failure (klass)) {
6416 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6420 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6421 if (mono_error_set_pending_exception (&error))
6423 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6424 if (mono_error_set_pending_exception (&error))
6427 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6428 if (mono_error_set_pending_exception (&error))
6433 ICALL_EXPORT MonoReflectionType *
6434 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6437 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6438 mono_error_set_pending_exception (&error);
6444 /* System.Environment */
6447 ves_icall_System_Environment_get_UserName (void)
6449 /* using glib is more portable */
6450 return mono_string_new (mono_domain_get (), g_get_user_name ());
6454 ICALL_EXPORT MonoString *
6455 ves_icall_System_Environment_get_MachineName (void)
6457 #if defined (HOST_WIN32)
6462 len = MAX_COMPUTERNAME_LENGTH + 1;
6463 buf = g_new (gunichar2, len);
6466 if (GetComputerName (buf, (PDWORD) &len)) {
6468 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6469 mono_error_set_pending_exception (&error);
6474 #elif !defined(DISABLE_SOCKETS)
6478 #if defined _SC_HOST_NAME_MAX
6479 n = sysconf (_SC_HOST_NAME_MAX);
6483 buf = g_malloc (n+1);
6485 if (gethostname (buf, n) == 0){
6487 result = mono_string_new (mono_domain_get (), buf);
6494 return mono_string_new (mono_domain_get (), "mono");
6499 ves_icall_System_Environment_get_Platform (void)
6501 #if defined (TARGET_WIN32)
6504 #elif defined(__MACH__)
6507 // Notice that the value is hidden from user code, and only exposed
6508 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6509 // define and making assumptions based on Unix/128/4 values before there
6510 // was a MacOS define. Lots of code would assume that not-Unix meant
6511 // Windows, but in this case, it would be OSX.
6520 ICALL_EXPORT MonoString *
6521 ves_icall_System_Environment_get_NewLine (void)
6523 #if defined (HOST_WIN32)
6524 return mono_string_new (mono_domain_get (), "\r\n");
6526 return mono_string_new (mono_domain_get (), "\n");
6530 ICALL_EXPORT MonoBoolean
6531 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6533 #if SIZEOF_VOID_P == 8
6537 gboolean isWow64Process = FALSE;
6538 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6539 return (MonoBoolean)isWow64Process;
6541 #elif defined(HAVE_SYS_UTSNAME_H)
6542 struct utsname name;
6544 if (uname (&name) >= 0) {
6545 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6552 ICALL_EXPORT MonoString *
6553 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6562 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6563 if (mono_error_set_pending_exception (&error))
6565 value = g_getenv (utf8_name);
6572 return mono_string_new (mono_domain_get (), value);
6576 * There is no standard way to get at environ.
6579 #ifndef __MINGW32_VERSION
6580 #if defined(__APPLE__)
6581 #if defined (TARGET_OSX)
6582 /* Apple defines this in crt_externs.h but doesn't provide that header for
6583 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6584 * in fact exist on all implementations (so far)
6586 gchar ***_NSGetEnviron(void);
6587 #define environ (*_NSGetEnviron())
6589 static char *mono_environ[1] = { NULL };
6590 #define environ mono_environ
6591 #endif /* defined (TARGET_OSX) */
6599 ICALL_EXPORT MonoArray *
6600 ves_icall_System_Environment_GetCoomandLineArgs (void)
6603 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6604 mono_error_set_pending_exception (&error);
6608 ICALL_EXPORT MonoArray *
6609 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6621 env_strings = GetEnvironmentStrings();
6624 env_string = env_strings;
6625 while (*env_string != '\0') {
6626 /* weird case that MS seems to skip */
6627 if (*env_string != '=')
6629 while (*env_string != '\0')
6635 domain = mono_domain_get ();
6636 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6637 if (mono_error_set_pending_exception (&error))
6642 env_string = env_strings;
6643 while (*env_string != '\0') {
6644 /* weird case that MS seems to skip */
6645 if (*env_string != '=') {
6646 equal_str = wcschr(env_string, '=');
6647 g_assert(equal_str);
6649 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6650 if (mono_error_set_pending_exception (&error))
6653 mono_array_setref (names, n, str);
6656 while (*env_string != '\0')
6661 FreeEnvironmentStrings (env_strings);
6675 for (e = environ; *e != 0; ++ e)
6678 domain = mono_domain_get ();
6679 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6680 if (mono_error_set_pending_exception (&error))
6684 for (e = environ; *e != 0; ++ e) {
6685 parts = g_strsplit (*e, "=", 2);
6687 str = mono_string_new (domain, *parts);
6688 mono_array_setref (names, n, str);
6701 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6704 gunichar2 *utf16_name, *utf16_value;
6706 gchar *utf8_name, *utf8_value;
6711 utf16_name = mono_string_to_utf16 (name);
6712 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6713 SetEnvironmentVariable (utf16_name, NULL);
6714 g_free (utf16_name);
6718 utf16_value = mono_string_to_utf16 (value);
6720 SetEnvironmentVariable (utf16_name, utf16_value);
6722 g_free (utf16_name);
6723 g_free (utf16_value);
6725 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6726 if (mono_error_set_pending_exception (&error))
6729 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6730 g_unsetenv (utf8_name);
6735 utf8_value = mono_string_to_utf8_checked (value, &error);
6736 if (!mono_error_ok (&error)) {
6738 mono_error_set_pending_exception (&error);
6741 g_setenv (utf8_name, utf8_value, TRUE);
6744 g_free (utf8_value);
6749 ves_icall_System_Environment_Exit (int result)
6751 mono_environment_exitcode_set (result);
6753 /* FIXME: There are some cleanup hangs that should be worked out, but
6754 * if the program is going to exit, everything will be cleaned up when
6755 * NaCl exits anyway.
6757 #ifndef __native_client__
6758 if (!mono_runtime_try_shutdown ())
6759 mono_thread_exit ();
6761 /* Suspend all managed threads since the runtime is going away */
6762 mono_thread_suspend_all_other_threads ();
6764 mono_runtime_quit ();
6767 /* we may need to do some cleanup here... */
6771 ICALL_EXPORT MonoString*
6772 ves_icall_System_Environment_GetGacPath (void)
6774 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6777 ICALL_EXPORT MonoString*
6778 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6780 #if defined (HOST_WIN32)
6781 #ifndef CSIDL_FLAG_CREATE
6782 #define CSIDL_FLAG_CREATE 0x8000
6785 WCHAR path [MAX_PATH];
6786 /* Create directory if no existing */
6787 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6792 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6793 mono_error_set_pending_exception (&error);
6797 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6799 return mono_string_new (mono_domain_get (), "");
6802 ICALL_EXPORT MonoArray *
6803 ves_icall_System_Environment_GetLogicalDrives (void)
6806 gunichar2 buf [256], *ptr, *dname;
6808 guint initial_size = 127, size = 128;
6811 MonoString *drivestr;
6812 MonoDomain *domain = mono_domain_get ();
6818 while (size > initial_size) {
6819 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6820 if (size > initial_size) {
6823 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6824 initial_size = size;
6838 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6839 if (mono_error_set_pending_exception (&error))
6846 while (*u16) { u16++; len ++; }
6847 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6848 if (mono_error_set_pending_exception (&error))
6851 mono_array_setref (result, ndrives++, drivestr);
6862 ICALL_EXPORT MonoString *
6863 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6866 gunichar2 volume_name [MAX_PATH + 1];
6868 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6870 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6871 mono_error_set_pending_exception (&error);
6875 ICALL_EXPORT MonoString *
6876 ves_icall_System_Environment_InternalGetHome (void)
6878 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6881 static const char *encodings [] = {
6883 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6884 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6885 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6887 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6888 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6889 "x_unicode_2_0_utf_7",
6891 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6892 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6894 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6897 "unicodefffe", "utf_16be",
6904 * Returns the internal codepage, if the value of "int_code_page" is
6905 * 1 at entry, and we can not compute a suitable code page number,
6906 * returns the code page as a string
6908 ICALL_EXPORT MonoString*
6909 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6914 char *codepage = NULL;
6916 int want_name = *int_code_page;
6919 *int_code_page = -1;
6921 g_get_charset (&cset);
6922 c = codepage = strdup (cset);
6923 for (c = codepage; *c; c++){
6924 if (isascii (*c) && isalpha (*c))
6929 /* g_print ("charset: %s\n", cset); */
6931 /* handle some common aliases */
6934 for (i = 0; p != 0; ){
6937 p = encodings [++i];
6940 if (strcmp (p, codepage) == 0){
6941 *int_code_page = code;
6944 p = encodings [++i];
6947 if (strstr (codepage, "utf_8") != NULL)
6948 *int_code_page |= 0x10000000;
6951 if (want_name && *int_code_page == -1)
6952 return mono_string_new (mono_domain_get (), cset);
6957 ICALL_EXPORT MonoBoolean
6958 ves_icall_System_Environment_get_HasShutdownStarted (void)
6960 if (mono_runtime_is_shutting_down ())
6963 if (mono_domain_is_unloading (mono_domain_get ()))
6970 ves_icall_System_Environment_BroadcastSettingChange (void)
6973 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6979 ves_icall_System_Environment_get_TickCount (void)
6981 /* this will overflow after ~24 days */
6982 return (gint32) (mono_msec_boottime () & 0xffffffff);
6986 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6991 #ifndef DISABLE_REMOTING
6992 ICALL_EXPORT MonoBoolean
6993 ves_icall_IsTransparentProxy (MonoObject *proxy)
6998 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7004 ICALL_EXPORT MonoReflectionMethod *
7005 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7006 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7008 MonoReflectionMethod *ret = NULL;
7013 MonoMethod **vtable;
7014 MonoMethod *res = NULL;
7016 MONO_CHECK_ARG_NULL (rtype, NULL);
7017 MONO_CHECK_ARG_NULL (rmethod, NULL);
7019 method = rmethod->method;
7020 klass = mono_class_from_mono_type (rtype->type);
7021 mono_class_init_checked (klass, &error);
7022 if (mono_error_set_pending_exception (&error))
7025 if (MONO_CLASS_IS_INTERFACE (klass))
7028 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7031 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7032 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7038 mono_class_setup_vtable (klass);
7039 vtable = klass->vtable;
7041 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7042 gboolean variance_used = FALSE;
7043 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7044 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7046 res = vtable [offs + method->slot];
7048 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7051 if (method->slot != -1)
7052 res = vtable [method->slot];
7058 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7059 mono_error_set_pending_exception (&error);
7064 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7070 klass = mono_class_from_mono_type (type->type);
7071 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7072 if (!is_ok (&error)) {
7073 mono_error_set_pending_exception (&error);
7077 mono_vtable_set_is_remote (vtable, enable);
7080 #else /* DISABLE_REMOTING */
7083 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7085 g_assert_not_reached ();
7090 ICALL_EXPORT MonoObject *
7091 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7098 domain = mono_object_domain (type);
7099 klass = mono_class_from_mono_type (type->type);
7100 mono_class_init_checked (klass, &error);
7101 if (mono_error_set_pending_exception (&error))
7104 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7105 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7109 if (klass->rank >= 1) {
7110 g_assert (klass->rank == 1);
7111 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7112 mono_error_set_pending_exception (&error);
7115 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7116 if (!is_ok (&error)) {
7117 mono_error_set_pending_exception (&error);
7120 /* Bypass remoting object creation check */
7121 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7122 mono_error_set_pending_exception (&error);
7128 ICALL_EXPORT MonoString *
7129 ves_icall_System_IO_get_temp_path (void)
7131 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7134 #ifndef PLATFORM_NO_DRIVEINFO
7135 ICALL_EXPORT MonoBoolean
7136 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7137 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7141 ULARGE_INTEGER wapi_free_bytes_avail;
7142 ULARGE_INTEGER wapi_total_number_of_bytes;
7143 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7145 *error = ERROR_SUCCESS;
7146 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7147 &wapi_total_number_of_free_bytes);
7150 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7151 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7152 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7154 *free_bytes_avail = 0;
7155 *total_number_of_bytes = 0;
7156 *total_number_of_free_bytes = 0;
7157 *error = GetLastError ();
7163 ICALL_EXPORT guint32
7164 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7166 return GetDriveType (mono_string_chars (root_path_name));
7170 ICALL_EXPORT gpointer
7171 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7174 gpointer result = mono_compile_method_checked (method, &error);
7175 mono_error_set_pending_exception (&error);
7179 ICALL_EXPORT MonoString *
7180 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7185 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7187 #if defined (HOST_WIN32)
7188 /* Avoid mixing '/' and '\\' */
7191 for (i = strlen (path) - 1; i >= 0; i--)
7192 if (path [i] == '/')
7196 mcpath = mono_string_new (mono_domain_get (), path);
7202 /* this is an icall */
7204 get_bundled_app_config (void)
7207 const gchar *app_config;
7210 gchar *config_file_name, *config_file_path;
7211 gsize len, config_file_path_length, config_ext_length;
7214 domain = mono_domain_get ();
7215 file = domain->setup->configuration_file;
7216 if (!file || file->length == 0)
7219 // Retrieve config file and remove the extension
7220 config_file_name = mono_string_to_utf8_checked (file, &error);
7221 if (mono_error_set_pending_exception (&error))
7223 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7224 if (!config_file_path)
7225 config_file_path = config_file_name;
7227 config_file_path_length = strlen (config_file_path);
7228 config_ext_length = strlen (".config");
7229 if (config_file_path_length <= config_ext_length)
7232 len = config_file_path_length - config_ext_length;
7233 module = (gchar *)g_malloc0 (len + 1);
7234 memcpy (module, config_file_path, len);
7235 // Get the config file from the module name
7236 app_config = mono_config_string_for_assembly_file (module);
7239 if (config_file_name != config_file_path)
7240 g_free (config_file_name);
7241 g_free (config_file_path);
7246 return mono_string_new (mono_domain_get (), app_config);
7250 get_bundled_machine_config (void)
7252 const gchar *machine_config;
7254 machine_config = mono_get_machine_config ();
7256 if (!machine_config)
7259 return mono_string_new (mono_domain_get (), machine_config);
7262 ICALL_EXPORT MonoString *
7263 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7268 path = g_path_get_dirname (mono_get_config_dir ());
7270 #if defined (HOST_WIN32)
7271 /* Avoid mixing '/' and '\\' */
7274 for (i = strlen (path) - 1; i >= 0; i--)
7275 if (path [i] == '/')
7279 ipath = mono_string_new (mono_domain_get (), path);
7285 ICALL_EXPORT gboolean
7286 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7288 MonoPEResourceDataEntry *entry;
7291 if (!assembly || !result || !size)
7296 image = assembly->assembly->image;
7297 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7301 *result = mono_image_rva_map (image, entry->rde_data_offset);
7306 *size = entry->rde_size;
7311 ICALL_EXPORT MonoBoolean
7312 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7314 return mono_is_debugger_attached ();
7317 ICALL_EXPORT MonoBoolean
7318 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7320 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7321 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7327 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7329 if (mono_get_runtime_callbacks ()->debug_log)
7330 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7334 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7336 #if defined (HOST_WIN32)
7337 OutputDebugString (mono_string_chars (message));
7339 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7343 /* Only used for value types */
7344 ICALL_EXPORT MonoObject *
7345 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7352 domain = mono_object_domain (type);
7353 klass = mono_class_from_mono_type (type->type);
7354 mono_class_init_checked (klass, &error);
7355 if (mono_error_set_pending_exception (&error))
7358 if (mono_class_is_nullable (klass))
7359 /* No arguments -> null */
7362 result = mono_object_new_checked (domain, klass, &error);
7363 mono_error_set_pending_exception (&error);
7367 ICALL_EXPORT MonoReflectionMethod *
7368 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7370 MonoReflectionMethod *ret = NULL;
7373 MonoClass *klass, *parent;
7374 MonoGenericContext *generic_inst = NULL;
7375 MonoMethod *method = m->method;
7376 MonoMethod *result = NULL;
7379 if (method->klass == NULL)
7382 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7383 MONO_CLASS_IS_INTERFACE (method->klass) ||
7384 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7387 slot = mono_method_get_vtable_slot (method);
7391 klass = method->klass;
7392 if (klass->generic_class) {
7393 generic_inst = mono_class_get_context (klass);
7394 klass = klass->generic_class->container_class;
7398 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7399 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7400 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7401 or klass is the generic container class and generic_inst is the instantiation.
7403 when we go to the parent, if the parent is an open constructed type, we need to
7404 replace the type parameters by the definitions from the generic_inst, and then take it
7405 apart again into the klass and the generic_inst.
7407 For cases like this:
7408 class C<T> : B<T, int> {
7409 public override void Foo () { ... }
7411 class B<U,V> : A<HashMap<U,V>> {
7412 public override void Foo () { ... }
7415 public virtual void Foo () { ... }
7418 if at each iteration the parent isn't open, we can skip inflating it. if at some
7419 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7422 MonoGenericContext *parent_inst = NULL;
7423 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7424 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7425 if (!mono_error_ok (&error)) {
7426 mono_error_set_pending_exception (&error);
7430 if (parent->generic_class) {
7431 parent_inst = mono_class_get_context (parent);
7432 parent = parent->generic_class->container_class;
7435 mono_class_setup_vtable (parent);
7436 if (parent->vtable_size <= slot)
7439 generic_inst = parent_inst;
7442 klass = klass->parent;
7445 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7446 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7447 if (!mono_error_ok (&error)) {
7448 mono_error_set_pending_exception (&error);
7452 generic_inst = NULL;
7454 if (klass->generic_class) {
7455 generic_inst = mono_class_get_context (klass);
7456 klass = klass->generic_class->container_class;
7462 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7463 if (!mono_error_ok (&error)) {
7464 mono_error_set_pending_exception (&error);
7469 if (klass == method->klass)
7472 /*This is possible if definition == FALSE.
7473 * Do it here to be really sure we don't read invalid memory.
7475 if (slot >= klass->vtable_size)
7478 mono_class_setup_vtable (klass);
7480 result = klass->vtable [slot];
7481 if (result == NULL) {
7482 /* It is an abstract method */
7483 gpointer iter = NULL;
7484 while ((result = mono_class_get_methods (klass, &iter)))
7485 if (result->slot == slot)
7492 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7493 mono_error_set_pending_exception (&error);
7497 ICALL_EXPORT MonoString*
7498 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7500 MonoMethod *method = m->method;
7502 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7507 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7509 iter->sig = *(MonoMethodSignature**)argsp;
7511 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7512 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7515 /* FIXME: it's not documented what start is exactly... */
7519 iter->args = argsp + sizeof (gpointer);
7521 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7523 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7526 ICALL_EXPORT MonoTypedRef
7527 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7529 guint32 i, arg_size;
7533 i = iter->sig->sentinelpos + iter->next_arg;
7535 g_assert (i < iter->sig->param_count);
7537 res.type = iter->sig->params [i];
7538 res.klass = mono_class_from_mono_type (res.type);
7539 arg_size = mono_type_stack_size (res.type, &align);
7540 #if defined(__arm__) || defined(__mips__)
7541 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7543 res.value = iter->args;
7544 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7545 /* Values are stored as 8 byte register sized objects, but 'value'
7546 * is dereferenced as a pointer in other routines.
7548 res.value = (char*)res.value + 4;
7550 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7551 if (arg_size <= sizeof (gpointer)) {
7553 int padding = arg_size - mono_type_size (res.type, &dummy);
7554 res.value = (guint8*)res.value + padding;
7557 iter->args = (char*)iter->args + arg_size;
7560 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7565 ICALL_EXPORT MonoTypedRef
7566 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7568 guint32 i, arg_size;
7572 i = iter->sig->sentinelpos + iter->next_arg;
7574 g_assert (i < iter->sig->param_count);
7576 while (i < iter->sig->param_count) {
7577 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7579 res.type = iter->sig->params [i];
7580 res.klass = mono_class_from_mono_type (res.type);
7581 /* FIXME: endianess issue... */
7582 arg_size = mono_type_stack_size (res.type, &align);
7583 #if defined(__arm__) || defined(__mips__)
7584 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7586 res.value = iter->args;
7587 iter->args = (char*)iter->args + arg_size;
7589 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7592 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7600 ICALL_EXPORT MonoType*
7601 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7605 i = iter->sig->sentinelpos + iter->next_arg;
7607 g_assert (i < iter->sig->param_count);
7609 return iter->sig->params [i];
7612 ICALL_EXPORT MonoObject*
7613 mono_TypedReference_ToObject (MonoTypedRef* tref)
7616 MonoObject *result = NULL;
7617 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7618 MonoObject** objp = (MonoObject **)tref->value;
7622 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7623 mono_error_set_pending_exception (&error);
7627 ICALL_EXPORT MonoTypedRef
7628 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7631 MonoReflectionField *f;
7633 MonoType *ftype = NULL;
7637 memset (&res, 0, sizeof (res));
7640 g_assert (mono_array_length (fields) > 0);
7642 klass = target->vtable->klass;
7644 for (i = 0; i < mono_array_length (fields); ++i) {
7645 f = mono_array_get (fields, MonoReflectionField*, i);
7647 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7650 if (f->field->parent != klass) {
7651 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7655 p = (guint8*)target + f->field->offset;
7657 p += f->field->offset - sizeof (MonoObject);
7658 klass = mono_class_from_mono_type (f->field->type);
7659 ftype = f->field->type;
7663 res.klass = mono_class_from_mono_type (ftype);
7670 prelink_method (MonoMethod *method, MonoError *error)
7672 const char *exc_class, *exc_arg;
7674 mono_error_init (error);
7675 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7677 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7679 mono_error_set_exception_instance (error,
7680 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7683 /* create the wrapper, too? */
7687 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7691 prelink_method (method->method, &error);
7692 mono_error_set_pending_exception (&error);
7696 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7699 MonoClass *klass = mono_class_from_mono_type (type->type);
7701 gpointer iter = NULL;
7703 mono_class_init_checked (klass, &error);
7704 if (mono_error_set_pending_exception (&error))
7707 while ((m = mono_class_get_methods (klass, &iter))) {
7708 prelink_method (m, &error);
7709 if (mono_error_set_pending_exception (&error))
7714 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7716 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7717 gint32 const **exponents,
7718 gunichar2 const **digitLowerTable,
7719 gunichar2 const **digitUpperTable,
7720 gint64 const **tenPowersList,
7721 gint32 const **decHexDigits)
7723 *mantissas = Formatter_MantissaBitsTable;
7724 *exponents = Formatter_TensExponentTable;
7725 *digitLowerTable = Formatter_DigitLowerTable;
7726 *digitUpperTable = Formatter_DigitUpperTable;
7727 *tenPowersList = Formatter_TenPowersList;
7728 *decHexDigits = Formatter_DecHexDigits;
7732 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7733 * and avoid useless allocations.
7736 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7738 MonoReflectionType *rt;
7742 mono_error_init (error);
7743 for (i = 0; i < type->num_mods; ++i) {
7744 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7749 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7750 return_val_if_nok (error, NULL);
7752 for (i = 0; i < type->num_mods; ++i) {
7753 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7754 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7755 return_val_if_nok (error, NULL);
7757 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7758 return_val_if_nok (error, NULL);
7760 mono_array_setref (res, count, rt);
7767 ICALL_EXPORT MonoArray*
7768 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7771 MonoType *type = param->ClassImpl->type;
7772 MonoClass *member_class = mono_object_class (param->MemberImpl);
7773 MonoMethod *method = NULL;
7776 MonoMethodSignature *sig;
7779 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7780 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7781 method = rmethod->method;
7782 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7783 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7784 if (!(method = prop->property->get))
7785 method = prop->property->set;
7788 char *type_name = mono_type_get_full_name (member_class);
7789 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7790 MonoException *ex = mono_get_exception_not_supported (msg);
7793 mono_set_pending_exception (ex);
7797 image = method->klass->image;
7798 pos = param->PositionImpl;
7799 sig = mono_method_signature (method);
7803 type = sig->params [pos];
7805 res = type_array_from_modifiers (image, type, optional, &error);
7806 mono_error_set_pending_exception (&error);
7811 get_property_type (MonoProperty *prop)
7813 MonoMethodSignature *sig;
7815 sig = mono_method_signature (prop->get);
7817 } else if (prop->set) {
7818 sig = mono_method_signature (prop->set);
7819 return sig->params [sig->param_count - 1];
7824 ICALL_EXPORT MonoArray*
7825 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7828 MonoType *type = get_property_type (property->property);
7829 MonoImage *image = property->klass->image;
7834 res = type_array_from_modifiers (image, type, optional, &error);
7835 mono_error_set_pending_exception (&error);
7840 *Construct a MonoType suited to be used to decode a constant blob object.
7842 * @type is the target type which will be constructed
7843 * @blob_type is the blob type, for example, that comes from the constant table
7844 * @real_type is the expected constructed type.
7847 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7849 type->type = blob_type;
7850 type->data.klass = NULL;
7851 if (blob_type == MONO_TYPE_CLASS)
7852 type->data.klass = mono_defaults.object_class;
7853 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7854 /* For enums, we need to use the base type */
7855 type->type = MONO_TYPE_VALUETYPE;
7856 type->data.klass = mono_class_from_mono_type (real_type);
7858 type->data.klass = mono_class_from_mono_type (real_type);
7861 ICALL_EXPORT MonoObject*
7862 property_info_get_default_value (MonoReflectionProperty *property)
7866 MonoProperty *prop = property->property;
7867 MonoType *type = get_property_type (prop);
7868 MonoDomain *domain = mono_object_domain (property);
7869 MonoTypeEnum def_type;
7870 const char *def_value;
7873 mono_class_init (prop->parent);
7875 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7876 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7880 def_value = mono_class_get_property_default_value (prop, &def_type);
7882 mono_type_from_blob_type (&blob_type, def_type, type);
7883 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7885 mono_error_set_pending_exception (&error);
7889 ICALL_EXPORT MonoBoolean
7890 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7893 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7894 MonoCustomAttrInfo *cinfo;
7897 mono_class_init_checked (attr_class, &error);
7898 if (mono_error_set_pending_exception (&error))
7901 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7902 if (!is_ok (&error)) {
7903 mono_error_set_pending_exception (&error);
7908 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7910 mono_custom_attrs_free (cinfo);
7914 ICALL_EXPORT MonoArray*
7915 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7917 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7922 mono_class_init_checked (attr_class, &error);
7923 if (mono_error_set_pending_exception (&error))
7927 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7928 if (!mono_error_ok (&error)) {
7929 mono_error_set_pending_exception (&error);
7936 ICALL_EXPORT MonoArray*
7937 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7941 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7942 mono_error_set_pending_exception (&error);
7947 ICALL_EXPORT MonoString*
7948 ves_icall_Mono_Runtime_GetDisplayName (void)
7951 MonoString *display_name;
7953 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7954 display_name = mono_string_new (mono_domain_get (), info);
7956 return display_name;
7959 ICALL_EXPORT MonoString*
7960 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7963 MonoString *message;
7967 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7968 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7971 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7973 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7974 if (mono_error_set_pending_exception (&error))
7981 ICALL_EXPORT gpointer
7982 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7984 return GetCurrentProcess ();
7987 ICALL_EXPORT MonoBoolean
7988 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7990 return GetExitCodeProcess (handle, (guint32*) exitcode);
7993 ICALL_EXPORT MonoBoolean
7994 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7996 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7997 return CloseHandle (handle);
7999 return CloseProcess (handle);
8003 ICALL_EXPORT MonoBoolean
8004 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8006 return TerminateProcess (handle, exitcode);
8010 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8013 return WaitForInputIdle (handle, milliseconds);
8015 /*TODO: Not implemented*/
8016 return WAIT_TIMEOUT;
8020 ICALL_EXPORT MonoBoolean
8021 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8023 return GetProcessWorkingSetSize (handle, min, max);
8026 ICALL_EXPORT MonoBoolean
8027 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8029 return SetProcessWorkingSetSize (handle, min, max);
8032 ICALL_EXPORT MonoBoolean
8033 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8035 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8039 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8041 return mono_process_current_pid ();
8045 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8047 return GetPriorityClass (handle);
8050 ICALL_EXPORT MonoBoolean
8051 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8053 return SetPriorityClass (handle, priorityClass);
8056 #ifndef DISABLE_ICALL_TABLES
8058 #define ICALL_TYPE(id,name,first)
8059 #define ICALL(id,name,func) Icall_ ## id,
8060 #define HANDLES(inner) inner
8063 #include "metadata/icall-def.h"
8069 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8070 #define ICALL(id,name,func)
8072 #define HANDLES(inner) inner
8074 #include "metadata/icall-def.h"
8080 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8081 #define ICALL(id,name,func)
8083 #define HANDLES(inner) inner
8085 guint16 first_icall;
8088 static const IcallTypeDesc
8089 icall_type_descs [] = {
8090 #include "metadata/icall-def.h"
8094 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8097 #define HANDLES(inner) inner
8099 #define ICALL_TYPE(id,name,first)
8102 #ifdef HAVE_ARRAY_ELEM_INIT
8103 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8104 #define MSGSTRFIELD1(line) str##line
8106 static const struct msgstrtn_t {
8107 #define ICALL(id,name,func)
8109 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8110 #include "metadata/icall-def.h"
8112 } icall_type_names_str = {
8113 #define ICALL_TYPE(id,name,first) (name),
8114 #include "metadata/icall-def.h"
8117 static const guint16 icall_type_names_idx [] = {
8118 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8119 #include "metadata/icall-def.h"
8122 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8124 static const struct msgstr_t {
8126 #define ICALL_TYPE(id,name,first)
8127 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8128 #include "metadata/icall-def.h"
8130 } icall_names_str = {
8131 #define ICALL(id,name,func) (name),
8132 #include "metadata/icall-def.h"
8135 static const guint16 icall_names_idx [] = {
8136 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8137 #include "metadata/icall-def.h"
8140 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8146 #define ICALL_TYPE(id,name,first) name,
8147 #define ICALL(id,name,func)
8148 static const char* const
8149 icall_type_names [] = {
8150 #include "metadata/icall-def.h"
8154 #define icall_type_name_get(id) (icall_type_names [(id)])
8158 #define ICALL_TYPE(id,name,first)
8159 #define ICALL(id,name,func) name,
8160 static const char* const
8162 #include "metadata/icall-def.h"
8165 #define icall_name_get(id) icall_names [(id)]
8167 #endif /* !HAVE_ARRAY_ELEM_INIT */
8170 #define HANDLES(inner) inner
8173 #define ICALL_TYPE(id,name,first)
8174 #define ICALL(id,name,func) func,
8175 static const gconstpointer
8176 icall_functions [] = {
8177 #include "metadata/icall-def.h"
8181 #ifdef ENABLE_ICALL_SYMBOL_MAP
8183 #define HANDLES(inner) inner
8186 #define ICALL_TYPE(id,name,first)
8187 #define ICALL(id,name,func) #func,
8188 static const gconstpointer
8189 icall_symbols [] = {
8190 #include "metadata/icall-def.h"
8197 #define ICALL_TYPE(id,name,first)
8198 #define ICALL(id,name,func) 0,
8200 #define HANDLES(inner) 1,
8202 icall_uses_handles [] = {
8203 #include "metadata/icall-def.h"
8208 #endif /* DISABLE_ICALL_TABLES */
8210 static mono_mutex_t icall_mutex;
8211 static GHashTable *icall_hash = NULL;
8212 static GHashTable *jit_icall_hash_name = NULL;
8213 static GHashTable *jit_icall_hash_addr = NULL;
8216 mono_icall_init (void)
8218 #ifndef DISABLE_ICALL_TABLES
8221 /* check that tables are sorted: disable in release */
8224 const char *prev_class = NULL;
8225 const char *prev_method;
8227 for (i = 0; i < Icall_type_num; ++i) {
8228 const IcallTypeDesc *desc;
8231 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8232 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8233 prev_class = icall_type_name_get (i);
8234 desc = &icall_type_descs [i];
8235 num_icalls = icall_desc_num_icalls (desc);
8236 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8237 for (j = 0; j < num_icalls; ++j) {
8238 const char *methodn = icall_name_get (desc->first_icall + j);
8239 if (prev_method && strcmp (prev_method, methodn) >= 0)
8240 g_print ("method %s should come before method %s\n", methodn, prev_method);
8241 prev_method = methodn;
8247 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8248 mono_os_mutex_init (&icall_mutex);
8252 mono_icall_lock (void)
8254 mono_locks_os_acquire (&icall_mutex, IcallLock);
8258 mono_icall_unlock (void)
8260 mono_locks_os_release (&icall_mutex, IcallLock);
8264 mono_icall_cleanup (void)
8266 g_hash_table_destroy (icall_hash);
8267 g_hash_table_destroy (jit_icall_hash_name);
8268 g_hash_table_destroy (jit_icall_hash_addr);
8269 mono_os_mutex_destroy (&icall_mutex);
8273 * mono_add_internal_call:
8274 * @name: method specification to surface to the managed world
8275 * @method: pointer to a C method to invoke when the method is called
8277 * This method surfaces the C function pointed by @method as a method
8278 * that has been surfaced in managed code with the method specified in
8279 * @name as an internal call.
8281 * Internal calls are surfaced to all app domains loaded and they are
8282 * accessibly by a type with the specified name.
8284 * You must provide a fully qualified type name, that is namespaces
8285 * and type name, followed by a colon and the method name, with an
8286 * optional signature to bind.
8288 * For example, the following are all valid declarations:
8290 * "MyApp.Services.ScriptService:Accelerate"
8291 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8293 * You use method parameters in cases where there might be more than
8294 * one surface method to managed code. That way you can register different
8295 * internal calls for different method overloads.
8297 * The internal calls are invoked with no marshalling. This means that .NET
8298 * types like System.String are exposed as `MonoString *` parameters. This is
8299 * different than the way that strings are surfaced in P/Invoke.
8301 * For more information on how the parameters are marshalled, see the
8302 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8305 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8306 * reference for more information on the format of method descriptions.
8309 mono_add_internal_call (const char *name, gconstpointer method)
8313 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8315 mono_icall_unlock ();
8318 #ifndef DISABLE_ICALL_TABLES
8320 #ifdef HAVE_ARRAY_ELEM_INIT
8322 compare_method_imap (const void *key, const void *elem)
8324 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8325 return strcmp (key, method_name);
8329 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8331 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);
8334 return (nameslot - &icall_names_idx [0]);
8338 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8340 gsize slotnum = find_slot_icall (imap, name);
8343 return (gboolean)icall_uses_handles [slotnum];
8347 find_method_icall (const IcallTypeDesc *imap, const char *name)
8349 gsize slotnum = find_slot_icall (imap, name);
8352 return (gpointer)icall_functions [slotnum];
8356 compare_class_imap (const void *key, const void *elem)
8358 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8359 return strcmp (key, class_name);
8362 static const IcallTypeDesc*
8363 find_class_icalls (const char *name)
8365 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);
8368 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8371 #else /* HAVE_ARRAY_ELEM_INIT */
8374 compare_method_imap (const void *key, const void *elem)
8376 const char** method_name = (const char**)elem;
8377 return strcmp (key, *method_name);
8381 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8383 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8386 return nameslot - icall_names;
8390 find_method_icall (const IcallTypeDesc *imap, const char *name)
8392 gsize slotnum = find_slot_icall (imap, name);
8395 return (gpointer)icall_functions [slotnum];
8399 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8401 gsize slotnum = find_slot_icall (imap, name);
8404 return (gboolean)icall_uses_handles [slotnum];
8408 compare_class_imap (const void *key, const void *elem)
8410 const char** class_name = (const char**)elem;
8411 return strcmp (key, *class_name);
8414 static const IcallTypeDesc*
8415 find_class_icalls (const char *name)
8417 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8420 return &icall_type_descs [nameslot - icall_type_names];
8423 #endif /* HAVE_ARRAY_ELEM_INIT */
8425 #endif /* DISABLE_ICALL_TABLES */
8428 * we should probably export this as an helper (handle nested types).
8429 * Returns the number of chars written in buf.
8432 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8434 int nspacelen, cnamelen;
8435 nspacelen = strlen (klass->name_space);
8436 cnamelen = strlen (klass->name);
8437 if (nspacelen + cnamelen + 2 > bufsize)
8440 memcpy (buf, klass->name_space, nspacelen);
8441 buf [nspacelen ++] = '.';
8443 memcpy (buf + nspacelen, klass->name, cnamelen);
8444 buf [nspacelen + cnamelen] = 0;
8445 return nspacelen + cnamelen;
8448 #ifdef DISABLE_ICALL_TABLES
8450 no_icall_table (void)
8452 g_assert_not_reached ();
8457 * mono_lookup_internal_call_full:
8458 * @method: the method to look up
8459 * @uses_handles: out argument if method needs handles around managed objects.
8461 * Returns a pointer to the icall code for the given method. If
8462 * uses_handles is not NULL, it will be set to TRUE if the method
8463 * needs managed objects wrapped using the infrastructure in handle.h
8465 * If the method is not found, warns and returns NULL.
8468 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8473 int typelen = 0, mlen, siglen;
8475 #ifndef DISABLE_ICALL_TABLES
8476 const IcallTypeDesc *imap = NULL;
8479 g_assert (method != NULL);
8481 if (method->is_inflated)
8482 method = ((MonoMethodInflated *) method)->declaring;
8484 if (method->klass->nested_in) {
8485 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8489 mname [pos++] = '/';
8492 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8498 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8503 #ifndef DISABLE_ICALL_TABLES
8504 imap = find_class_icalls (mname);
8507 mname [typelen] = ':';
8508 mname [typelen + 1] = ':';
8510 mlen = strlen (method->name);
8511 memcpy (mname + typelen + 2, method->name, mlen);
8512 sigstart = mname + typelen + 2 + mlen;
8515 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8516 siglen = strlen (tmpsig);
8517 if (typelen + mlen + siglen + 6 > sizeof (mname))
8520 memcpy (sigstart + 1, tmpsig, siglen);
8521 sigstart [siglen + 1] = ')';
8522 sigstart [siglen + 2] = 0;
8527 res = g_hash_table_lookup (icall_hash, mname);
8530 *uses_handles = FALSE;
8531 mono_icall_unlock ();;
8534 /* try without signature */
8536 res = g_hash_table_lookup (icall_hash, mname);
8539 *uses_handles = FALSE;
8540 mono_icall_unlock ();
8544 #ifdef DISABLE_ICALL_TABLES
8545 mono_icall_unlock ();
8546 /* Fail only when the result is actually used */
8547 /* mono_marshal_get_native_wrapper () depends on this */
8548 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8549 return ves_icall_System_String_ctor_RedirectToCreateString;
8551 return no_icall_table;
8553 /* it wasn't found in the static call tables */
8556 *uses_handles = FALSE;
8557 mono_icall_unlock ();
8560 res = find_method_icall (imap, sigstart - mlen);
8563 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8564 mono_icall_unlock ();
8567 /* try _with_ signature */
8569 res = find_method_icall (imap, sigstart - mlen);
8572 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8573 mono_icall_unlock ();
8577 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8578 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8579 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8580 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8581 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");
8582 g_print ("If you see other errors or faults after this message they are probably related\n");
8583 g_print ("and you need to fix your mono install first.\n");
8585 mono_icall_unlock ();
8592 mono_lookup_internal_call (MonoMethod *method)
8594 return mono_lookup_internal_call_full (method, NULL);
8597 #ifdef ENABLE_ICALL_SYMBOL_MAP
8599 func_cmp (gconstpointer key, gconstpointer p)
8601 return (gsize)key - (gsize)*(gsize*)p;
8606 * mono_lookup_icall_symbol:
8608 * Given the icall METHOD, returns its C symbol.
8611 mono_lookup_icall_symbol (MonoMethod *m)
8613 #ifdef DISABLE_ICALL_TABLES
8614 g_assert_not_reached ();
8617 #ifdef ENABLE_ICALL_SYMBOL_MAP
8621 static gconstpointer *functions_sorted;
8622 static const char**symbols_sorted;
8623 static gboolean inited;
8628 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8629 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8630 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8631 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8632 /* Bubble sort the two arrays */
8636 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8637 if (functions_sorted [i] > functions_sorted [i + 1]) {
8640 tmp = functions_sorted [i];
8641 functions_sorted [i] = functions_sorted [i + 1];
8642 functions_sorted [i + 1] = tmp;
8643 tmp = symbols_sorted [i];
8644 symbols_sorted [i] = symbols_sorted [i + 1];
8645 symbols_sorted [i + 1] = tmp;
8652 func = mono_lookup_internal_call (m);
8655 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8659 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8661 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8662 g_assert_not_reached ();
8669 type_from_typename (char *type_name)
8671 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8673 if (!strcmp (type_name, "int"))
8674 klass = mono_defaults.int_class;
8675 else if (!strcmp (type_name, "ptr"))
8676 klass = mono_defaults.int_class;
8677 else if (!strcmp (type_name, "void"))
8678 klass = mono_defaults.void_class;
8679 else if (!strcmp (type_name, "int32"))
8680 klass = mono_defaults.int32_class;
8681 else if (!strcmp (type_name, "uint32"))
8682 klass = mono_defaults.uint32_class;
8683 else if (!strcmp (type_name, "int8"))
8684 klass = mono_defaults.sbyte_class;
8685 else if (!strcmp (type_name, "uint8"))
8686 klass = mono_defaults.byte_class;
8687 else if (!strcmp (type_name, "int16"))
8688 klass = mono_defaults.int16_class;
8689 else if (!strcmp (type_name, "uint16"))
8690 klass = mono_defaults.uint16_class;
8691 else if (!strcmp (type_name, "long"))
8692 klass = mono_defaults.int64_class;
8693 else if (!strcmp (type_name, "ulong"))
8694 klass = mono_defaults.uint64_class;
8695 else if (!strcmp (type_name, "float"))
8696 klass = mono_defaults.single_class;
8697 else if (!strcmp (type_name, "double"))
8698 klass = mono_defaults.double_class;
8699 else if (!strcmp (type_name, "object"))
8700 klass = mono_defaults.object_class;
8701 else if (!strcmp (type_name, "obj"))
8702 klass = mono_defaults.object_class;
8703 else if (!strcmp (type_name, "string"))
8704 klass = mono_defaults.string_class;
8705 else if (!strcmp (type_name, "bool"))
8706 klass = mono_defaults.boolean_class;
8707 else if (!strcmp (type_name, "boolean"))
8708 klass = mono_defaults.boolean_class;
8710 g_error ("%s", type_name);
8711 g_assert_not_reached ();
8713 return &klass->byval_arg;
8717 * LOCKING: Take the corlib image lock.
8719 MonoMethodSignature*
8720 mono_create_icall_signature (const char *sigstr)
8725 MonoMethodSignature *res, *res2;
8726 MonoImage *corlib = mono_defaults.corlib;
8728 mono_image_lock (corlib);
8729 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8730 mono_image_unlock (corlib);
8735 parts = g_strsplit (sigstr, " ", 256);
8744 res = mono_metadata_signature_alloc (corlib, len - 1);
8749 * Under windows, the default pinvoke calling convention is STDCALL but
8752 res->call_convention = MONO_CALL_C;
8755 res->ret = type_from_typename (parts [0]);
8756 for (i = 1; i < len; ++i) {
8757 res->params [i - 1] = type_from_typename (parts [i]);
8762 mono_image_lock (corlib);
8763 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8765 res = res2; /*Value is allocated in the image pool*/
8767 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8768 mono_image_unlock (corlib);
8774 mono_find_jit_icall_by_name (const char *name)
8776 MonoJitICallInfo *info;
8777 g_assert (jit_icall_hash_name);
8780 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8781 mono_icall_unlock ();
8786 mono_find_jit_icall_by_addr (gconstpointer addr)
8788 MonoJitICallInfo *info;
8789 g_assert (jit_icall_hash_addr);
8792 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8793 mono_icall_unlock ();
8799 * mono_get_jit_icall_info:
8801 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8802 * caller should access it while holding the icall lock.
8805 mono_get_jit_icall_info (void)
8807 return jit_icall_hash_name;
8811 * mono_lookup_jit_icall_symbol:
8813 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8816 mono_lookup_jit_icall_symbol (const char *name)
8818 MonoJitICallInfo *info;
8819 const char *res = NULL;
8822 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8824 res = info->c_symbol;
8825 mono_icall_unlock ();
8830 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8833 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8834 mono_icall_unlock ();
8838 * 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
8839 * icalls without wrappers in some cases.
8842 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8844 MonoJitICallInfo *info;
8851 if (!jit_icall_hash_name) {
8852 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8853 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8856 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8857 g_warning ("jit icall already defined \"%s\"\n", name);
8858 g_assert_not_reached ();
8861 info = g_new0 (MonoJitICallInfo, 1);
8866 info->c_symbol = c_symbol;
8867 info->no_raise = no_raise;
8870 info->wrapper = func;
8872 info->wrapper = NULL;
8875 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8876 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8878 mono_icall_unlock ();
8883 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8885 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);