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;
6216 mono_class_init_checked (delegate_class, &error);
6217 if (mono_error_set_pending_exception (&error))
6220 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6221 /* FIXME improve this exception message */
6222 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6224 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6225 mono_error_set_pending_exception (&error);
6229 if (mono_security_core_clr_enabled ()) {
6230 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6231 if (throwOnBindFailure)
6232 mono_error_set_pending_exception (&error);
6234 mono_error_cleanup (&error);
6239 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6240 if (mono_error_set_pending_exception (&error))
6243 if (method_is_dynamic (method)) {
6244 /* Creating a trampoline would leak memory */
6245 func = mono_compile_method_checked (method, &error);
6246 if (mono_error_set_pending_exception (&error))
6249 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6250 method = mono_object_get_virtual_method (target, method);
6251 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6252 if (mono_error_set_pending_exception (&error))
6254 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6257 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6258 if (mono_error_set_pending_exception (&error))
6263 ICALL_EXPORT MonoMulticastDelegate *
6264 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6267 MonoMulticastDelegate *ret;
6269 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6271 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6272 if (mono_error_set_pending_exception (&error))
6275 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6280 ICALL_EXPORT MonoReflectionMethod*
6281 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6283 MonoReflectionMethod *ret = NULL;
6285 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6286 mono_error_set_pending_exception (&error);
6292 static inline gint32
6293 mono_array_get_byte_length (MonoArray *array)
6299 klass = array->obj.vtable->klass;
6301 if (array->bounds == NULL)
6302 length = array->max_length;
6305 for (i = 0; i < klass->rank; ++ i)
6306 length *= array->bounds [i].length;
6309 switch (klass->element_class->byval_arg.type) {
6312 case MONO_TYPE_BOOLEAN:
6316 case MONO_TYPE_CHAR:
6324 return length * sizeof (gpointer);
6335 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6337 return mono_array_get_byte_length (array);
6341 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6343 return mono_array_get (array, gint8, idx);
6347 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6349 mono_array_set (array, gint8, idx, value);
6352 ICALL_EXPORT MonoBoolean
6353 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6355 guint8 *src_buf, *dest_buf;
6358 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6362 g_assert (count >= 0);
6364 /* This is called directly from the class libraries without going through the managed wrapper */
6365 MONO_CHECK_ARG_NULL (src, FALSE);
6366 MONO_CHECK_ARG_NULL (dest, FALSE);
6368 /* watch out for integer overflow */
6369 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6372 src_buf = (guint8 *)src->vector + src_offset;
6373 dest_buf = (guint8 *)dest->vector + dest_offset;
6376 memcpy (dest_buf, src_buf, count);
6378 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6383 #ifndef DISABLE_REMOTING
6384 ICALL_EXPORT MonoObject *
6385 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6388 MonoDomain *domain = mono_object_domain (this_obj);
6390 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6391 MonoTransparentProxy *tp;
6395 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6396 if (mono_error_set_pending_exception (&error))
6399 tp = (MonoTransparentProxy*) res;
6401 MONO_OBJECT_SETREF (tp, rp, rp);
6402 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6403 klass = mono_class_from_mono_type (type);
6405 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6406 mono_class_setup_vtable (klass);
6407 if (mono_class_has_failure (klass)) {
6408 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6412 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6413 if (mono_error_set_pending_exception (&error))
6415 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6416 if (mono_error_set_pending_exception (&error))
6419 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6420 if (mono_error_set_pending_exception (&error))
6425 ICALL_EXPORT MonoReflectionType *
6426 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6429 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6430 mono_error_set_pending_exception (&error);
6436 /* System.Environment */
6439 ves_icall_System_Environment_get_UserName (void)
6441 /* using glib is more portable */
6442 return mono_string_new (mono_domain_get (), g_get_user_name ());
6446 ICALL_EXPORT MonoString *
6447 ves_icall_System_Environment_get_MachineName (void)
6449 #if defined (HOST_WIN32)
6454 len = MAX_COMPUTERNAME_LENGTH + 1;
6455 buf = g_new (gunichar2, len);
6458 if (GetComputerName (buf, (PDWORD) &len)) {
6460 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6461 mono_error_set_pending_exception (&error);
6466 #elif !defined(DISABLE_SOCKETS)
6470 #if defined _SC_HOST_NAME_MAX
6471 n = sysconf (_SC_HOST_NAME_MAX);
6475 buf = g_malloc (n+1);
6477 if (gethostname (buf, n) == 0){
6479 result = mono_string_new (mono_domain_get (), buf);
6486 return mono_string_new (mono_domain_get (), "mono");
6491 ves_icall_System_Environment_get_Platform (void)
6493 #if defined (TARGET_WIN32)
6496 #elif defined(__MACH__)
6499 // Notice that the value is hidden from user code, and only exposed
6500 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6501 // define and making assumptions based on Unix/128/4 values before there
6502 // was a MacOS define. Lots of code would assume that not-Unix meant
6503 // Windows, but in this case, it would be OSX.
6512 ICALL_EXPORT MonoString *
6513 ves_icall_System_Environment_get_NewLine (void)
6515 #if defined (HOST_WIN32)
6516 return mono_string_new (mono_domain_get (), "\r\n");
6518 return mono_string_new (mono_domain_get (), "\n");
6522 ICALL_EXPORT MonoBoolean
6523 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6525 #if SIZEOF_VOID_P == 8
6529 gboolean isWow64Process = FALSE;
6530 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6531 return (MonoBoolean)isWow64Process;
6533 #elif defined(HAVE_SYS_UTSNAME_H)
6534 struct utsname name;
6536 if (uname (&name) >= 0) {
6537 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6544 ICALL_EXPORT MonoString *
6545 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6554 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6555 if (mono_error_set_pending_exception (&error))
6557 value = g_getenv (utf8_name);
6564 return mono_string_new (mono_domain_get (), value);
6568 * There is no standard way to get at environ.
6571 #ifndef __MINGW32_VERSION
6572 #if defined(__APPLE__)
6573 #if defined (TARGET_OSX)
6574 /* Apple defines this in crt_externs.h but doesn't provide that header for
6575 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6576 * in fact exist on all implementations (so far)
6578 gchar ***_NSGetEnviron(void);
6579 #define environ (*_NSGetEnviron())
6581 static char *mono_environ[1] = { NULL };
6582 #define environ mono_environ
6583 #endif /* defined (TARGET_OSX) */
6591 ICALL_EXPORT MonoArray *
6592 ves_icall_System_Environment_GetCoomandLineArgs (void)
6595 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6596 mono_error_set_pending_exception (&error);
6600 ICALL_EXPORT MonoArray *
6601 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6613 env_strings = GetEnvironmentStrings();
6616 env_string = env_strings;
6617 while (*env_string != '\0') {
6618 /* weird case that MS seems to skip */
6619 if (*env_string != '=')
6621 while (*env_string != '\0')
6627 domain = mono_domain_get ();
6628 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6629 if (mono_error_set_pending_exception (&error))
6634 env_string = env_strings;
6635 while (*env_string != '\0') {
6636 /* weird case that MS seems to skip */
6637 if (*env_string != '=') {
6638 equal_str = wcschr(env_string, '=');
6639 g_assert(equal_str);
6641 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6642 if (mono_error_set_pending_exception (&error))
6645 mono_array_setref (names, n, str);
6648 while (*env_string != '\0')
6653 FreeEnvironmentStrings (env_strings);
6667 for (e = environ; *e != 0; ++ e)
6670 domain = mono_domain_get ();
6671 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6672 if (mono_error_set_pending_exception (&error))
6676 for (e = environ; *e != 0; ++ e) {
6677 parts = g_strsplit (*e, "=", 2);
6679 str = mono_string_new (domain, *parts);
6680 mono_array_setref (names, n, str);
6693 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6696 gunichar2 *utf16_name, *utf16_value;
6698 gchar *utf8_name, *utf8_value;
6703 utf16_name = mono_string_to_utf16 (name);
6704 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6705 SetEnvironmentVariable (utf16_name, NULL);
6706 g_free (utf16_name);
6710 utf16_value = mono_string_to_utf16 (value);
6712 SetEnvironmentVariable (utf16_name, utf16_value);
6714 g_free (utf16_name);
6715 g_free (utf16_value);
6717 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6718 if (mono_error_set_pending_exception (&error))
6721 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6722 g_unsetenv (utf8_name);
6727 utf8_value = mono_string_to_utf8_checked (value, &error);
6728 if (!mono_error_ok (&error)) {
6730 mono_error_set_pending_exception (&error);
6733 g_setenv (utf8_name, utf8_value, TRUE);
6736 g_free (utf8_value);
6741 ves_icall_System_Environment_Exit (int result)
6743 mono_environment_exitcode_set (result);
6745 /* FIXME: There are some cleanup hangs that should be worked out, but
6746 * if the program is going to exit, everything will be cleaned up when
6747 * NaCl exits anyway.
6749 #ifndef __native_client__
6750 if (!mono_runtime_try_shutdown ())
6751 mono_thread_exit ();
6753 /* Suspend all managed threads since the runtime is going away */
6754 mono_thread_suspend_all_other_threads ();
6756 mono_runtime_quit ();
6759 /* we may need to do some cleanup here... */
6763 ICALL_EXPORT MonoString*
6764 ves_icall_System_Environment_GetGacPath (void)
6766 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6769 ICALL_EXPORT MonoString*
6770 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6772 #if defined (HOST_WIN32)
6773 #ifndef CSIDL_FLAG_CREATE
6774 #define CSIDL_FLAG_CREATE 0x8000
6777 WCHAR path [MAX_PATH];
6778 /* Create directory if no existing */
6779 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6784 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6785 mono_error_set_pending_exception (&error);
6789 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6791 return mono_string_new (mono_domain_get (), "");
6794 ICALL_EXPORT MonoArray *
6795 ves_icall_System_Environment_GetLogicalDrives (void)
6798 gunichar2 buf [256], *ptr, *dname;
6800 guint initial_size = 127, size = 128;
6803 MonoString *drivestr;
6804 MonoDomain *domain = mono_domain_get ();
6810 while (size > initial_size) {
6811 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6812 if (size > initial_size) {
6815 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6816 initial_size = size;
6830 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
6831 if (mono_error_set_pending_exception (&error))
6838 while (*u16) { u16++; len ++; }
6839 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6840 if (mono_error_set_pending_exception (&error))
6843 mono_array_setref (result, ndrives++, drivestr);
6854 ICALL_EXPORT MonoString *
6855 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6858 gunichar2 volume_name [MAX_PATH + 1];
6860 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6862 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
6863 mono_error_set_pending_exception (&error);
6867 ICALL_EXPORT MonoString *
6868 ves_icall_System_Environment_InternalGetHome (void)
6870 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6873 static const char *encodings [] = {
6875 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6876 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6877 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6879 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6880 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6881 "x_unicode_2_0_utf_7",
6883 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6884 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6886 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6889 "unicodefffe", "utf_16be",
6896 * Returns the internal codepage, if the value of "int_code_page" is
6897 * 1 at entry, and we can not compute a suitable code page number,
6898 * returns the code page as a string
6900 ICALL_EXPORT MonoString*
6901 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6906 char *codepage = NULL;
6908 int want_name = *int_code_page;
6911 *int_code_page = -1;
6913 g_get_charset (&cset);
6914 c = codepage = strdup (cset);
6915 for (c = codepage; *c; c++){
6916 if (isascii (*c) && isalpha (*c))
6921 /* g_print ("charset: %s\n", cset); */
6923 /* handle some common aliases */
6926 for (i = 0; p != 0; ){
6929 p = encodings [++i];
6932 if (strcmp (p, codepage) == 0){
6933 *int_code_page = code;
6936 p = encodings [++i];
6939 if (strstr (codepage, "utf_8") != NULL)
6940 *int_code_page |= 0x10000000;
6943 if (want_name && *int_code_page == -1)
6944 return mono_string_new (mono_domain_get (), cset);
6949 ICALL_EXPORT MonoBoolean
6950 ves_icall_System_Environment_get_HasShutdownStarted (void)
6952 if (mono_runtime_is_shutting_down ())
6955 if (mono_domain_is_unloading (mono_domain_get ()))
6962 ves_icall_System_Environment_BroadcastSettingChange (void)
6965 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6971 ves_icall_System_Environment_get_TickCount (void)
6973 /* this will overflow after ~24 days */
6974 return (gint32) (mono_msec_boottime () & 0xffffffff);
6978 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6983 #ifndef DISABLE_REMOTING
6984 ICALL_EXPORT MonoBoolean
6985 ves_icall_IsTransparentProxy (MonoObject *proxy)
6990 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6996 ICALL_EXPORT MonoReflectionMethod *
6997 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6998 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7000 MonoReflectionMethod *ret = NULL;
7005 MonoMethod **vtable;
7006 MonoMethod *res = NULL;
7008 MONO_CHECK_ARG_NULL (rtype, NULL);
7009 MONO_CHECK_ARG_NULL (rmethod, NULL);
7011 method = rmethod->method;
7012 klass = mono_class_from_mono_type (rtype->type);
7013 mono_class_init_checked (klass, &error);
7014 if (mono_error_set_pending_exception (&error))
7017 if (MONO_CLASS_IS_INTERFACE (klass))
7020 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7023 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7024 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7030 mono_class_setup_vtable (klass);
7031 vtable = klass->vtable;
7033 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7034 gboolean variance_used = FALSE;
7035 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7036 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7038 res = vtable [offs + method->slot];
7040 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7043 if (method->slot != -1)
7044 res = vtable [method->slot];
7050 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7051 mono_error_set_pending_exception (&error);
7056 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7062 klass = mono_class_from_mono_type (type->type);
7063 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7064 if (!is_ok (&error)) {
7065 mono_error_set_pending_exception (&error);
7069 mono_vtable_set_is_remote (vtable, enable);
7072 #else /* DISABLE_REMOTING */
7075 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7077 g_assert_not_reached ();
7082 ICALL_EXPORT MonoObject *
7083 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7090 domain = mono_object_domain (type);
7091 klass = mono_class_from_mono_type (type->type);
7092 mono_class_init_checked (klass, &error);
7093 if (mono_error_set_pending_exception (&error))
7096 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7097 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7101 if (klass->rank >= 1) {
7102 g_assert (klass->rank == 1);
7103 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7104 mono_error_set_pending_exception (&error);
7107 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7108 if (!is_ok (&error)) {
7109 mono_error_set_pending_exception (&error);
7112 /* Bypass remoting object creation check */
7113 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7114 mono_error_set_pending_exception (&error);
7120 ICALL_EXPORT MonoString *
7121 ves_icall_System_IO_get_temp_path (void)
7123 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7126 #ifndef PLATFORM_NO_DRIVEINFO
7127 ICALL_EXPORT MonoBoolean
7128 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7129 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7133 ULARGE_INTEGER wapi_free_bytes_avail;
7134 ULARGE_INTEGER wapi_total_number_of_bytes;
7135 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7137 *error = ERROR_SUCCESS;
7138 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7139 &wapi_total_number_of_free_bytes);
7142 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7143 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7144 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7146 *free_bytes_avail = 0;
7147 *total_number_of_bytes = 0;
7148 *total_number_of_free_bytes = 0;
7149 *error = GetLastError ();
7155 ICALL_EXPORT guint32
7156 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7158 return GetDriveType (mono_string_chars (root_path_name));
7162 ICALL_EXPORT gpointer
7163 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7166 gpointer result = mono_compile_method_checked (method, &error);
7167 mono_error_set_pending_exception (&error);
7171 ICALL_EXPORT MonoString *
7172 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7177 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7179 #if defined (HOST_WIN32)
7180 /* Avoid mixing '/' and '\\' */
7183 for (i = strlen (path) - 1; i >= 0; i--)
7184 if (path [i] == '/')
7188 mcpath = mono_string_new (mono_domain_get (), path);
7194 /* this is an icall */
7196 get_bundled_app_config (void)
7199 const gchar *app_config;
7202 gchar *config_file_name, *config_file_path;
7203 gsize len, config_file_path_length, config_ext_length;
7206 domain = mono_domain_get ();
7207 file = domain->setup->configuration_file;
7208 if (!file || file->length == 0)
7211 // Retrieve config file and remove the extension
7212 config_file_name = mono_string_to_utf8_checked (file, &error);
7213 if (mono_error_set_pending_exception (&error))
7215 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7216 if (!config_file_path)
7217 config_file_path = config_file_name;
7219 config_file_path_length = strlen (config_file_path);
7220 config_ext_length = strlen (".config");
7221 if (config_file_path_length <= config_ext_length)
7224 len = config_file_path_length - config_ext_length;
7225 module = (gchar *)g_malloc0 (len + 1);
7226 memcpy (module, config_file_path, len);
7227 // Get the config file from the module name
7228 app_config = mono_config_string_for_assembly_file (module);
7231 if (config_file_name != config_file_path)
7232 g_free (config_file_name);
7233 g_free (config_file_path);
7238 return mono_string_new (mono_domain_get (), app_config);
7242 get_bundled_machine_config (void)
7244 const gchar *machine_config;
7246 machine_config = mono_get_machine_config ();
7248 if (!machine_config)
7251 return mono_string_new (mono_domain_get (), machine_config);
7254 ICALL_EXPORT MonoString *
7255 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7260 path = g_path_get_dirname (mono_get_config_dir ());
7262 #if defined (HOST_WIN32)
7263 /* Avoid mixing '/' and '\\' */
7266 for (i = strlen (path) - 1; i >= 0; i--)
7267 if (path [i] == '/')
7271 ipath = mono_string_new (mono_domain_get (), path);
7277 ICALL_EXPORT gboolean
7278 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7280 MonoPEResourceDataEntry *entry;
7283 if (!assembly || !result || !size)
7288 image = assembly->assembly->image;
7289 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7293 *result = mono_image_rva_map (image, entry->rde_data_offset);
7298 *size = entry->rde_size;
7303 ICALL_EXPORT MonoBoolean
7304 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7306 return mono_is_debugger_attached ();
7309 ICALL_EXPORT MonoBoolean
7310 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7312 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7313 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7319 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7321 if (mono_get_runtime_callbacks ()->debug_log)
7322 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7326 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7328 #if defined (HOST_WIN32)
7329 OutputDebugString (mono_string_chars (message));
7331 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7335 /* Only used for value types */
7336 ICALL_EXPORT MonoObject *
7337 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7344 domain = mono_object_domain (type);
7345 klass = mono_class_from_mono_type (type->type);
7346 mono_class_init_checked (klass, &error);
7347 if (mono_error_set_pending_exception (&error))
7350 if (mono_class_is_nullable (klass))
7351 /* No arguments -> null */
7354 result = mono_object_new_checked (domain, klass, &error);
7355 mono_error_set_pending_exception (&error);
7359 ICALL_EXPORT MonoReflectionMethod *
7360 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7362 MonoReflectionMethod *ret = NULL;
7365 MonoClass *klass, *parent;
7366 MonoGenericContext *generic_inst = NULL;
7367 MonoMethod *method = m->method;
7368 MonoMethod *result = NULL;
7371 if (method->klass == NULL)
7374 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7375 MONO_CLASS_IS_INTERFACE (method->klass) ||
7376 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7379 slot = mono_method_get_vtable_slot (method);
7383 klass = method->klass;
7384 if (klass->generic_class) {
7385 generic_inst = mono_class_get_context (klass);
7386 klass = klass->generic_class->container_class;
7390 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7391 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7392 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7393 or klass is the generic container class and generic_inst is the instantiation.
7395 when we go to the parent, if the parent is an open constructed type, we need to
7396 replace the type parameters by the definitions from the generic_inst, and then take it
7397 apart again into the klass and the generic_inst.
7399 For cases like this:
7400 class C<T> : B<T, int> {
7401 public override void Foo () { ... }
7403 class B<U,V> : A<HashMap<U,V>> {
7404 public override void Foo () { ... }
7407 public virtual void Foo () { ... }
7410 if at each iteration the parent isn't open, we can skip inflating it. if at some
7411 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7414 MonoGenericContext *parent_inst = NULL;
7415 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7416 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7417 if (!mono_error_ok (&error)) {
7418 mono_error_set_pending_exception (&error);
7422 if (parent->generic_class) {
7423 parent_inst = mono_class_get_context (parent);
7424 parent = parent->generic_class->container_class;
7427 mono_class_setup_vtable (parent);
7428 if (parent->vtable_size <= slot)
7431 generic_inst = parent_inst;
7434 klass = klass->parent;
7437 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7438 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7439 if (!mono_error_ok (&error)) {
7440 mono_error_set_pending_exception (&error);
7444 generic_inst = NULL;
7446 if (klass->generic_class) {
7447 generic_inst = mono_class_get_context (klass);
7448 klass = klass->generic_class->container_class;
7454 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7455 if (!mono_error_ok (&error)) {
7456 mono_error_set_pending_exception (&error);
7461 if (klass == method->klass)
7464 /*This is possible if definition == FALSE.
7465 * Do it here to be really sure we don't read invalid memory.
7467 if (slot >= klass->vtable_size)
7470 mono_class_setup_vtable (klass);
7472 result = klass->vtable [slot];
7473 if (result == NULL) {
7474 /* It is an abstract method */
7475 gpointer iter = NULL;
7476 while ((result = mono_class_get_methods (klass, &iter)))
7477 if (result->slot == slot)
7484 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7485 mono_error_set_pending_exception (&error);
7489 ICALL_EXPORT MonoString*
7490 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7492 MonoMethod *method = m->method;
7494 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7499 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7501 iter->sig = *(MonoMethodSignature**)argsp;
7503 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7504 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7507 /* FIXME: it's not documented what start is exactly... */
7511 iter->args = argsp + sizeof (gpointer);
7513 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7515 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7518 ICALL_EXPORT MonoTypedRef
7519 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7521 guint32 i, arg_size;
7525 i = iter->sig->sentinelpos + iter->next_arg;
7527 g_assert (i < iter->sig->param_count);
7529 res.type = iter->sig->params [i];
7530 res.klass = mono_class_from_mono_type (res.type);
7531 arg_size = mono_type_stack_size (res.type, &align);
7532 #if defined(__arm__) || defined(__mips__)
7533 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7535 res.value = iter->args;
7536 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7537 /* Values are stored as 8 byte register sized objects, but 'value'
7538 * is dereferenced as a pointer in other routines.
7540 res.value = (char*)res.value + 4;
7542 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7543 if (arg_size <= sizeof (gpointer)) {
7545 int padding = arg_size - mono_type_size (res.type, &dummy);
7546 res.value = (guint8*)res.value + padding;
7549 iter->args = (char*)iter->args + arg_size;
7552 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7557 ICALL_EXPORT MonoTypedRef
7558 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7560 guint32 i, arg_size;
7564 i = iter->sig->sentinelpos + iter->next_arg;
7566 g_assert (i < iter->sig->param_count);
7568 while (i < iter->sig->param_count) {
7569 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7571 res.type = iter->sig->params [i];
7572 res.klass = mono_class_from_mono_type (res.type);
7573 /* FIXME: endianess issue... */
7574 arg_size = mono_type_stack_size (res.type, &align);
7575 #if defined(__arm__) || defined(__mips__)
7576 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7578 res.value = iter->args;
7579 iter->args = (char*)iter->args + arg_size;
7581 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7584 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7592 ICALL_EXPORT MonoType*
7593 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7597 i = iter->sig->sentinelpos + iter->next_arg;
7599 g_assert (i < iter->sig->param_count);
7601 return iter->sig->params [i];
7604 ICALL_EXPORT MonoObject*
7605 mono_TypedReference_ToObject (MonoTypedRef* tref)
7608 MonoObject *result = NULL;
7609 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7610 MonoObject** objp = (MonoObject **)tref->value;
7614 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7615 mono_error_set_pending_exception (&error);
7619 ICALL_EXPORT MonoTypedRef
7620 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7623 MonoReflectionField *f;
7625 MonoType *ftype = NULL;
7629 memset (&res, 0, sizeof (res));
7632 g_assert (mono_array_length (fields) > 0);
7634 klass = target->vtable->klass;
7636 for (i = 0; i < mono_array_length (fields); ++i) {
7637 f = mono_array_get (fields, MonoReflectionField*, i);
7639 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7642 if (f->field->parent != klass) {
7643 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7647 p = (guint8*)target + f->field->offset;
7649 p += f->field->offset - sizeof (MonoObject);
7650 klass = mono_class_from_mono_type (f->field->type);
7651 ftype = f->field->type;
7655 res.klass = mono_class_from_mono_type (ftype);
7662 prelink_method (MonoMethod *method, MonoError *error)
7664 const char *exc_class, *exc_arg;
7666 mono_error_init (error);
7667 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7669 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7671 mono_error_set_exception_instance (error,
7672 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7675 /* create the wrapper, too? */
7679 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7683 prelink_method (method->method, &error);
7684 mono_error_set_pending_exception (&error);
7688 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7691 MonoClass *klass = mono_class_from_mono_type (type->type);
7693 gpointer iter = NULL;
7695 mono_class_init_checked (klass, &error);
7696 if (mono_error_set_pending_exception (&error))
7699 while ((m = mono_class_get_methods (klass, &iter))) {
7700 prelink_method (m, &error);
7701 if (mono_error_set_pending_exception (&error))
7706 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7708 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7709 gint32 const **exponents,
7710 gunichar2 const **digitLowerTable,
7711 gunichar2 const **digitUpperTable,
7712 gint64 const **tenPowersList,
7713 gint32 const **decHexDigits)
7715 *mantissas = Formatter_MantissaBitsTable;
7716 *exponents = Formatter_TensExponentTable;
7717 *digitLowerTable = Formatter_DigitLowerTable;
7718 *digitUpperTable = Formatter_DigitUpperTable;
7719 *tenPowersList = Formatter_TenPowersList;
7720 *decHexDigits = Formatter_DecHexDigits;
7724 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7725 * and avoid useless allocations.
7728 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7730 MonoReflectionType *rt;
7734 mono_error_init (error);
7735 for (i = 0; i < type->num_mods; ++i) {
7736 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7741 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7742 return_val_if_nok (error, NULL);
7744 for (i = 0; i < type->num_mods; ++i) {
7745 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7746 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7747 return_val_if_nok (error, NULL);
7749 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7750 return_val_if_nok (error, NULL);
7752 mono_array_setref (res, count, rt);
7759 ICALL_EXPORT MonoArray*
7760 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7763 MonoType *type = param->ClassImpl->type;
7764 MonoClass *member_class = mono_object_class (param->MemberImpl);
7765 MonoMethod *method = NULL;
7768 MonoMethodSignature *sig;
7771 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7772 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7773 method = rmethod->method;
7774 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7775 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7776 if (!(method = prop->property->get))
7777 method = prop->property->set;
7780 char *type_name = mono_type_get_full_name (member_class);
7781 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7782 MonoException *ex = mono_get_exception_not_supported (msg);
7785 mono_set_pending_exception (ex);
7789 image = method->klass->image;
7790 pos = param->PositionImpl;
7791 sig = mono_method_signature (method);
7795 type = sig->params [pos];
7797 res = type_array_from_modifiers (image, type, optional, &error);
7798 mono_error_set_pending_exception (&error);
7803 get_property_type (MonoProperty *prop)
7805 MonoMethodSignature *sig;
7807 sig = mono_method_signature (prop->get);
7809 } else if (prop->set) {
7810 sig = mono_method_signature (prop->set);
7811 return sig->params [sig->param_count - 1];
7816 ICALL_EXPORT MonoArray*
7817 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7820 MonoType *type = get_property_type (property->property);
7821 MonoImage *image = property->klass->image;
7826 res = type_array_from_modifiers (image, type, optional, &error);
7827 mono_error_set_pending_exception (&error);
7832 *Construct a MonoType suited to be used to decode a constant blob object.
7834 * @type is the target type which will be constructed
7835 * @blob_type is the blob type, for example, that comes from the constant table
7836 * @real_type is the expected constructed type.
7839 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7841 type->type = blob_type;
7842 type->data.klass = NULL;
7843 if (blob_type == MONO_TYPE_CLASS)
7844 type->data.klass = mono_defaults.object_class;
7845 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7846 /* For enums, we need to use the base type */
7847 type->type = MONO_TYPE_VALUETYPE;
7848 type->data.klass = mono_class_from_mono_type (real_type);
7850 type->data.klass = mono_class_from_mono_type (real_type);
7853 ICALL_EXPORT MonoObject*
7854 property_info_get_default_value (MonoReflectionProperty *property)
7858 MonoProperty *prop = property->property;
7859 MonoType *type = get_property_type (prop);
7860 MonoDomain *domain = mono_object_domain (property);
7861 MonoTypeEnum def_type;
7862 const char *def_value;
7865 mono_class_init (prop->parent);
7867 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7868 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7872 def_value = mono_class_get_property_default_value (prop, &def_type);
7874 mono_type_from_blob_type (&blob_type, def_type, type);
7875 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7877 mono_error_set_pending_exception (&error);
7881 ICALL_EXPORT MonoBoolean
7882 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7885 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7886 MonoCustomAttrInfo *cinfo;
7889 mono_class_init_checked (attr_class, &error);
7890 if (mono_error_set_pending_exception (&error))
7893 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7894 if (!is_ok (&error)) {
7895 mono_error_set_pending_exception (&error);
7900 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7902 mono_custom_attrs_free (cinfo);
7906 ICALL_EXPORT MonoArray*
7907 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7909 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7914 mono_class_init_checked (attr_class, &error);
7915 if (mono_error_set_pending_exception (&error))
7919 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7920 if (!mono_error_ok (&error)) {
7921 mono_error_set_pending_exception (&error);
7928 ICALL_EXPORT MonoArray*
7929 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7933 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7934 mono_error_set_pending_exception (&error);
7939 ICALL_EXPORT MonoString*
7940 ves_icall_Mono_Runtime_GetDisplayName (void)
7943 MonoString *display_name;
7945 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7946 display_name = mono_string_new (mono_domain_get (), info);
7948 return display_name;
7951 ICALL_EXPORT MonoString*
7952 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7955 MonoString *message;
7959 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7960 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7963 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7965 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7966 if (mono_error_set_pending_exception (&error))
7973 ICALL_EXPORT gpointer
7974 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7976 return GetCurrentProcess ();
7979 ICALL_EXPORT MonoBoolean
7980 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7982 return GetExitCodeProcess (handle, (guint32*) exitcode);
7985 ICALL_EXPORT MonoBoolean
7986 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7988 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7989 return CloseHandle (handle);
7991 return CloseProcess (handle);
7995 ICALL_EXPORT MonoBoolean
7996 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7998 return TerminateProcess (handle, exitcode);
8002 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8005 return WaitForInputIdle (handle, milliseconds);
8007 /*TODO: Not implemented*/
8008 return WAIT_TIMEOUT;
8012 ICALL_EXPORT MonoBoolean
8013 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8015 return GetProcessWorkingSetSize (handle, min, max);
8018 ICALL_EXPORT MonoBoolean
8019 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8021 return SetProcessWorkingSetSize (handle, min, max);
8024 ICALL_EXPORT MonoBoolean
8025 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8027 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8031 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8033 return mono_process_current_pid ();
8037 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8039 return GetPriorityClass (handle);
8042 ICALL_EXPORT MonoBoolean
8043 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8045 return SetPriorityClass (handle, priorityClass);
8048 #ifndef DISABLE_ICALL_TABLES
8050 #define ICALL_TYPE(id,name,first)
8051 #define ICALL(id,name,func) Icall_ ## id,
8052 #define HANDLES(inner) inner
8055 #include "metadata/icall-def.h"
8061 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8062 #define ICALL(id,name,func)
8064 #define HANDLES(inner) inner
8066 #include "metadata/icall-def.h"
8072 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8073 #define ICALL(id,name,func)
8075 #define HANDLES(inner) inner
8077 guint16 first_icall;
8080 static const IcallTypeDesc
8081 icall_type_descs [] = {
8082 #include "metadata/icall-def.h"
8086 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8089 #define HANDLES(inner) inner
8091 #define ICALL_TYPE(id,name,first)
8094 #ifdef HAVE_ARRAY_ELEM_INIT
8095 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8096 #define MSGSTRFIELD1(line) str##line
8098 static const struct msgstrtn_t {
8099 #define ICALL(id,name,func)
8101 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8102 #include "metadata/icall-def.h"
8104 } icall_type_names_str = {
8105 #define ICALL_TYPE(id,name,first) (name),
8106 #include "metadata/icall-def.h"
8109 static const guint16 icall_type_names_idx [] = {
8110 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8111 #include "metadata/icall-def.h"
8114 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8116 static const struct msgstr_t {
8118 #define ICALL_TYPE(id,name,first)
8119 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8120 #include "metadata/icall-def.h"
8122 } icall_names_str = {
8123 #define ICALL(id,name,func) (name),
8124 #include "metadata/icall-def.h"
8127 static const guint16 icall_names_idx [] = {
8128 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8129 #include "metadata/icall-def.h"
8132 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8138 #define ICALL_TYPE(id,name,first) name,
8139 #define ICALL(id,name,func)
8140 static const char* const
8141 icall_type_names [] = {
8142 #include "metadata/icall-def.h"
8146 #define icall_type_name_get(id) (icall_type_names [(id)])
8150 #define ICALL_TYPE(id,name,first)
8151 #define ICALL(id,name,func) name,
8152 static const char* const
8154 #include "metadata/icall-def.h"
8157 #define icall_name_get(id) icall_names [(id)]
8159 #endif /* !HAVE_ARRAY_ELEM_INIT */
8162 #define HANDLES(inner) inner
8165 #define ICALL_TYPE(id,name,first)
8166 #define ICALL(id,name,func) func,
8167 static const gconstpointer
8168 icall_functions [] = {
8169 #include "metadata/icall-def.h"
8173 #ifdef ENABLE_ICALL_SYMBOL_MAP
8175 #define HANDLES(inner) inner
8178 #define ICALL_TYPE(id,name,first)
8179 #define ICALL(id,name,func) #func,
8180 static const gconstpointer
8181 icall_symbols [] = {
8182 #include "metadata/icall-def.h"
8189 #define ICALL_TYPE(id,name,first)
8190 #define ICALL(id,name,func) 0,
8192 #define HANDLES(inner) 1,
8194 icall_uses_handles [] = {
8195 #include "metadata/icall-def.h"
8200 #endif /* DISABLE_ICALL_TABLES */
8202 static mono_mutex_t icall_mutex;
8203 static GHashTable *icall_hash = NULL;
8204 static GHashTable *jit_icall_hash_name = NULL;
8205 static GHashTable *jit_icall_hash_addr = NULL;
8208 mono_icall_init (void)
8210 #ifndef DISABLE_ICALL_TABLES
8213 /* check that tables are sorted: disable in release */
8216 const char *prev_class = NULL;
8217 const char *prev_method;
8219 for (i = 0; i < Icall_type_num; ++i) {
8220 const IcallTypeDesc *desc;
8223 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8224 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8225 prev_class = icall_type_name_get (i);
8226 desc = &icall_type_descs [i];
8227 num_icalls = icall_desc_num_icalls (desc);
8228 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8229 for (j = 0; j < num_icalls; ++j) {
8230 const char *methodn = icall_name_get (desc->first_icall + j);
8231 if (prev_method && strcmp (prev_method, methodn) >= 0)
8232 g_print ("method %s should come before method %s\n", methodn, prev_method);
8233 prev_method = methodn;
8239 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8240 mono_os_mutex_init (&icall_mutex);
8244 mono_icall_lock (void)
8246 mono_locks_os_acquire (&icall_mutex, IcallLock);
8250 mono_icall_unlock (void)
8252 mono_locks_os_release (&icall_mutex, IcallLock);
8256 mono_icall_cleanup (void)
8258 g_hash_table_destroy (icall_hash);
8259 g_hash_table_destroy (jit_icall_hash_name);
8260 g_hash_table_destroy (jit_icall_hash_addr);
8261 mono_os_mutex_destroy (&icall_mutex);
8265 * mono_add_internal_call:
8266 * @name: method specification to surface to the managed world
8267 * @method: pointer to a C method to invoke when the method is called
8269 * This method surfaces the C function pointed by @method as a method
8270 * that has been surfaced in managed code with the method specified in
8271 * @name as an internal call.
8273 * Internal calls are surfaced to all app domains loaded and they are
8274 * accessibly by a type with the specified name.
8276 * You must provide a fully qualified type name, that is namespaces
8277 * and type name, followed by a colon and the method name, with an
8278 * optional signature to bind.
8280 * For example, the following are all valid declarations:
8282 * "MyApp.Services.ScriptService:Accelerate"
8283 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8285 * You use method parameters in cases where there might be more than
8286 * one surface method to managed code. That way you can register different
8287 * internal calls for different method overloads.
8289 * The internal calls are invoked with no marshalling. This means that .NET
8290 * types like System.String are exposed as `MonoString *` parameters. This is
8291 * different than the way that strings are surfaced in P/Invoke.
8293 * For more information on how the parameters are marshalled, see the
8294 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8297 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8298 * reference for more information on the format of method descriptions.
8301 mono_add_internal_call (const char *name, gconstpointer method)
8305 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8307 mono_icall_unlock ();
8310 #ifndef DISABLE_ICALL_TABLES
8312 #ifdef HAVE_ARRAY_ELEM_INIT
8314 compare_method_imap (const void *key, const void *elem)
8316 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8317 return strcmp (key, method_name);
8321 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8323 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);
8326 return (nameslot - &icall_names_idx [0]);
8330 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8332 gsize slotnum = find_slot_icall (imap, name);
8335 return (gboolean)icall_uses_handles [slotnum];
8339 find_method_icall (const IcallTypeDesc *imap, const char *name)
8341 gsize slotnum = find_slot_icall (imap, name);
8344 return (gpointer)icall_functions [slotnum];
8348 compare_class_imap (const void *key, const void *elem)
8350 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8351 return strcmp (key, class_name);
8354 static const IcallTypeDesc*
8355 find_class_icalls (const char *name)
8357 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);
8360 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8363 #else /* HAVE_ARRAY_ELEM_INIT */
8366 compare_method_imap (const void *key, const void *elem)
8368 const char** method_name = (const char**)elem;
8369 return strcmp (key, *method_name);
8373 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8375 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8378 return nameslot - icall_names;
8382 find_method_icall (const IcallTypeDesc *imap, const char *name)
8384 gsize slotnum = find_slot_icall (imap, name);
8387 return (gpointer)icall_functions [slotnum];
8391 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8393 gsize slotnum = find_slot_icall (imap, name);
8396 return (gboolean)icall_uses_handles [slotnum];
8400 compare_class_imap (const void *key, const void *elem)
8402 const char** class_name = (const char**)elem;
8403 return strcmp (key, *class_name);
8406 static const IcallTypeDesc*
8407 find_class_icalls (const char *name)
8409 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8412 return &icall_type_descs [nameslot - icall_type_names];
8415 #endif /* HAVE_ARRAY_ELEM_INIT */
8417 #endif /* DISABLE_ICALL_TABLES */
8420 * we should probably export this as an helper (handle nested types).
8421 * Returns the number of chars written in buf.
8424 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8426 int nspacelen, cnamelen;
8427 nspacelen = strlen (klass->name_space);
8428 cnamelen = strlen (klass->name);
8429 if (nspacelen + cnamelen + 2 > bufsize)
8432 memcpy (buf, klass->name_space, nspacelen);
8433 buf [nspacelen ++] = '.';
8435 memcpy (buf + nspacelen, klass->name, cnamelen);
8436 buf [nspacelen + cnamelen] = 0;
8437 return nspacelen + cnamelen;
8440 #ifdef DISABLE_ICALL_TABLES
8442 no_icall_table (void)
8444 g_assert_not_reached ();
8449 * mono_lookup_internal_call_full:
8450 * @method: the method to look up
8451 * @uses_handles: out argument if method needs handles around managed objects.
8453 * Returns a pointer to the icall code for the given method. If
8454 * uses_handles is not NULL, it will be set to TRUE if the method
8455 * needs managed objects wrapped using the infrastructure in handle.h
8457 * If the method is not found, warns and returns NULL.
8460 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8465 int typelen = 0, mlen, siglen;
8467 #ifndef DISABLE_ICALL_TABLES
8468 const IcallTypeDesc *imap = NULL;
8471 g_assert (method != NULL);
8473 if (method->is_inflated)
8474 method = ((MonoMethodInflated *) method)->declaring;
8476 if (method->klass->nested_in) {
8477 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8481 mname [pos++] = '/';
8484 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8490 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8495 #ifndef DISABLE_ICALL_TABLES
8496 imap = find_class_icalls (mname);
8499 mname [typelen] = ':';
8500 mname [typelen + 1] = ':';
8502 mlen = strlen (method->name);
8503 memcpy (mname + typelen + 2, method->name, mlen);
8504 sigstart = mname + typelen + 2 + mlen;
8507 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8508 siglen = strlen (tmpsig);
8509 if (typelen + mlen + siglen + 6 > sizeof (mname))
8512 memcpy (sigstart + 1, tmpsig, siglen);
8513 sigstart [siglen + 1] = ')';
8514 sigstart [siglen + 2] = 0;
8519 res = g_hash_table_lookup (icall_hash, mname);
8522 *uses_handles = FALSE;
8523 mono_icall_unlock ();;
8526 /* try without signature */
8528 res = g_hash_table_lookup (icall_hash, mname);
8531 *uses_handles = FALSE;
8532 mono_icall_unlock ();
8536 #ifdef DISABLE_ICALL_TABLES
8537 mono_icall_unlock ();
8538 /* Fail only when the result is actually used */
8539 /* mono_marshal_get_native_wrapper () depends on this */
8540 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8541 return ves_icall_System_String_ctor_RedirectToCreateString;
8543 return no_icall_table;
8545 /* it wasn't found in the static call tables */
8548 *uses_handles = FALSE;
8549 mono_icall_unlock ();
8552 res = find_method_icall (imap, sigstart - mlen);
8555 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8556 mono_icall_unlock ();
8559 /* try _with_ signature */
8561 res = find_method_icall (imap, sigstart - mlen);
8564 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8565 mono_icall_unlock ();
8569 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8570 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8571 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8572 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8573 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");
8574 g_print ("If you see other errors or faults after this message they are probably related\n");
8575 g_print ("and you need to fix your mono install first.\n");
8577 mono_icall_unlock ();
8584 mono_lookup_internal_call (MonoMethod *method)
8586 return mono_lookup_internal_call_full (method, NULL);
8589 #ifdef ENABLE_ICALL_SYMBOL_MAP
8591 func_cmp (gconstpointer key, gconstpointer p)
8593 return (gsize)key - (gsize)*(gsize*)p;
8598 * mono_lookup_icall_symbol:
8600 * Given the icall METHOD, returns its C symbol.
8603 mono_lookup_icall_symbol (MonoMethod *m)
8605 #ifdef DISABLE_ICALL_TABLES
8606 g_assert_not_reached ();
8609 #ifdef ENABLE_ICALL_SYMBOL_MAP
8613 static gconstpointer *functions_sorted;
8614 static const char**symbols_sorted;
8615 static gboolean inited;
8620 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8621 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8622 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8623 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8624 /* Bubble sort the two arrays */
8628 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8629 if (functions_sorted [i] > functions_sorted [i + 1]) {
8632 tmp = functions_sorted [i];
8633 functions_sorted [i] = functions_sorted [i + 1];
8634 functions_sorted [i + 1] = tmp;
8635 tmp = symbols_sorted [i];
8636 symbols_sorted [i] = symbols_sorted [i + 1];
8637 symbols_sorted [i + 1] = tmp;
8644 func = mono_lookup_internal_call (m);
8647 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8651 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8653 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8654 g_assert_not_reached ();
8661 type_from_typename (char *type_name)
8663 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8665 if (!strcmp (type_name, "int"))
8666 klass = mono_defaults.int_class;
8667 else if (!strcmp (type_name, "ptr"))
8668 klass = mono_defaults.int_class;
8669 else if (!strcmp (type_name, "void"))
8670 klass = mono_defaults.void_class;
8671 else if (!strcmp (type_name, "int32"))
8672 klass = mono_defaults.int32_class;
8673 else if (!strcmp (type_name, "uint32"))
8674 klass = mono_defaults.uint32_class;
8675 else if (!strcmp (type_name, "int8"))
8676 klass = mono_defaults.sbyte_class;
8677 else if (!strcmp (type_name, "uint8"))
8678 klass = mono_defaults.byte_class;
8679 else if (!strcmp (type_name, "int16"))
8680 klass = mono_defaults.int16_class;
8681 else if (!strcmp (type_name, "uint16"))
8682 klass = mono_defaults.uint16_class;
8683 else if (!strcmp (type_name, "long"))
8684 klass = mono_defaults.int64_class;
8685 else if (!strcmp (type_name, "ulong"))
8686 klass = mono_defaults.uint64_class;
8687 else if (!strcmp (type_name, "float"))
8688 klass = mono_defaults.single_class;
8689 else if (!strcmp (type_name, "double"))
8690 klass = mono_defaults.double_class;
8691 else if (!strcmp (type_name, "object"))
8692 klass = mono_defaults.object_class;
8693 else if (!strcmp (type_name, "obj"))
8694 klass = mono_defaults.object_class;
8695 else if (!strcmp (type_name, "string"))
8696 klass = mono_defaults.string_class;
8697 else if (!strcmp (type_name, "bool"))
8698 klass = mono_defaults.boolean_class;
8699 else if (!strcmp (type_name, "boolean"))
8700 klass = mono_defaults.boolean_class;
8702 g_error ("%s", type_name);
8703 g_assert_not_reached ();
8705 return &klass->byval_arg;
8709 * LOCKING: Take the corlib image lock.
8711 MonoMethodSignature*
8712 mono_create_icall_signature (const char *sigstr)
8717 MonoMethodSignature *res, *res2;
8718 MonoImage *corlib = mono_defaults.corlib;
8720 mono_image_lock (corlib);
8721 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8722 mono_image_unlock (corlib);
8727 parts = g_strsplit (sigstr, " ", 256);
8736 res = mono_metadata_signature_alloc (corlib, len - 1);
8741 * Under windows, the default pinvoke calling convention is STDCALL but
8744 res->call_convention = MONO_CALL_C;
8747 res->ret = type_from_typename (parts [0]);
8748 for (i = 1; i < len; ++i) {
8749 res->params [i - 1] = type_from_typename (parts [i]);
8754 mono_image_lock (corlib);
8755 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8757 res = res2; /*Value is allocated in the image pool*/
8759 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8760 mono_image_unlock (corlib);
8766 mono_find_jit_icall_by_name (const char *name)
8768 MonoJitICallInfo *info;
8769 g_assert (jit_icall_hash_name);
8772 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8773 mono_icall_unlock ();
8778 mono_find_jit_icall_by_addr (gconstpointer addr)
8780 MonoJitICallInfo *info;
8781 g_assert (jit_icall_hash_addr);
8784 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8785 mono_icall_unlock ();
8791 * mono_get_jit_icall_info:
8793 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8794 * caller should access it while holding the icall lock.
8797 mono_get_jit_icall_info (void)
8799 return jit_icall_hash_name;
8803 * mono_lookup_jit_icall_symbol:
8805 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8808 mono_lookup_jit_icall_symbol (const char *name)
8810 MonoJitICallInfo *info;
8811 const char *res = NULL;
8814 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8816 res = info->c_symbol;
8817 mono_icall_unlock ();
8822 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8825 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8826 mono_icall_unlock ();
8830 * 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
8831 * icalls without wrappers in some cases.
8834 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8836 MonoJitICallInfo *info;
8843 if (!jit_icall_hash_name) {
8844 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8845 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8848 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8849 g_warning ("jit icall already defined \"%s\"\n", name);
8850 g_assert_not_reached ();
8853 info = g_new0 (MonoJitICallInfo, 1);
8858 info->c_symbol = c_symbol;
8859 info->no_raise = no_raise;
8862 info->wrapper = func;
8864 info->wrapper = NULL;
8867 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8868 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8870 mono_icall_unlock ();
8875 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8877 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);