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 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1219 MONO_CHECK_ARG_NULL (obj, 0);
1222 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1223 mono_error_set_pending_exception (&error);
1228 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1229 MonoReflectionMethod *method,
1230 MonoArray *opt_param_types)
1232 MONO_CHECK_ARG_NULL (method, 0);
1235 gint32 result = mono_image_create_method_token (
1236 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1237 mono_error_set_pending_exception (&error);
1242 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1245 mono_image_create_pefile (mb, file, &error);
1246 mono_error_set_pending_exception (&error);
1250 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1253 mono_image_build_metadata (mb, &error);
1254 mono_error_set_pending_exception (&error);
1258 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1260 mono_image_register_token (mb->dynamic_image, token, obj);
1263 ICALL_EXPORT MonoObject*
1264 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1268 mono_loader_lock ();
1269 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1270 mono_loader_unlock ();
1275 ICALL_EXPORT MonoReflectionModule*
1276 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1279 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1280 mono_error_set_pending_exception (&error);
1285 * ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class:
1286 * @tb: a TypeBuilder object
1289 * Creates the generic class after all generic parameters have been added.
1292 ves_icall_System_Reflection_Emit_TypeBuilder_create_generic_class (MonoReflectionTypeBuilder *tb)
1295 (void) mono_reflection_create_generic_class (tb, &error);
1296 mono_error_set_pending_exception (&error);
1299 #ifndef DISABLE_REFLECTION_EMIT
1300 ICALL_EXPORT MonoArray*
1301 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1304 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1305 mono_error_set_pending_exception (&error);
1311 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1313 MonoMethod **dest = (MonoMethod **)data;
1315 /* skip unmanaged frames */
1320 if (!strcmp (m->klass->name_space, "System.Reflection"))
1329 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1331 MonoMethod **dest = (MonoMethod **)data;
1333 /* skip unmanaged frames */
1337 if (m->wrapper_type != MONO_WRAPPER_NONE)
1345 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1356 get_caller_no_system_or_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1358 MonoMethod **dest = (MonoMethod **)data;
1360 /* skip unmanaged frames */
1364 if (m->wrapper_type != MONO_WRAPPER_NONE)
1372 if (m->klass->image == mono_defaults.corlib && ((!strcmp (m->klass->name_space, "System.Reflection"))
1373 || (!strcmp (m->klass->name_space, "System"))))
1383 static MonoReflectionType *
1384 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1386 MonoMethod *m, *dest;
1388 MonoType *type = NULL;
1389 MonoAssembly *assembly = NULL;
1390 gboolean type_resolve = FALSE;
1391 MonoImage *rootimage = NULL;
1393 mono_error_init (error);
1396 * We must compute the calling assembly as type loading must happen under a metadata context.
1397 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1398 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1400 m = mono_method_get_last_managed ();
1402 if (m && m->klass->image != mono_defaults.corlib) {
1403 /* Happens with inlining */
1405 /* Ugly hack: type_from_parsed_name is called from
1406 * System.Type.internal_from_name, which is called most
1407 * directly from System.Type.GetType(string,bool,bool) but
1408 * also indirectly from places such as
1409 * System.Type.GetType(string,func,func) (via
1410 * System.TypeNameParser.GetType and System.TypeSpec.Resolve)
1411 * so we need to skip over all of those to find the true caller.
1413 * It would be nice if we had stack marks.
1415 mono_stack_walk_no_il (get_caller_no_system_or_reflection, &dest);
1421 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1422 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1423 * to crash. This only seems to happen in some strange remoting
1424 * scenarios and I was unable to figure out what's happening there.
1425 * Dec 10, 2005 - Martin.
1429 assembly = dest->klass->image->assembly;
1430 type_resolve = TRUE;
1431 rootimage = assembly->image;
1433 g_warning (G_STRLOC);
1436 if (info->assembly.name)
1437 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1440 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1441 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1442 return_val_if_nok (error, NULL);
1446 // Say we're looking for System.Generic.Dict<int, Local>
1447 // we FAIL the get type above, because S.G.Dict isn't in assembly->image. So we drop down here.
1448 // but then we FAIL AGAIN because now we pass null as the image and the rootimage and everything
1449 // is messed up when we go to construct the Local as the type arg...
1451 // By contrast, if we started with Mine<System.Generic.Dict<int, Local>> we'd go in with assembly->image
1452 // as the root and then even the detour into generics would still not screw us when we went to load Local.
1453 if (!info->assembly.name && !type) {
1455 type = mono_reflection_get_type_checked (rootimage, NULL, info, ignoreCase, &type_resolve, error);
1456 return_val_if_nok (error, NULL);
1458 if (assembly && !type && type_resolve) {
1459 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1460 type = mono_reflection_get_type_checked (rootimage, assembly->image, info, ignoreCase, &type_resolve, error);
1461 return_val_if_nok (error, NULL);
1467 return mono_type_get_object_checked (mono_domain_get (), type, error);
1470 ICALL_EXPORT MonoReflectionType*
1471 ves_icall_System_Type_internal_from_name (MonoString *name,
1472 MonoBoolean throwOnError,
1473 MonoBoolean ignoreCase)
1476 MonoTypeNameParse info;
1477 MonoReflectionType *type = NULL;
1480 char *str = mono_string_to_utf8_checked (name, &error);
1481 if (!is_ok (&error))
1484 parsedOk = mono_reflection_parse_type (str, &info);
1486 /* mono_reflection_parse_type() mangles the string */
1488 mono_reflection_free_type_info (&info);
1490 mono_error_set_argument (&error, "typeName", "failed parse: %s", str);
1494 type = type_from_parsed_name (&info, ignoreCase, &error);
1496 mono_reflection_free_type_info (&info);
1498 if (!is_ok (&error))
1503 mono_error_set_type_load_name (&error, g_strdup (str), NULL, "");
1510 if (!is_ok (&error)) {
1512 mono_error_set_pending_exception (&error);
1514 mono_error_cleanup (&error);
1522 ICALL_EXPORT MonoReflectionType*
1523 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1526 MonoReflectionType *ret;
1527 MonoDomain *domain = mono_domain_get ();
1529 ret = mono_type_get_object_checked (domain, handle, &error);
1530 mono_error_set_pending_exception (&error);
1535 ICALL_EXPORT MonoType*
1536 ves_icall_Mono_RuntimeClassHandle_GetTypeFromClass (MonoClass *klass)
1538 return mono_class_get_type (klass);
1542 ves_icall_Mono_RuntimeGPtrArrayHandle_GPtrArrayFree (GPtrArray *ptr_array)
1544 g_ptr_array_free (ptr_array, TRUE);
1548 ves_icall_Mono_SafeStringMarshal_GFree (void *c_str)
1554 ves_icall_Mono_SafeStringMarshal_StringToUtf8 (MonoString *s)
1557 char *res = mono_string_to_utf8_checked (s, &error);
1558 mono_error_set_pending_exception (&error);
1562 /* System.TypeCode */
1581 TYPECODE_STRING = 18
1584 ICALL_EXPORT guint32
1585 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1587 int t = type->type->type;
1589 if (type->type->byref)
1590 return TYPECODE_OBJECT;
1594 case MONO_TYPE_VOID:
1595 return TYPECODE_OBJECT;
1596 case MONO_TYPE_BOOLEAN:
1597 return TYPECODE_BOOLEAN;
1599 return TYPECODE_BYTE;
1601 return TYPECODE_SBYTE;
1603 return TYPECODE_UINT16;
1605 return TYPECODE_INT16;
1606 case MONO_TYPE_CHAR:
1607 return TYPECODE_CHAR;
1611 return TYPECODE_OBJECT;
1613 return TYPECODE_UINT32;
1615 return TYPECODE_INT32;
1617 return TYPECODE_UINT64;
1619 return TYPECODE_INT64;
1621 return TYPECODE_SINGLE;
1623 return TYPECODE_DOUBLE;
1624 case MONO_TYPE_VALUETYPE: {
1625 MonoClass *klass = type->type->data.klass;
1627 if (klass->enumtype) {
1628 t = mono_class_enum_basetype (klass)->type;
1630 } else if (mono_is_corlib_image (klass->image)) {
1631 if (strcmp (klass->name_space, "System") == 0) {
1632 if (strcmp (klass->name, "Decimal") == 0)
1633 return TYPECODE_DECIMAL;
1634 else if (strcmp (klass->name, "DateTime") == 0)
1635 return TYPECODE_DATETIME;
1638 return TYPECODE_OBJECT;
1640 case MONO_TYPE_STRING:
1641 return TYPECODE_STRING;
1642 case MONO_TYPE_SZARRAY:
1643 case MONO_TYPE_ARRAY:
1644 case MONO_TYPE_OBJECT:
1646 case MONO_TYPE_MVAR:
1647 case MONO_TYPE_TYPEDBYREF:
1648 return TYPECODE_OBJECT;
1649 case MONO_TYPE_CLASS:
1651 MonoClass *klass = type->type->data.klass;
1652 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1653 if (strcmp (klass->name, "DBNull") == 0)
1654 return TYPECODE_DBNULL;
1657 return TYPECODE_OBJECT;
1658 case MONO_TYPE_GENERICINST:
1659 return TYPECODE_OBJECT;
1661 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1667 mono_type_is_primitive (MonoType *type)
1669 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1670 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1674 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1676 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1677 return mono_class_enum_basetype (type->data.klass);
1678 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1679 return mono_class_enum_basetype (type->data.generic_class->container_class);
1683 ICALL_EXPORT guint32
1684 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1689 g_assert (type != NULL);
1691 klass = mono_class_from_mono_type (type->type);
1692 klassc = mono_class_from_mono_type (c->type);
1694 if (type->type->byref ^ c->type->byref)
1697 if (type->type->byref) {
1698 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1699 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1701 klass = mono_class_from_mono_type (t);
1702 klassc = mono_class_from_mono_type (ot);
1704 if (mono_type_is_primitive (t)) {
1705 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1706 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1707 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1708 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1709 return t->type == ot->type;
1711 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1714 if (klass->valuetype)
1715 return klass == klassc;
1716 return klass->valuetype == klassc->valuetype;
1719 return mono_class_is_assignable_from (klass, klassc);
1722 ICALL_EXPORT guint32
1723 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1726 MonoClass *klass = mono_class_from_mono_type (type->type);
1727 mono_class_init_checked (klass, &error);
1728 if (!is_ok (&error)) {
1729 mono_error_set_pending_exception (&error);
1732 guint32 result = (mono_object_isinst_checked (obj, klass, &error) != NULL);
1733 mono_error_set_pending_exception (&error);
1737 ICALL_EXPORT guint32
1738 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1740 MonoClass *klass = mono_class_from_mono_type (type->type);
1741 return klass->flags;
1744 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1745 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1748 MonoClass *klass = field->field->parent;
1749 MonoMarshalType *info;
1753 if (klass->generic_container ||
1754 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1757 ftype = mono_field_get_type (field->field);
1758 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1761 info = mono_marshal_load_type_info (klass);
1763 for (i = 0; i < info->num_fields; ++i) {
1764 if (info->fields [i].field == field->field) {
1765 if (!info->fields [i].mspec)
1768 MonoReflectionMarshalAsAttribute* obj;
1769 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1770 if (!mono_error_ok (&error))
1771 mono_error_set_pending_exception (&error);
1780 ICALL_EXPORT MonoReflectionField*
1781 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1784 gboolean found = FALSE;
1790 klass = handle->parent;
1792 klass = mono_class_from_mono_type (type);
1794 found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1797 /* The managed code will throw the exception */
1801 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1802 mono_error_set_pending_exception (&error);
1806 ICALL_EXPORT MonoReflectionEvent*
1807 ves_icall_System_Reflection_EventInfo_internal_from_handle_type (MonoEvent *handle, MonoType *type)
1815 klass = handle->parent;
1817 klass = mono_class_from_mono_type (type);
1819 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1821 /* Managed code will throw an exception */
1825 MonoReflectionEvent *result = mono_event_get_object_checked (mono_domain_get (), klass, handle, &error);
1826 mono_error_set_pending_exception (&error);
1831 ICALL_EXPORT MonoReflectionProperty*
1832 ves_icall_System_Reflection_PropertyInfo_internal_from_handle_type (MonoProperty *handle, MonoType *type)
1840 klass = handle->parent;
1842 klass = mono_class_from_mono_type (type);
1844 gboolean found = klass == handle->parent || mono_class_has_parent (klass, handle->parent);
1846 /* Managed code will throw an exception */
1850 MonoReflectionProperty *result = mono_property_get_object_checked (mono_domain_get (), klass, handle, &error);
1851 mono_error_set_pending_exception (&error);
1855 ICALL_EXPORT MonoArray*
1856 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1859 MonoType *type = mono_field_get_type_checked (field->field, &error);
1862 if (!mono_error_ok (&error)) {
1863 mono_error_set_pending_exception (&error);
1867 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1868 mono_error_set_pending_exception (&error);
1873 vell_icall_get_method_attributes (MonoMethod *method)
1875 return method->flags;
1879 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1882 MonoReflectionType *rt;
1883 MonoDomain *domain = mono_domain_get ();
1884 MonoMethodSignature* sig;
1886 sig = mono_method_signature_checked (method, &error);
1887 if (!mono_error_ok (&error)) {
1888 mono_error_set_pending_exception (&error);
1892 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1893 if (!mono_error_ok (&error)) {
1894 mono_error_set_pending_exception (&error);
1898 MONO_STRUCT_SETREF (info, parent, rt);
1900 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1901 if (!mono_error_ok (&error)) {
1902 mono_error_set_pending_exception (&error);
1906 MONO_STRUCT_SETREF (info, ret, rt);
1908 info->attrs = method->flags;
1909 info->implattrs = method->iflags;
1910 if (sig->call_convention == MONO_CALL_DEFAULT)
1911 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1913 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1918 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1921 ICALL_EXPORT MonoArray*
1922 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1925 MonoDomain *domain = mono_domain_get ();
1927 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1928 mono_error_set_pending_exception (&error);
1932 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1933 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1936 MonoDomain *domain = mono_domain_get ();
1937 MonoReflectionMarshalAsAttribute* res = NULL;
1938 MonoMarshalSpec **mspecs;
1941 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1942 mono_method_get_marshal_info (method, mspecs);
1945 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1946 if (!mono_error_ok (&error)) {
1947 mono_error_set_pending_exception (&error);
1952 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1954 mono_metadata_free_marshal_spec (mspecs [i]);
1961 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1963 MonoClass *parent = field->field->parent;
1964 if (!parent->size_inited)
1965 mono_class_init (parent);
1966 mono_class_setup_fields_locking (parent);
1968 return field->field->offset - sizeof (MonoObject);
1971 ICALL_EXPORT MonoReflectionType*
1972 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1975 MonoReflectionType *ret;
1978 parent = declaring? field->field->parent: field->klass;
1980 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1981 mono_error_set_pending_exception (&error);
1987 ICALL_EXPORT MonoObject *
1988 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1991 MonoClass *fklass = field->klass;
1992 MonoClassField *cf = field->field;
1993 MonoDomain *domain = mono_object_domain (field);
1995 if (fklass->image->assembly->ref_only) {
1996 mono_set_pending_exception (mono_get_exception_invalid_operation (
1997 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
2001 if (mono_security_core_clr_enabled () &&
2002 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
2003 mono_error_set_pending_exception (&error);
2007 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
2008 mono_error_set_pending_exception (&error);
2013 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
2016 MonoClassField *cf = field->field;
2020 if (field->klass->image->assembly->ref_only) {
2021 mono_set_pending_exception (mono_get_exception_invalid_operation (
2022 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
2026 if (mono_security_core_clr_enabled () &&
2027 !mono_security_core_clr_ensure_reflection_access_field (cf, &error)) {
2028 mono_error_set_pending_exception (&error);
2032 type = mono_field_get_type_checked (cf, &error);
2033 if (!mono_error_ok (&error)) {
2034 mono_error_set_pending_exception (&error);
2038 v = (gchar *) value;
2040 switch (type->type) {
2043 case MONO_TYPE_BOOLEAN:
2046 case MONO_TYPE_CHAR:
2055 case MONO_TYPE_VALUETYPE:
2058 v += sizeof (MonoObject);
2060 case MONO_TYPE_STRING:
2061 case MONO_TYPE_OBJECT:
2062 case MONO_TYPE_CLASS:
2063 case MONO_TYPE_ARRAY:
2064 case MONO_TYPE_SZARRAY:
2067 case MONO_TYPE_GENERICINST: {
2068 MonoGenericClass *gclass = type->data.generic_class;
2069 g_assert (!gclass->context.class_inst->is_open);
2071 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
2072 MonoClass *nklass = mono_class_from_mono_type (type);
2073 MonoObject *nullable;
2076 * Convert the boxed vtype into a Nullable structure.
2077 * This is complicated by the fact that Nullables have
2078 * a variable structure.
2080 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
2081 if (!mono_error_ok (&error)) {
2082 mono_error_set_pending_exception (&error);
2086 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
2088 v = (gchar *)mono_object_unbox (nullable);
2091 if (gclass->container_class->valuetype && (v != NULL))
2092 v += sizeof (MonoObject);
2096 g_error ("type 0x%x not handled in "
2097 "ves_icall_FieldInfo_SetValueInternal", type->type);
2102 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
2103 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
2104 if (!is_ok (&error)) {
2105 mono_error_set_pending_exception (&error);
2108 if (!vtable->initialized) {
2109 if (!mono_runtime_class_init_full (vtable, &error)) {
2110 mono_error_set_pending_exception (&error);
2114 mono_field_static_set_value (vtable, cf, v);
2116 mono_field_set_value (obj, cf, v);
2121 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
2130 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
2131 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2135 if (MONO_TYPE_IS_REFERENCE (f->type))
2136 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
2138 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
2141 ICALL_EXPORT MonoObject *
2142 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
2144 MonoObject *o = NULL;
2145 MonoClassField *field = rfield->field;
2147 MonoDomain *domain = mono_object_domain (rfield);
2149 MonoTypeEnum def_type;
2150 const char *def_value;
2154 mono_class_init (field->parent);
2156 t = mono_field_get_type_checked (field, &error);
2157 if (!mono_error_ok (&error)) {
2158 mono_error_set_pending_exception (&error);
2162 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2163 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2167 if (image_is_dynamic (field->parent->image)) {
2168 MonoClass *klass = field->parent;
2169 int fidx = field - klass->fields;
2171 g_assert (fidx >= 0 && fidx < klass->field.count);
2172 g_assert (klass->ext);
2173 g_assert (klass->ext->field_def_values);
2174 def_type = klass->ext->field_def_values [fidx].def_type;
2175 def_value = klass->ext->field_def_values [fidx].data;
2176 if (def_type == MONO_TYPE_END) {
2177 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2181 def_value = mono_class_get_field_default_value (field, &def_type);
2182 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2184 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2189 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2193 case MONO_TYPE_BOOLEAN:
2196 case MONO_TYPE_CHAR:
2204 case MONO_TYPE_R8: {
2207 /* boxed value type */
2208 t = g_new0 (MonoType, 1);
2210 klass = mono_class_from_mono_type (t);
2212 o = mono_object_new_checked (domain, klass, &error);
2213 if (!mono_error_ok (&error)) {
2214 mono_error_set_pending_exception (&error);
2217 v = ((gchar *) o) + sizeof (MonoObject);
2218 mono_get_constant_value_from_blob (domain, def_type, def_value, v, &error);
2219 if (mono_error_set_pending_exception (&error))
2223 case MONO_TYPE_STRING:
2224 case MONO_TYPE_CLASS:
2225 mono_get_constant_value_from_blob (domain, def_type, def_value, &o, &error);
2226 if (mono_error_set_pending_exception (&error))
2230 g_assert_not_reached ();
2236 ICALL_EXPORT MonoReflectionType*
2237 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2240 MonoReflectionType *ret;
2243 type = mono_field_get_type_checked (ref_field->field, &error);
2244 if (!mono_error_ok (&error)) {
2245 mono_error_set_pending_exception (&error);
2249 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2250 if (!mono_error_ok (&error)) {
2251 mono_error_set_pending_exception (&error);
2258 /* From MonoProperty.cs */
2260 PInfo_Attributes = 1,
2261 PInfo_GetMethod = 1 << 1,
2262 PInfo_SetMethod = 1 << 2,
2263 PInfo_ReflectedType = 1 << 3,
2264 PInfo_DeclaringType = 1 << 4,
2269 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2272 MonoReflectionType *rt;
2273 MonoReflectionMethod *rm;
2274 MonoDomain *domain = mono_object_domain (property);
2275 const MonoProperty *pproperty = property->property;
2277 if ((req_info & PInfo_ReflectedType) != 0) {
2278 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2279 if (mono_error_set_pending_exception (&error))
2282 MONO_STRUCT_SETREF (info, parent, rt);
2284 if ((req_info & PInfo_DeclaringType) != 0) {
2285 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2286 if (mono_error_set_pending_exception (&error))
2289 MONO_STRUCT_SETREF (info, declaring_type, rt);
2292 if ((req_info & PInfo_Name) != 0)
2293 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2295 if ((req_info & PInfo_Attributes) != 0)
2296 info->attrs = pproperty->attrs;
2298 if ((req_info & PInfo_GetMethod) != 0) {
2299 if (pproperty->get &&
2300 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2301 pproperty->get->klass == property->klass)) {
2302 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2303 if (mono_error_set_pending_exception (&error))
2309 MONO_STRUCT_SETREF (info, get, rm);
2311 if ((req_info & PInfo_SetMethod) != 0) {
2312 if (pproperty->set &&
2313 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2314 pproperty->set->klass == property->klass)) {
2315 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2316 if (mono_error_set_pending_exception (&error))
2322 MONO_STRUCT_SETREF (info, set, rm);
2325 * There may be other methods defined for properties, though, it seems they are not exposed
2326 * in the reflection API
2331 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2334 MonoReflectionType *rt;
2335 MonoReflectionMethod *rm;
2336 MonoDomain *domain = mono_object_domain (event);
2338 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2339 if (mono_error_set_pending_exception (&error))
2342 MONO_STRUCT_SETREF (info, reflected_type, rt);
2344 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2345 if (mono_error_set_pending_exception (&error))
2348 MONO_STRUCT_SETREF (info, declaring_type, rt);
2350 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2351 info->attrs = event->event->attrs;
2353 if (event->event->add) {
2354 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2355 if (mono_error_set_pending_exception (&error))
2361 MONO_STRUCT_SETREF (info, add_method, rm);
2363 if (event->event->remove) {
2364 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2365 if (mono_error_set_pending_exception (&error))
2371 MONO_STRUCT_SETREF (info, remove_method, rm);
2373 if (event->event->raise) {
2374 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2375 if (mono_error_set_pending_exception (&error))
2381 MONO_STRUCT_SETREF (info, raise_method, rm);
2383 #ifndef MONO_SMALL_CONFIG
2384 if (event->event->other) {
2386 while (event->event->other [n])
2388 MonoArray *info_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, n, &error);
2389 if (mono_error_set_pending_exception (&error))
2391 MONO_STRUCT_SETREF (info, other_methods, info_arr);
2393 for (i = 0; i < n; i++) {
2394 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2395 if (mono_error_set_pending_exception (&error))
2397 mono_array_setref (info->other_methods, i, rm);
2404 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2409 mono_class_setup_interfaces (klass, error);
2410 if (!mono_error_ok (error))
2413 for (i = 0; i < klass->interface_count; i++) {
2414 ic = klass->interfaces [i];
2415 g_hash_table_insert (ifaces, ic, ic);
2417 collect_interfaces (ic, ifaces, error);
2418 if (!mono_error_ok (error))
2424 MonoArray *iface_array;
2425 MonoGenericContext *context;
2429 } FillIfaceArrayData;
2432 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2434 MonoReflectionType *rt;
2435 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2436 MonoClass *ic = (MonoClass *)key;
2437 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2439 if (!mono_error_ok (data->error))
2442 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2443 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2444 if (!mono_error_ok (data->error))
2448 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2449 if (!mono_error_ok (data->error))
2452 mono_array_setref (data->iface_array, data->next_idx++, rt);
2455 mono_metadata_free_type (inflated);
2459 get_interfaces_hash (gconstpointer v1)
2461 MonoClass *k = (MonoClass*)v1;
2463 return k->type_token;
2466 ICALL_EXPORT MonoArray*
2467 ves_icall_RuntimeType_GetInterfaces (MonoReflectionType* type)
2470 MonoClass *klass = mono_class_from_mono_type (type->type);
2472 FillIfaceArrayData data = { 0 };
2475 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2477 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2478 data.context = mono_class_get_context (klass);
2479 klass = klass->generic_class->container_class;
2482 for (parent = klass; parent; parent = parent->parent) {
2483 mono_class_setup_interfaces (parent, &error);
2484 if (!mono_error_ok (&error))
2486 collect_interfaces (parent, iface_hash, &error);
2487 if (!mono_error_ok (&error))
2491 data.error = &error;
2492 data.domain = mono_object_domain (type);
2494 len = g_hash_table_size (iface_hash);
2496 g_hash_table_destroy (iface_hash);
2497 if (!data.domain->empty_types) {
2498 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, 0, &error);
2499 if (!is_ok (&error))
2502 return data.domain->empty_types;
2505 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.runtimetype_class, len, &error);
2506 if (!is_ok (&error))
2508 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2509 if (!mono_error_ok (&error))
2512 g_hash_table_destroy (iface_hash);
2513 return data.iface_array;
2516 g_hash_table_destroy (iface_hash);
2517 mono_error_set_pending_exception (&error);
2522 ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2524 gboolean variance_used;
2525 MonoClass *klass = mono_class_from_mono_type (type->type);
2526 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2527 MonoReflectionMethod *member;
2530 int i = 0, len, ioffset;
2534 mono_class_init_checked (klass, &error);
2535 if (mono_error_set_pending_exception (&error))
2537 mono_class_init_checked (iclass, &error);
2538 if (mono_error_set_pending_exception (&error))
2541 mono_class_setup_vtable (klass);
2543 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2547 len = mono_class_num_methods (iclass);
2548 domain = mono_object_domain (type);
2549 MonoArray *targets_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2550 if (mono_error_set_pending_exception (&error))
2552 mono_gc_wbarrier_generic_store (targets, (MonoObject*) targets_arr);
2553 MonoArray *methods_arr = mono_array_new_checked (domain, mono_defaults.method_info_class, len, &error);
2554 if (mono_error_set_pending_exception (&error))
2556 mono_gc_wbarrier_generic_store (methods, (MonoObject*) methods_arr);
2558 while ((method = mono_class_get_methods (iclass, &iter))) {
2559 member = mono_method_get_object_checked (domain, method, iclass, &error);
2560 if (mono_error_set_pending_exception (&error))
2562 mono_array_setref (*methods, i, member);
2563 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2564 if (mono_error_set_pending_exception (&error))
2566 mono_array_setref (*targets, i, member);
2573 ves_icall_RuntimeType_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2576 MonoClass *klass = mono_class_from_mono_type (type->type);
2578 mono_class_init_checked (klass, &error);
2579 if (mono_error_set_pending_exception (&error))
2582 if (image_is_dynamic (klass->image)) {
2583 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2584 *packing = tb->packing_size;
2585 *size = tb->class_size;
2587 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2591 ICALL_EXPORT MonoReflectionType*
2592 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2595 MonoReflectionType *ret;
2598 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2599 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2600 mono_error_set_pending_exception (&error);
2604 klass = mono_class_from_mono_type (type->type);
2605 mono_class_init_checked (klass, &error);
2606 if (mono_error_set_pending_exception (&error))
2610 // GetElementType should only return a type for:
2611 // Array Pointer PassedByRef
2612 if (type->type->byref)
2613 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2614 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2615 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2616 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2617 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2621 mono_error_set_pending_exception (&error);
2626 ICALL_EXPORT MonoReflectionType*
2627 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2630 MonoReflectionType *ret;
2632 if (type->type->byref)
2635 MonoClass *klass = mono_class_from_mono_type (type->type);
2639 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2640 mono_error_set_pending_exception (&error);
2645 ICALL_EXPORT MonoBoolean
2646 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2648 return type->type->type == MONO_TYPE_PTR;
2651 ICALL_EXPORT MonoBoolean
2652 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2654 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)));
2657 ICALL_EXPORT MonoBoolean
2658 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2660 return type->type->byref;
2663 ICALL_EXPORT MonoBoolean
2664 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2667 MonoClass *klass = mono_class_from_mono_type (type->type);
2668 mono_class_init_checked (klass, &error);
2669 if (mono_error_set_pending_exception (&error))
2672 return mono_class_is_com_object (klass);
2675 ICALL_EXPORT guint32
2676 ves_icall_reflection_get_token (MonoObject* obj)
2679 guint32 result = mono_reflection_get_token_checked (obj, &error);
2680 mono_error_set_pending_exception (&error);
2684 ICALL_EXPORT MonoReflectionModule*
2685 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2688 MonoReflectionModule *result = NULL;
2689 MonoClass *klass = mono_class_from_mono_type (type->type);
2690 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2691 mono_error_set_pending_exception (&error);
2695 ICALL_EXPORT MonoReflectionAssembly*
2696 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2699 MonoDomain *domain = mono_domain_get ();
2700 MonoClass *klass = mono_class_from_mono_type (type->type);
2701 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2702 mono_error_set_pending_exception (&error);
2706 ICALL_EXPORT MonoReflectionType*
2707 ves_icall_RuntimeType_get_DeclaringType (MonoReflectionType *type)
2710 MonoReflectionType *ret;
2711 MonoDomain *domain = mono_domain_get ();
2714 if (type->type->byref)
2716 if (type->type->type == MONO_TYPE_VAR) {
2717 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2718 klass = param ? param->owner.klass : NULL;
2719 } else if (type->type->type == MONO_TYPE_MVAR) {
2720 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2721 klass = param ? param->owner.method->klass : NULL;
2723 klass = mono_class_from_mono_type (type->type)->nested_in;
2729 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2730 mono_error_set_pending_exception (&error);
2735 ICALL_EXPORT MonoString*
2736 ves_icall_RuntimeType_get_Name (MonoReflectionType *type)
2738 MonoDomain *domain = mono_domain_get ();
2739 MonoClass *klass = mono_class_from_mono_type (type->type);
2741 if (type->type->byref) {
2742 char *n = g_strdup_printf ("%s&", klass->name);
2743 MonoString *res = mono_string_new (domain, n);
2749 return mono_string_new (domain, klass->name);
2753 ICALL_EXPORT MonoString*
2754 ves_icall_RuntimeType_get_Namespace (MonoReflectionType *type)
2756 MonoDomain *domain = mono_domain_get ();
2757 MonoClass *klass = mono_class_from_mono_type (type->type);
2759 while (klass->nested_in)
2760 klass = klass->nested_in;
2762 if (klass->name_space [0] == '\0')
2765 return mono_string_new (domain, klass->name_space);
2769 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2773 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2774 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2778 klass = mono_class_from_mono_type (type->type);
2784 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count, MonoError *error)
2786 return mono_array_new_checked (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count, error);
2789 ICALL_EXPORT MonoArray*
2790 ves_icall_RuntimeType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2793 MonoReflectionType *rt;
2795 MonoClass *klass, *pklass;
2796 MonoDomain *domain = mono_object_domain (type);
2799 klass = mono_class_from_mono_type (type->type);
2801 if (klass->generic_container) {
2802 MonoGenericContainer *container = klass->generic_container;
2803 res = create_type_array (domain, runtimeTypeArray, container->type_argc, &error);
2804 if (mono_error_set_pending_exception (&error))
2806 for (i = 0; i < container->type_argc; ++i) {
2807 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2809 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2810 if (mono_error_set_pending_exception (&error))
2813 mono_array_setref (res, i, rt);
2815 } else if (klass->generic_class) {
2816 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2817 res = create_type_array (domain, runtimeTypeArray, inst->type_argc, &error);
2818 if (mono_error_set_pending_exception (&error))
2820 for (i = 0; i < inst->type_argc; ++i) {
2821 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2822 if (mono_error_set_pending_exception (&error))
2825 mono_array_setref (res, i, rt);
2833 ICALL_EXPORT gboolean
2834 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2838 if (!IS_MONOTYPE (type))
2841 if (type->type->byref)
2844 klass = mono_class_from_mono_type (type->type);
2845 return klass->generic_container != NULL;
2848 ICALL_EXPORT MonoReflectionType*
2849 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2852 MonoReflectionType *ret;
2855 if (type->type->byref)
2858 klass = mono_class_from_mono_type (type->type);
2860 if (klass->generic_container) {
2861 return type; /* check this one */
2863 if (klass->generic_class) {
2864 MonoClass *generic_class = klass->generic_class->container_class;
2867 tb = mono_class_get_ref_info (generic_class);
2869 if (generic_class->wastypebuilder && tb)
2870 return (MonoReflectionType *)tb;
2872 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2873 mono_error_set_pending_exception (&error);
2881 ICALL_EXPORT MonoReflectionType*
2882 ves_icall_RuntimeType_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2885 MonoReflectionType *ret;
2887 MonoType *geninst, **types;
2890 g_assert (IS_MONOTYPE (type));
2891 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2892 if (mono_error_set_pending_exception (&error))
2895 count = mono_array_length (type_array);
2896 types = g_new0 (MonoType *, count);
2898 for (i = 0; i < count; i++) {
2899 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2900 types [i] = t->type;
2903 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2906 mono_error_set_pending_exception (&error);
2910 klass = mono_class_from_mono_type (geninst);
2912 /*we might inflate to the GTD*/
2913 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2914 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2918 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2919 mono_error_set_pending_exception (&error);
2924 ICALL_EXPORT gboolean
2925 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2929 if (!IS_MONOTYPE (type))
2932 if (type->type->byref)
2935 klass = mono_class_from_mono_type (type->type);
2936 return klass->generic_class != NULL || klass->generic_container != NULL;
2940 ves_icall_RuntimeType_GetGenericParameterPosition (MonoReflectionType *type)
2942 if (!IS_MONOTYPE (type))
2945 if (is_generic_parameter (type->type))
2946 return mono_type_get_generic_param_num (type->type);
2950 ICALL_EXPORT MonoGenericParamInfo *
2951 ves_icall_RuntimeTypeHandle_GetGenericParameterInfo (MonoReflectionType *type)
2953 return mono_generic_param_info (type->type->data.generic_param);
2956 ICALL_EXPORT MonoBoolean
2957 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2959 return is_generic_parameter (type->type);
2962 ICALL_EXPORT MonoBoolean
2963 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2965 return is_generic_parameter (tb->type.type);
2969 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2970 MonoReflectionType *t)
2972 enumtype->type = t->type;
2975 ICALL_EXPORT MonoReflectionMethod*
2976 ves_icall_RuntimeType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2977 MonoReflectionMethod* generic)
2984 MonoReflectionMethod *ret = NULL;
2986 domain = ((MonoObject *)type)->vtable->domain;
2988 klass = mono_class_from_mono_type (type->type);
2989 mono_class_init_checked (klass, &error);
2990 if (mono_error_set_pending_exception (&error))
2994 while ((method = mono_class_get_methods (klass, &iter))) {
2995 if (method->token == generic->method->token) {
2996 ret = mono_method_get_object_checked (domain, method, klass, &error);
2997 if (mono_error_set_pending_exception (&error))
3005 ICALL_EXPORT MonoReflectionMethod *
3006 ves_icall_RuntimeType_get_DeclaringMethod (MonoReflectionType *ref_type)
3009 MonoType *type = ref_type->type;
3011 MonoReflectionMethod *ret = NULL;
3013 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
3014 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
3017 if (type->type == MONO_TYPE_VAR)
3020 method = mono_type_get_generic_param_owner (type)->owner.method;
3023 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
3024 if (!mono_error_ok (&error))
3025 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3029 ICALL_EXPORT MonoBoolean
3030 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
3032 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3036 ICALL_EXPORT MonoBoolean
3037 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
3039 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
3044 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
3046 MonoDomain *domain = mono_domain_get ();
3047 MonoImage *image = method->method->klass->image;
3048 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
3049 MonoTableInfo *tables = image->tables;
3050 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
3051 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
3052 guint32 im_cols [MONO_IMPLMAP_SIZE];
3053 guint32 scope_token;
3054 const char *import = NULL;
3055 const char *scope = NULL;
3057 if (image_is_dynamic (image)) {
3058 MonoReflectionMethodAux *method_aux =
3059 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
3061 import = method_aux->dllentry;
3062 scope = method_aux->dll;
3065 if (!import || !scope) {
3066 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
3071 if (piinfo->implmap_idx) {
3072 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
3074 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
3075 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
3076 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
3077 scope = mono_metadata_string_heap (image, scope_token);
3081 *flags = piinfo->piflags;
3082 *entry_point = mono_string_new (domain, import);
3083 *dll_name = mono_string_new (domain, scope);
3086 ICALL_EXPORT MonoReflectionMethod *
3087 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
3089 MonoMethodInflated *imethod;
3091 MonoReflectionMethod *ret = NULL;
3094 if (method->method->is_generic)
3097 if (!method->method->is_inflated)
3100 imethod = (MonoMethodInflated *) method->method;
3102 result = imethod->declaring;
3103 /* Not a generic method. */
3104 if (!result->is_generic)
3107 if (image_is_dynamic (method->method->klass->image)) {
3108 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3109 MonoReflectionMethod *res;
3112 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3113 * the dynamic case as well ?
3115 mono_image_lock ((MonoImage*)image);
3116 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3117 mono_image_unlock ((MonoImage*)image);
3123 if (imethod->context.class_inst) {
3124 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3125 /*Generic methods gets the context of the GTD.*/
3126 if (mono_class_get_context (klass)) {
3127 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
3128 if (!mono_error_ok (&error))
3133 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
3135 if (!mono_error_ok (&error))
3136 mono_error_set_pending_exception (&error);
3140 ICALL_EXPORT gboolean
3141 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3143 return mono_method_signature (method->method)->generic_param_count != 0;
3146 ICALL_EXPORT gboolean
3147 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3149 return method->method->is_generic;
3152 ICALL_EXPORT MonoArray*
3153 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3156 MonoReflectionType *rt;
3161 domain = mono_object_domain (method);
3163 if (method->method->is_inflated) {
3164 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3167 count = inst->type_argc;
3168 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3169 if (mono_error_set_pending_exception (&error))
3172 for (i = 0; i < count; i++) {
3173 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3174 if (mono_error_set_pending_exception (&error))
3177 mono_array_setref (res, i, rt);
3184 count = mono_method_signature (method->method)->generic_param_count;
3185 res = mono_array_new_checked (domain, mono_defaults.systemtype_class, count, &error);
3186 if (mono_error_set_pending_exception (&error))
3189 for (i = 0; i < count; i++) {
3190 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3191 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3192 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3194 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3195 if (mono_error_set_pending_exception (&error))
3198 mono_array_setref (res, i, rt);
3204 ICALL_EXPORT MonoObject *
3205 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3209 * Invoke from reflection is supposed to always be a virtual call (the API
3210 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3211 * greater flexibility.
3213 MonoMethod *m = method->method;
3214 MonoMethodSignature *sig = mono_method_signature (m);
3217 void *obj = this_arg;
3221 if (mono_security_core_clr_enabled () &&
3222 !mono_security_core_clr_ensure_reflection_access_method (m, &error)) {
3223 mono_error_set_pending_exception (&error);
3227 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3228 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3229 mono_error_cleanup (&error); /* FIXME does this make sense? */
3230 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3235 if (!mono_object_isinst_checked (this_arg, m->klass, &error)) {
3236 if (!is_ok (&error)) {
3237 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_error_convert_to_exception (&error));
3240 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3241 char *target_name = mono_type_get_full_name (m->klass);
3242 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3243 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3245 g_free (target_name);
3249 m = mono_object_get_virtual_method (this_arg, m);
3250 /* must pass the pointer to the value for valuetype methods */
3251 if (m->klass->valuetype)
3252 obj = mono_object_unbox (this_arg);
3253 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3254 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3259 if (sig->ret->byref) {
3260 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"));
3264 pcount = params? mono_array_length (params): 0;
3265 if (pcount != sig->param_count) {
3266 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3270 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3271 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."));
3275 image = m->klass->image;
3276 if (image->assembly->ref_only) {
3277 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."));
3281 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3282 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3286 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3290 intptr_t *lower_bounds;
3291 pcount = mono_array_length (params);
3292 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3293 /* Note: the synthetized array .ctors have int32 as argument type */
3294 for (i = 0; i < pcount; ++i)
3295 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3297 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3298 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3299 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3300 if (!mono_error_ok (&error)) {
3301 mono_error_set_pending_exception (&error);
3305 for (i = 0; i < mono_array_length (arr); ++i) {
3306 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3307 if (!mono_error_ok (&error)) {
3308 mono_error_set_pending_exception (&error);
3311 mono_array_setref_fast (arr, i, subarray);
3313 return (MonoObject*)arr;
3316 if (m->klass->rank == pcount) {
3317 /* Only lengths provided. */
3318 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3319 if (!mono_error_ok (&error)) {
3320 mono_error_set_pending_exception (&error);
3324 return (MonoObject*)arr;
3326 g_assert (pcount == (m->klass->rank * 2));
3327 /* The arguments are lower-bound-length pairs */
3328 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3330 for (i = 0; i < pcount / 2; ++i) {
3331 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3332 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3335 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3336 if (!mono_error_ok (&error)) {
3337 mono_error_set_pending_exception (&error);
3341 return (MonoObject*)arr;
3344 MonoObject *result = mono_runtime_invoke_array_checked (m, obj, params, &error);
3345 mono_error_set_pending_exception (&error);
3349 #ifndef DISABLE_REMOTING
3350 ICALL_EXPORT MonoObject *
3351 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3354 MonoDomain *domain = mono_object_domain (method);
3355 MonoMethod *m = method->method;
3356 MonoMethodSignature *sig = mono_method_signature (m);
3357 MonoArray *out_args;
3359 int i, j, outarg_count = 0;
3361 if (m->klass == mono_defaults.object_class) {
3362 if (!strcmp (m->name, "FieldGetter")) {
3363 MonoClass *k = this_arg->vtable->klass;
3367 /* If this is a proxy, then it must be a CBO */
3368 if (k == mono_defaults.transparent_proxy_class) {
3369 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3370 this_arg = tp->rp->unwrapped_server;
3371 g_assert (this_arg);
3372 k = this_arg->vtable->klass;
3375 name = mono_array_get (params, MonoString *, 1);
3376 str = mono_string_to_utf8_checked (name, &error);
3377 if (mono_error_set_pending_exception (&error))
3381 MonoClassField* field = mono_class_get_field_from_name (k, str);
3384 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3385 if (field_klass->valuetype) {
3386 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3387 if (mono_error_set_pending_exception (&error))
3390 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3392 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 1, &error);
3393 if (mono_error_set_pending_exception (&error))
3395 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3396 mono_array_setref (out_args, 0, result);
3403 g_assert_not_reached ();
3405 } else if (!strcmp (m->name, "FieldSetter")) {
3406 MonoClass *k = this_arg->vtable->klass;
3412 /* If this is a proxy, then it must be a CBO */
3413 if (k == mono_defaults.transparent_proxy_class) {
3414 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3415 this_arg = tp->rp->unwrapped_server;
3416 g_assert (this_arg);
3417 k = this_arg->vtable->klass;
3420 name = mono_array_get (params, MonoString *, 1);
3421 str = mono_string_to_utf8_checked (name, &error);
3422 if (mono_error_set_pending_exception (&error))
3426 MonoClassField* field = mono_class_get_field_from_name (k, str);
3429 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3430 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3432 if (field_klass->valuetype) {
3433 size = mono_type_size (field->type, &align);
3434 g_assert (size == mono_class_value_size (field_klass, NULL));
3435 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3437 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3440 out_args = mono_array_new_checked (domain, mono_defaults.object_class, 0, &error);
3441 if (mono_error_set_pending_exception (&error))
3443 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3452 g_assert_not_reached ();
3457 for (i = 0; i < mono_array_length (params); i++) {
3458 if (sig->params [i]->byref)
3462 out_args = mono_array_new_checked (domain, mono_defaults.object_class, outarg_count, &error);
3463 if (mono_error_set_pending_exception (&error))
3466 /* handle constructors only for objects already allocated */
3467 if (!strcmp (method->method->name, ".ctor"))
3468 g_assert (this_arg);
3470 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3471 g_assert (!method->method->klass->valuetype);
3472 result = mono_runtime_invoke_array_checked (method->method, this_arg, params, &error);
3473 if (mono_error_set_pending_exception (&error))
3476 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3477 if (sig->params [i]->byref) {
3479 arg = mono_array_get (params, gpointer, i);
3480 mono_array_setref (out_args, j, arg);
3485 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3492 read_enum_value (const char *mem, int type)
3495 case MONO_TYPE_BOOLEAN:
3497 return *(guint8*)mem;
3499 return *(gint8*)mem;
3500 case MONO_TYPE_CHAR:
3502 return read16 (mem);
3504 return (gint16) read16 (mem);
3506 return read32 (mem);
3508 return (gint32) read32 (mem);
3511 return read64 (mem);
3513 g_assert_not_reached ();
3519 write_enum_value (char *mem, int type, guint64 value)
3523 case MONO_TYPE_I1: {
3524 guint8 *p = (guint8*)mem;
3530 case MONO_TYPE_CHAR: {
3531 guint16 *p = (guint16 *)mem;
3536 case MONO_TYPE_I4: {
3537 guint32 *p = (guint32 *)mem;
3542 case MONO_TYPE_I8: {
3543 guint64 *p = (guint64 *)mem;
3548 g_assert_not_reached ();
3553 ICALL_EXPORT MonoObject *
3554 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3562 domain = mono_object_domain (enumType);
3563 enumc = mono_class_from_mono_type (enumType->type);
3565 mono_class_init_checked (enumc, &error);
3566 if (mono_error_set_pending_exception (&error))
3569 etype = mono_class_enum_basetype (enumc);
3571 res = mono_object_new_checked (domain, enumc, &error);
3572 if (mono_error_set_pending_exception (&error))
3574 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3579 ICALL_EXPORT MonoBoolean
3580 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3582 int size = mono_class_value_size (a->vtable->klass, NULL);
3583 guint64 a_val = 0, b_val = 0;
3585 memcpy (&a_val, mono_object_unbox (a), size);
3586 memcpy (&b_val, mono_object_unbox (b), size);
3588 return (a_val & b_val) == b_val;
3591 ICALL_EXPORT MonoObject *
3592 ves_icall_System_Enum_get_value (MonoObject *eobj)
3604 g_assert (eobj->vtable->klass->enumtype);
3606 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3607 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3608 if (mono_error_set_pending_exception (&error))
3610 dst = (char *)res + sizeof (MonoObject);
3611 src = (char *)eobj + sizeof (MonoObject);
3612 size = mono_class_value_size (enumc, NULL);
3614 memcpy (dst, src, size);
3619 ICALL_EXPORT MonoReflectionType *
3620 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3623 MonoReflectionType *ret;
3627 klass = mono_class_from_mono_type (type->type);
3628 mono_class_init_checked (klass, &error);
3629 if (mono_error_set_pending_exception (&error))
3632 etype = mono_class_enum_basetype (klass);
3634 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3638 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3639 mono_error_set_pending_exception (&error);
3645 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3647 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3648 gpointer odata = (char *)other + sizeof (MonoObject);
3649 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3650 g_assert (basetype);
3655 if (eobj->vtable->klass != other->vtable->klass)
3658 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3659 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3660 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3663 return me > other ? 1 : -1; \
3666 switch (basetype->type) {
3668 COMPARE_ENUM_VALUES (guint8);
3670 COMPARE_ENUM_VALUES (gint8);
3671 case MONO_TYPE_CHAR:
3673 COMPARE_ENUM_VALUES (guint16);
3675 COMPARE_ENUM_VALUES (gint16);
3677 COMPARE_ENUM_VALUES (guint32);
3679 COMPARE_ENUM_VALUES (gint32);
3681 COMPARE_ENUM_VALUES (guint64);
3683 COMPARE_ENUM_VALUES (gint64);
3687 #undef COMPARE_ENUM_VALUES
3688 /* indicates that the enum was of an unsupported unerlying type */
3693 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3695 gpointer data = (char *)eobj + sizeof (MonoObject);
3696 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3697 g_assert (basetype);
3699 switch (basetype->type) {
3700 case MONO_TYPE_I1: {
3701 gint8 value = *((gint8*)data);
3702 return ((int)value ^ (int)value << 8);
3705 return *((guint8*)data);
3706 case MONO_TYPE_CHAR:
3708 return *((guint16*)data);
3710 case MONO_TYPE_I2: {
3711 gint16 value = *((gint16*)data);
3712 return ((int)(guint16)value | (((int)value) << 16));
3715 return *((guint32*)data);
3717 return *((gint32*)data);
3719 case MONO_TYPE_I8: {
3720 gint64 value = *((gint64*)data);
3721 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3724 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3729 ICALL_EXPORT MonoBoolean
3730 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3733 MonoDomain *domain = mono_object_domain (type);
3734 MonoClass *enumc = mono_class_from_mono_type (type->type);
3735 guint j = 0, nvalues;
3737 MonoClassField *field;
3739 guint64 field_value, previous_value = 0;
3740 gboolean sorted = TRUE;
3742 mono_class_init_checked (enumc, &error);
3743 if (mono_error_set_pending_exception (&error))
3747 if (!enumc->enumtype) {
3748 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3752 base_type = mono_class_enum_basetype (enumc)->type;
3754 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3755 *names = mono_array_new_checked (domain, mono_defaults.string_class, nvalues, &error);
3756 if (mono_error_set_pending_exception (&error))
3758 *values = mono_array_new_checked (domain, mono_defaults.uint64_class, nvalues, &error);
3759 if (mono_error_set_pending_exception (&error))
3763 while ((field = mono_class_get_fields (enumc, &iter))) {
3765 MonoTypeEnum def_type;
3767 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3769 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3771 if (mono_field_is_deleted (field))
3773 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3775 p = mono_class_get_field_default_value (field, &def_type);
3776 /* len = */ mono_metadata_decode_blob_size (p, &p);
3778 field_value = read_enum_value (p, base_type);
3779 mono_array_set (*values, guint64, j, field_value);
3781 if (previous_value > field_value)
3784 previous_value = field_value;
3792 BFLAGS_IgnoreCase = 1,
3793 BFLAGS_DeclaredOnly = 2,
3794 BFLAGS_Instance = 4,
3796 BFLAGS_Public = 0x10,
3797 BFLAGS_NonPublic = 0x20,
3798 BFLAGS_FlattenHierarchy = 0x40,
3799 BFLAGS_InvokeMethod = 0x100,
3800 BFLAGS_CreateInstance = 0x200,
3801 BFLAGS_GetField = 0x400,
3802 BFLAGS_SetField = 0x800,
3803 BFLAGS_GetProperty = 0x1000,
3804 BFLAGS_SetProperty = 0x2000,
3805 BFLAGS_ExactBinding = 0x10000,
3806 BFLAGS_SuppressChangeType = 0x20000,
3807 BFLAGS_OptionalParamBinding = 0x40000
3810 ICALL_EXPORT GPtrArray*
3811 ves_icall_RuntimeType_GetFields_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
3814 MonoClass *startklass, *klass;
3817 int (*compare_func) (const char *s1, const char *s2) = NULL;
3818 MonoClassField *field;
3820 if (type->type->byref) {
3821 return g_ptr_array_new ();
3824 mono_error_init (&error);
3826 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3828 klass = startklass = mono_class_from_mono_type (type->type);
3830 GPtrArray *ptr_array = g_ptr_array_sized_new (16);
3833 if (mono_class_has_failure (klass)) {
3834 mono_error_set_for_class_failure (&error, klass);
3839 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3840 guint32 flags = mono_field_get_flags (field);
3842 if (mono_field_is_deleted_with_flags (field, flags))
3844 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3845 if (bflags & BFLAGS_Public)
3847 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3848 if (bflags & BFLAGS_NonPublic) {
3855 if (flags & FIELD_ATTRIBUTE_STATIC) {
3856 if (bflags & BFLAGS_Static)
3857 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3860 if (bflags & BFLAGS_Instance)
3867 if (utf8_name != NULL && compare_func (mono_field_get_name (field), utf8_name))
3870 g_ptr_array_add (ptr_array, field);
3872 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3878 g_ptr_array_free (ptr_array, TRUE);
3879 mono_error_set_pending_exception (&error);
3884 method_nonpublic (MonoMethod* method, gboolean start_klass)
3886 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3887 case METHOD_ATTRIBUTE_ASSEM:
3888 return (start_klass || mono_defaults.generic_ilist_class);
3889 case METHOD_ATTRIBUTE_PRIVATE:
3891 case METHOD_ATTRIBUTE_PUBLIC:
3899 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoError *error)
3902 MonoClass *startklass;
3906 /*FIXME, use MonoBitSet*/
3907 guint32 method_slots_default [8];
3908 guint32 *method_slots = NULL;
3909 int (*compare_func) (const char *s1, const char *s2) = NULL;
3911 array = g_ptr_array_new ();
3913 mono_error_init (error);
3916 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3918 /* An optimization for calls made from Delegate:CreateDelegate () */
3919 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3920 method = mono_get_delegate_invoke (klass);
3923 g_ptr_array_add (array, method);
3927 mono_class_setup_methods (klass);
3928 mono_class_setup_vtable (klass);
3929 if (mono_class_has_failure (klass))
3932 if (is_generic_parameter (&klass->byval_arg))
3933 nslots = mono_class_get_vtable_size (klass->parent);
3935 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3936 if (nslots >= sizeof (method_slots_default) * 8) {
3937 method_slots = g_new0 (guint32, nslots / 32 + 1);
3939 method_slots = method_slots_default;
3940 memset (method_slots, 0, sizeof (method_slots_default));
3943 mono_class_setup_methods (klass);
3944 mono_class_setup_vtable (klass);
3945 if (mono_class_has_failure (klass))
3949 while ((method = mono_class_get_methods (klass, &iter))) {
3951 if (method->slot != -1) {
3952 g_assert (method->slot < nslots);
3953 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3955 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3956 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3959 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3961 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3962 if (bflags & BFLAGS_Public)
3964 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3970 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3971 if (bflags & BFLAGS_Static)
3972 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3975 if (bflags & BFLAGS_Instance)
3983 if (compare_func (name, method->name))
3988 g_ptr_array_add (array, method);
3990 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3992 if (method_slots != method_slots_default)
3993 g_free (method_slots);
3998 if (method_slots != method_slots_default)
3999 g_free (method_slots);
4000 g_ptr_array_free (array, TRUE);
4002 g_assert (mono_class_has_failure (klass));
4003 mono_error_set_for_class_failure (error, klass);
4007 ICALL_EXPORT GPtrArray*
4008 ves_icall_RuntimeType_GetMethodsByName_native (MonoReflectionType *type, const char *mname, guint32 bflags, MonoBoolean ignore_case)
4011 GPtrArray *method_array;
4014 klass = mono_class_from_mono_type (type->type);
4015 if (type->type->byref) {
4016 return g_ptr_array_new ();
4019 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &error);
4020 mono_error_set_pending_exception (&error);
4021 return method_array;
4024 ICALL_EXPORT GPtrArray*
4025 ves_icall_RuntimeType_GetConstructors_native (MonoReflectionType *type, guint32 bflags)
4027 MonoClass *startklass, *klass;
4030 gpointer iter = NULL;
4031 GPtrArray *res_array;
4034 if (type->type->byref) {
4035 return g_ptr_array_new ();
4038 klass = startklass = mono_class_from_mono_type (type->type);
4040 mono_class_setup_methods (klass);
4041 if (mono_class_has_failure (klass)) {
4042 mono_error_init (&error);
4043 mono_error_set_for_class_failure (&error, klass);
4044 mono_error_set_pending_exception (&error);
4048 res_array = g_ptr_array_sized_new (4); /* FIXME, guestimating */
4051 while ((method = mono_class_get_methods (klass, &iter))) {
4053 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
4055 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4056 if (bflags & BFLAGS_Public)
4059 if (bflags & BFLAGS_NonPublic)
4065 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4066 if (bflags & BFLAGS_Static)
4067 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4070 if (bflags & BFLAGS_Instance)
4076 g_ptr_array_add (res_array, method);
4083 property_hash (gconstpointer data)
4085 MonoProperty *prop = (MonoProperty*)data;
4087 return g_str_hash (prop->name);
4091 property_accessor_override (MonoMethod *method1, MonoMethod *method2)
4093 if (method1->slot != -1 && method1->slot == method2->slot)
4096 if (mono_class_get_generic_type_definition (method1->klass) == mono_class_get_generic_type_definition (method2->klass)) {
4097 if (method1->is_inflated)
4098 method1 = ((MonoMethodInflated*) method1)->declaring;
4099 if (method2->is_inflated)
4100 method2 = ((MonoMethodInflated*) method2)->declaring;
4103 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4107 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4109 // Properties are hide-by-name-and-signature
4110 if (!g_str_equal (prop1->name, prop2->name))
4113 /* If we see a property in a generic method, we want to
4114 compare the generic signatures, not the inflated signatures
4115 because we might conflate two properties that were
4119 public T this[T t] { getter { return t; } } // method 1
4120 public U this[U u] { getter { return u; } } // method 2
4123 If we see int Foo<int,int>::Item[int] we need to know if
4124 the indexer came from method 1 or from method 2, and we
4125 shouldn't conflate them. (Bugzilla 36283)
4127 if (prop1->get && prop2->get && !property_accessor_override (prop1->get, prop2->get))
4130 if (prop1->set && prop2->set && !property_accessor_override (prop1->set, prop2->set))
4137 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4142 return method_nonpublic (accessor, start_klass);
4145 ICALL_EXPORT GPtrArray*
4146 ves_icall_RuntimeType_GetPropertiesByName_native (MonoReflectionType *type, gchar *propname, guint32 bflags, MonoBoolean ignore_case)
4149 MonoClass *startklass, *klass;
4154 int (*compare_func) (const char *s1, const char *s2) = NULL;
4156 GHashTable *properties = NULL;
4157 GPtrArray *res_array;
4159 if (type->type->byref) {
4160 return g_ptr_array_new ();
4163 mono_error_init (&error);
4165 klass = startklass = mono_class_from_mono_type (type->type);
4167 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4169 res_array = g_ptr_array_sized_new (8); /*This the average for ASP.NET types*/
4171 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4173 mono_class_setup_methods (klass);
4174 mono_class_setup_vtable (klass);
4175 if (mono_class_has_failure (klass)) {
4176 mono_error_set_for_class_failure (&error, klass);
4181 while ((prop = mono_class_get_properties (klass, &iter))) {
4187 flags = method->flags;
4190 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4191 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4192 if (bflags & BFLAGS_Public)
4194 } else if (bflags & BFLAGS_NonPublic) {
4195 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4196 property_accessor_nonpublic(prop->set, startklass == klass)) {
4203 if (flags & METHOD_ATTRIBUTE_STATIC) {
4204 if (bflags & BFLAGS_Static)
4205 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4208 if (bflags & BFLAGS_Instance)
4216 if (propname != NULL && compare_func (propname, prop->name))
4219 if (g_hash_table_lookup (properties, prop))
4222 g_ptr_array_add (res_array, prop);
4224 g_hash_table_insert (properties, prop, prop);
4226 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4229 g_hash_table_destroy (properties);
4236 g_hash_table_destroy (properties);
4237 g_ptr_array_free (res_array, TRUE);
4239 mono_error_set_pending_exception (&error);
4245 event_hash (gconstpointer data)
4247 MonoEvent *event = (MonoEvent*)data;
4249 return g_str_hash (event->name);
4253 event_equal (MonoEvent *event1, MonoEvent *event2)
4255 // Events are hide-by-name
4256 return g_str_equal (event1->name, event2->name);
4259 ICALL_EXPORT GPtrArray*
4260 ves_icall_RuntimeType_GetEvents_native (MonoReflectionType *type, char *utf8_name, guint32 bflags)
4263 MonoClass *startklass, *klass;
4268 int (*compare_func) (const char *s1, const char *s2) = NULL;
4269 GHashTable *events = NULL;
4270 GPtrArray *res_array;
4272 if (type->type->byref) {
4273 return g_ptr_array_new ();
4276 mono_error_init (&error);
4278 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4280 res_array = g_ptr_array_sized_new (4);
4282 klass = startklass = mono_class_from_mono_type (type->type);
4284 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4286 mono_class_setup_methods (klass);
4287 mono_class_setup_vtable (klass);
4288 if (mono_class_has_failure (klass)) {
4289 mono_error_set_for_class_failure (&error, klass);
4294 while ((event = mono_class_get_events (klass, &iter))) {
4296 method = event->add;
4298 method = event->remove;
4300 method = event->raise;
4302 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4303 if (bflags & BFLAGS_Public)
4305 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4306 if (bflags & BFLAGS_NonPublic)
4311 if (bflags & BFLAGS_NonPublic)
4317 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4318 if (bflags & BFLAGS_Static)
4319 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4322 if (bflags & BFLAGS_Instance)
4327 if (bflags & BFLAGS_Instance)
4332 if (utf8_name != NULL && compare_func (event->name, utf8_name))
4335 if (g_hash_table_lookup (events, event))
4338 g_ptr_array_add (res_array, event);
4340 g_hash_table_insert (events, event, event);
4342 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4345 g_hash_table_destroy (events);
4351 g_hash_table_destroy (events);
4353 g_ptr_array_free (res_array, TRUE);
4355 mono_error_set_pending_exception (&error);
4359 ICALL_EXPORT GPtrArray *
4360 ves_icall_RuntimeType_GetNestedTypes_native (MonoReflectionType *type, char *str, guint32 bflags)
4366 GPtrArray *res_array;
4368 if (type->type->byref) {
4369 return g_ptr_array_new ();
4372 klass = mono_class_from_mono_type (type->type);
4375 * If a nested type is generic, return its generic type definition.
4376 * Note that this means that the return value is essentially the set
4377 * of nested types of the generic type definition of @klass.
4379 * A note in MSDN claims that a generic type definition can have
4380 * nested types that aren't generic. In any case, the container of that
4381 * nested type would be the generic type definition.
4383 if (klass->generic_class)
4384 klass = klass->generic_class->container_class;
4386 res_array = g_ptr_array_new ();
4389 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4391 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4392 if (bflags & BFLAGS_Public)
4395 if (bflags & BFLAGS_NonPublic)
4401 if (str != NULL && strcmp (nested->name, str))
4404 g_ptr_array_add (res_array, &nested->byval_arg);
4410 ICALL_EXPORT MonoReflectionType*
4411 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4414 MonoReflectionType *ret;
4416 MonoType *type = NULL;
4417 MonoTypeNameParse info;
4418 gboolean type_resolve;
4420 /* On MS.NET, this does not fire a TypeResolve event */
4421 type_resolve = TRUE;
4422 str = mono_string_to_utf8_checked (name, &error);
4423 if (mono_error_set_pending_exception (&error))
4425 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4426 if (!mono_reflection_parse_type (str, &info)) {
4428 mono_reflection_free_type_info (&info);
4430 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4433 /*g_print ("failed parse\n");*/
4437 if (info.assembly.name) {
4439 mono_reflection_free_type_info (&info);
4441 /* 1.0 and 2.0 throw different exceptions */
4442 if (mono_defaults.generic_ilist_class)
4443 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4445 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4451 if (module != NULL) {
4452 if (module->image) {
4453 type = mono_reflection_get_type_checked (module->image, module->image, &info, ignoreCase, &type_resolve, &error);
4454 if (!is_ok (&error)) {
4456 mono_reflection_free_type_info (&info);
4457 mono_error_set_pending_exception (&error);
4464 if (assembly_is_dynamic (assembly->assembly)) {
4465 /* Enumerate all modules */
4466 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4470 if (abuilder->modules) {
4471 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4472 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4473 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4474 if (!is_ok (&error)) {
4476 mono_reflection_free_type_info (&info);
4477 mono_error_set_pending_exception (&error);
4485 if (!type && abuilder->loaded_modules) {
4486 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4487 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4488 type = mono_reflection_get_type_checked (mod->image, mod->image, &info, ignoreCase, &type_resolve, &error);
4489 if (!is_ok (&error)) {
4491 mono_reflection_free_type_info (&info);
4492 mono_error_set_pending_exception (&error);
4501 type = mono_reflection_get_type_checked (assembly->assembly->image, assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4502 if (!is_ok (&error)) {
4504 mono_reflection_free_type_info (&info);
4505 mono_error_set_pending_exception (&error);
4510 mono_reflection_free_type_info (&info);
4512 MonoException *e = NULL;
4515 e = mono_get_exception_type_load (name, NULL);
4518 mono_set_pending_exception (e);
4522 if (type->type == MONO_TYPE_CLASS) {
4523 MonoClass *klass = mono_type_get_class (type);
4525 /* need to report exceptions ? */
4526 if (throwOnError && mono_class_has_failure (klass)) {
4527 /* report SecurityException (or others) that occured when loading the assembly */
4528 MonoException *exc = mono_class_get_exception_for_failure (klass);
4529 mono_set_pending_exception (exc);
4534 /* g_print ("got it\n"); */
4535 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4536 mono_error_set_pending_exception (&error);
4542 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4545 gchar *shadow_ini_file;
4548 /* Check for shadow-copied assembly */
4549 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4550 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4552 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4553 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4559 g_free (shadow_ini_file);
4560 if (content != NULL) {
4563 *filename = content;
4570 ICALL_EXPORT MonoString *
4571 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4573 MonoDomain *domain = mono_object_domain (assembly);
4574 MonoAssembly *mass = assembly->assembly;
4575 MonoString *res = NULL;
4580 if (g_path_is_absolute (mass->image->name)) {
4581 absolute = g_strdup (mass->image->name);
4582 dirname = g_path_get_dirname (absolute);
4584 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4585 dirname = g_strdup (mass->basedir);
4588 replace_shadow_path (domain, dirname, &absolute);
4593 for (i = strlen (absolute) - 1; i >= 0; i--)
4594 if (absolute [i] == '\\')
4599 uri = g_filename_to_uri (absolute, NULL, NULL);
4601 const char *prepend = "file://";
4603 if (*absolute == '/' && *(absolute + 1) == '/') {
4606 prepend = "file:///";
4609 uri = g_strconcat (prepend, absolute, NULL);
4613 res = mono_string_new (domain, uri);
4620 ICALL_EXPORT MonoBoolean
4621 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4623 MonoAssembly *mass = assembly->assembly;
4625 return mass->in_gac;
4628 ICALL_EXPORT MonoReflectionAssembly*
4629 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4634 MonoImageOpenStatus status;
4635 MonoReflectionAssembly* result = NULL;
4637 name = mono_string_to_utf8_checked (mname, &error);
4638 if (mono_error_set_pending_exception (&error))
4640 res = mono_assembly_load_with_partial_name (name, &status);
4646 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4648 mono_error_set_pending_exception (&error);
4652 ICALL_EXPORT MonoString *
4653 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4655 MonoDomain *domain = mono_object_domain (assembly);
4658 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4663 ICALL_EXPORT MonoBoolean
4664 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4666 return assembly->assembly->ref_only;
4669 ICALL_EXPORT MonoString *
4670 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4672 MonoDomain *domain = mono_object_domain (assembly);
4674 return mono_string_new (domain, assembly->assembly->image->version);
4677 ICALL_EXPORT MonoReflectionMethod*
4678 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4681 MonoReflectionMethod *res = NULL;
4684 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4688 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4689 if (!mono_error_ok (&error))
4692 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4695 if (!mono_error_ok (&error))
4696 mono_error_set_pending_exception (&error);
4700 ICALL_EXPORT MonoReflectionModule*
4701 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4704 MonoReflectionModule *result = NULL;
4705 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4706 if (!mono_error_ok (&error))
4707 mono_error_set_pending_exception (&error);
4711 ICALL_EXPORT MonoArray*
4712 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4715 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4716 MonoArray *result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, table->rows, &error);
4717 if (mono_error_set_pending_exception (&error))
4722 for (i = 0; i < table->rows; ++i) {
4723 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4724 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4729 ICALL_EXPORT MonoString*
4730 ves_icall_System_Reflection_Assembly_GetAotId ()
4733 guint8 aotid_sum = 0;
4734 MonoDomain* domain = mono_domain_get ();
4736 if (!domain->entry_assembly || !domain->entry_assembly->image)
4739 guint8 (*aotid)[16] = &domain->entry_assembly->image->aotid;
4741 for (i = 0; i < 16; ++i)
4742 aotid_sum |= (*aotid)[i];
4747 return mono_string_new (domain, mono_guid_to_string((guint8*) aotid));
4751 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4753 static MonoMethod *create_version = NULL;
4757 mono_error_init (error);
4760 if (!create_version) {
4761 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4762 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4763 g_assert (create_version);
4764 mono_method_desc_free (desc);
4770 args [3] = &revision;
4771 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4772 return_val_if_nok (error, NULL);
4774 mono_runtime_invoke_checked (create_version, result, args, error);
4775 return_val_if_nok (error, NULL);
4780 ICALL_EXPORT MonoArray*
4781 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4785 MonoDomain *domain = mono_object_domain (assembly);
4787 static MonoMethod *create_culture = NULL;
4788 MonoImage *image = assembly->assembly->image;
4792 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4795 result = mono_array_new_checked (domain, mono_class_get_assembly_name_class (), count, &error);
4796 if (mono_error_set_pending_exception (&error))
4800 if (count > 0 && !create_culture) {
4801 MonoMethodDesc *desc = mono_method_desc_new (
4802 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4803 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4804 g_assert (create_culture);
4805 mono_method_desc_free (desc);
4808 for (i = 0; i < count; i++) {
4809 MonoObject *version;
4810 MonoReflectionAssemblyName *aname;
4811 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4813 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4815 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4816 domain, mono_class_get_assembly_name_class (), &error);
4817 if (mono_error_set_pending_exception (&error))
4820 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4822 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4823 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4824 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4825 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4826 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4827 aname->versioncompat = 1; /* SameMachine (default) */
4828 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4830 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4831 if (mono_error_set_pending_exception (&error))
4834 MONO_OBJECT_SETREF (aname, version, version);
4836 if (create_culture) {
4838 MonoBoolean assembly_ref = 1;
4839 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4840 args [1] = &assembly_ref;
4842 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4843 if (mono_error_set_pending_exception (&error))
4846 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4849 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4850 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4851 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4853 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4854 /* public key token isn't copied - the class library will
4855 automatically generate it from the public key if required */
4856 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4857 if (mono_error_set_pending_exception (&error))
4860 MONO_OBJECT_SETREF (aname, publicKey, pkey);
4861 memcpy (mono_array_addr (pkey, guint8, 0), pkey_ptr, pkey_len);
4863 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, &error);
4864 if (mono_error_set_pending_exception (&error))
4867 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4868 memcpy (mono_array_addr (keyToken, guint8, 0), pkey_ptr, pkey_len);
4871 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, &error);
4872 if (mono_error_set_pending_exception (&error))
4875 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
4878 /* note: this function doesn't return the codebase on purpose (i.e. it can
4879 be used under partial trust as path information isn't present). */
4881 mono_array_setref (result, i, aname);
4886 /* move this in some file in mono/util/ */
4888 g_concat_dir_and_file (const char *dir, const char *file)
4890 g_return_val_if_fail (dir != NULL, NULL);
4891 g_return_val_if_fail (file != NULL, NULL);
4894 * If the directory name doesn't have a / on the end, we need
4895 * to add one so we get a proper path to the file
4897 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4898 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4900 return g_strconcat (dir, file, NULL);
4904 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4907 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4909 guint32 cols [MONO_MANIFEST_SIZE];
4910 guint32 impl, file_idx;
4914 char *n = mono_string_to_utf8_checked (name, &error);
4915 if (mono_error_set_pending_exception (&error))
4918 for (i = 0; i < table->rows; ++i) {
4919 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4920 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4921 if (strcmp (val, n) == 0)
4925 if (i == table->rows)
4928 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4931 * this code should only be called after obtaining the
4932 * ResourceInfo and handling the other cases.
4934 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4935 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4937 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4942 module = assembly->assembly->image;
4945 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4946 if (mono_error_set_pending_exception (&error))
4948 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4950 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4953 ICALL_EXPORT gboolean
4954 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4957 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4959 guint32 cols [MONO_MANIFEST_SIZE];
4960 guint32 file_cols [MONO_FILE_SIZE];
4964 n = mono_string_to_utf8_checked (name, &error);
4965 if (mono_error_set_pending_exception (&error))
4967 for (i = 0; i < table->rows; ++i) {
4968 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4969 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4970 if (strcmp (val, n) == 0)
4974 if (i == table->rows)
4977 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4978 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4981 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4982 case MONO_IMPLEMENTATION_FILE:
4983 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4984 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4985 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4986 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4987 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4988 if (file_cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA)
4991 info->location = RESOURCE_LOCATION_EMBEDDED;
4994 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4995 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4996 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4997 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4998 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4999 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
5001 mono_set_pending_exception (ex);
5004 MonoReflectionAssembly *assm_obj;
5005 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
5007 mono_error_set_pending_exception (&error);
5010 MONO_OBJECT_SETREF (info, assembly, assm_obj);
5012 /* Obtain info recursively */
5013 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
5014 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
5017 case MONO_IMPLEMENTATION_EXP_TYPE:
5018 g_assert_not_reached ();
5026 ICALL_EXPORT MonoObject*
5027 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
5030 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
5031 MonoArray *result = NULL;
5036 /* check hash if needed */
5038 n = mono_string_to_utf8_checked (name, &error);
5039 if (mono_error_set_pending_exception (&error))
5042 for (i = 0; i < table->rows; ++i) {
5043 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5044 if (strcmp (val, n) == 0) {
5047 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5048 fn = mono_string_new (mono_object_domain (assembly), n);
5050 return (MonoObject*)fn;
5058 for (i = 0; i < table->rows; ++i) {
5059 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
5063 result = mono_array_new_checked (mono_object_domain (assembly), mono_defaults.string_class, count, &error);
5064 if (mono_error_set_pending_exception (&error))
5069 for (i = 0; i < table->rows; ++i) {
5070 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5071 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
5072 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
5073 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5078 return (MonoObject*)result;
5081 ICALL_EXPORT MonoArray*
5082 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5085 MonoDomain *domain = mono_domain_get();
5088 int i, j, file_count = 0;
5089 MonoImage **modules;
5090 guint32 module_count, real_module_count;
5091 MonoTableInfo *table;
5092 guint32 cols [MONO_FILE_SIZE];
5093 MonoImage *image = assembly->assembly->image;
5095 g_assert (image != NULL);
5096 g_assert (!assembly_is_dynamic (assembly->assembly));
5098 table = &image->tables [MONO_TABLE_FILE];
5099 file_count = table->rows;
5101 modules = image->modules;
5102 module_count = image->module_count;
5104 real_module_count = 0;
5105 for (i = 0; i < module_count; ++i)
5107 real_module_count ++;
5109 klass = mono_class_get_module_class ();
5110 res = mono_array_new_checked (domain, klass, 1 + real_module_count + file_count, &error);
5111 if (mono_error_set_pending_exception (&error))
5114 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5115 if (mono_error_set_pending_exception (&error))
5118 mono_array_setref (res, 0, image_obj);
5120 for (i = 0; i < module_count; ++i)
5122 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5123 if (mono_error_set_pending_exception (&error))
5125 mono_array_setref (res, j, rm);
5129 for (i = 0; i < file_count; ++i, ++j) {
5130 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5131 if (cols [MONO_FILE_FLAGS] & FILE_CONTAINS_NO_METADATA) {
5132 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5133 if (mono_error_set_pending_exception (&error))
5135 mono_array_setref (res, j, rm);
5138 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5140 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5141 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5144 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5145 if (mono_error_set_pending_exception (&error))
5147 mono_array_setref (res, j, rm);
5154 ICALL_EXPORT MonoReflectionMethod*
5155 ves_icall_GetCurrentMethod (void)
5157 MonoReflectionMethod *res = NULL;
5160 MonoMethod *m = mono_method_get_last_managed ();
5163 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5167 while (m->is_inflated)
5168 m = ((MonoMethodInflated*)m)->declaring;
5170 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5171 mono_error_set_pending_exception (&error);
5177 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5180 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5183 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5184 //method is inflated, we should inflate it on the other class
5185 MonoGenericContext ctx;
5186 ctx.method_inst = inflated->context.method_inst;
5187 ctx.class_inst = inflated->context.class_inst;
5188 if (klass->generic_class)
5189 ctx.class_inst = klass->generic_class->context.class_inst;
5190 else if (klass->generic_container)
5191 ctx.class_inst = klass->generic_container->context.class_inst;
5192 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5193 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5197 mono_class_setup_methods (method->klass);
5198 if (mono_class_has_failure (method->klass))
5200 for (i = 0; i < method->klass->method.count; ++i) {
5201 if (method->klass->methods [i] == method) {
5206 mono_class_setup_methods (klass);
5207 if (mono_class_has_failure (klass))
5209 g_assert (offset >= 0 && offset < klass->method.count);
5210 return klass->methods [offset];
5213 ICALL_EXPORT MonoReflectionMethod*
5214 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType_native (MonoMethod *method, MonoType *type, MonoBoolean generic_check)
5216 MonoReflectionMethod *res = NULL;
5219 if (type && generic_check) {
5220 klass = mono_class_from_mono_type (type);
5221 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5224 if (method->klass != klass) {
5225 method = mono_method_get_equivalent_method (method, klass);
5230 klass = mono_class_from_mono_type (type);
5232 klass = method->klass;
5233 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5234 mono_error_set_pending_exception (&error);
5238 ICALL_EXPORT MonoReflectionMethodBody*
5239 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5242 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5243 mono_error_set_pending_exception (&error);
5247 ICALL_EXPORT MonoReflectionAssembly*
5248 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5251 MonoReflectionAssembly *result;
5252 MonoMethod *dest = NULL;
5254 mono_stack_walk_no_il (get_executing, &dest);
5256 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5258 mono_error_set_pending_exception (&error);
5263 ICALL_EXPORT MonoReflectionAssembly*
5264 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5267 MonoReflectionAssembly *result;
5268 MonoDomain* domain = mono_domain_get ();
5270 if (!domain->entry_assembly)
5273 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5275 mono_error_set_pending_exception (&error);
5279 ICALL_EXPORT MonoReflectionAssembly*
5280 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5285 MonoReflectionAssembly *result;
5288 mono_stack_walk_no_il (get_executing, &dest);
5290 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5294 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5297 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5299 mono_error_set_pending_exception (&error);
5303 ICALL_EXPORT MonoStringHandle
5304 ves_icall_System_RuntimeType_getFullName (MonoReflectionTypeHandle object, gboolean full_name,
5305 gboolean assembly_qualified, MonoError *error)
5307 MonoDomain *domain = mono_object_domain (MONO_HANDLE_RAW (object));
5308 MonoType *type = MONO_HANDLE_RAW (object)->type;
5309 MonoTypeNameFormat format;
5310 MonoStringHandle res;
5314 format = assembly_qualified ?
5315 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5316 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5318 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5320 name = mono_type_get_name_full (type, format);
5322 return NULL_HANDLE_STRING;
5324 if (full_name && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
5326 return NULL_HANDLE_STRING;
5329 res = mono_string_new_handle (domain, name);
5336 vell_icall_RuntimeType_get_core_clr_security_level (MonoReflectionType *rfield)
5339 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5341 mono_class_init_checked (klass, &error);
5342 mono_error_set_pending_exception (&error);
5343 return mono_security_core_clr_class_level (klass);
5347 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5349 MonoClassField *field = rfield->field;
5350 return mono_security_core_clr_field_level (field, TRUE);
5354 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5356 MonoMethod *method = rfield->method;
5357 return mono_security_core_clr_method_level (method, TRUE);
5361 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)
5363 static MonoMethod *create_culture = NULL;
5367 const char *pkey_ptr;
5369 MonoBoolean assembly_ref = 0;
5371 mono_error_init (error);
5373 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5374 aname->major = name->major;
5375 aname->minor = name->minor;
5376 aname->build = name->build;
5377 aname->flags = name->flags;
5378 aname->revision = name->revision;
5379 aname->hashalg = name->hash_alg;
5380 aname->versioncompat = 1; /* SameMachine (default) */
5381 aname->processor_architecture = name->arch;
5383 if (by_default_version) {
5384 MonoObject *version;
5386 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5387 return_if_nok (error);
5389 MONO_OBJECT_SETREF (aname, version, version);
5393 if (absolute != NULL && *absolute != '\0') {
5394 const gchar *prepend = "file://";
5397 codebase = g_strdup (absolute);
5402 for (i = strlen (codebase) - 1; i >= 0; i--)
5403 if (codebase [i] == '\\')
5406 if (*codebase == '/' && *(codebase + 1) == '/') {
5409 prepend = "file:///";
5413 result = g_strconcat (prepend, codebase, NULL);
5419 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5423 if (!create_culture) {
5424 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5425 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5426 g_assert (create_culture);
5427 mono_method_desc_free (desc);
5430 if (name->culture) {
5431 args [0] = mono_string_new (domain, name->culture);
5432 args [1] = &assembly_ref;
5434 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5435 return_if_nok (error);
5437 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5440 if (name->public_key) {
5441 pkey_ptr = (char*)name->public_key;
5442 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5444 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, pkey_len, error);
5445 return_if_nok (error);
5446 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5447 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5448 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5449 } else if (default_publickey) {
5450 MonoArray *pkey = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5451 return_if_nok (error);
5452 MONO_OBJECT_SETREF (aname, publicKey, pkey);
5453 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5456 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5457 if (name->public_key_token [0]) {
5461 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 8, error);
5462 return_if_nok (error);
5464 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5465 p = mono_array_addr (keyToken, char, 0);
5467 for (i = 0, j = 0; i < 8; i++) {
5468 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5469 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5472 } else if (default_token) {
5473 MonoArray *keyToken = mono_array_new_checked (domain, mono_defaults.byte_class, 0, error);
5474 return_if_nok (error);
5475 MONO_OBJECT_SETREF (aname, keyToken, keyToken);
5479 ICALL_EXPORT MonoString *
5480 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5482 MonoDomain *domain = mono_object_domain (assembly);
5483 MonoAssembly *mass = assembly->assembly;
5487 name = mono_stringify_assembly_name (&mass->aname);
5488 res = mono_string_new (domain, name);
5494 ICALL_EXPORT MonoAssemblyName *
5495 ves_icall_System_Reflection_AssemblyName_GetNativeName (MonoAssembly *mass)
5497 return &mass->aname;
5501 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5505 MonoImageOpenStatus status = MONO_IMAGE_OK;
5508 MonoAssemblyName name;
5511 filename = mono_string_to_utf8_checked (fname, &error);
5512 if (mono_error_set_pending_exception (&error))
5515 dirname = g_path_get_dirname (filename);
5516 replace_shadow_path (mono_domain_get (), dirname, &filename);
5519 image = mono_image_open (filename, &status);
5525 if (status == MONO_IMAGE_IMAGE_INVALID)
5526 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5528 exc = mono_get_exception_file_not_found2 (NULL, fname);
5529 mono_set_pending_exception (exc);
5533 res = mono_assembly_fill_assembly_name (image, &name);
5535 mono_image_close (image);
5537 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5541 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5542 mono_error_set_pending_exception (&error);
5544 mono_image_close (image);
5548 ICALL_EXPORT MonoBoolean
5549 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5550 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5552 MonoBoolean result = FALSE;
5553 MonoDeclSecurityEntry entry;
5555 /* SecurityAction.RequestMinimum */
5556 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5557 *minimum = entry.blob;
5558 *minLength = entry.size;
5561 /* SecurityAction.RequestOptional */
5562 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5563 *optional = entry.blob;
5564 *optLength = entry.size;
5567 /* SecurityAction.RequestRefuse */
5568 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5569 *refused = entry.blob;
5570 *refLength = entry.size;
5578 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5580 guint32 attrs, visibility;
5582 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5583 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5584 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5587 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5593 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5595 MonoReflectionType *rt;
5598 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5601 mono_error_init (error);
5603 /* we start the count from 1 because we skip the special type <Module> */
5606 for (i = 1; i < tdef->rows; ++i) {
5607 if (mono_module_type_is_visible (tdef, image, i + 1))
5611 count = tdef->rows - 1;
5613 res = mono_array_new_checked (domain, mono_defaults.runtimetype_class, count, error);
5614 return_val_if_nok (error, NULL);
5615 *exceptions = mono_array_new_checked (domain, mono_defaults.exception_class, count, error);
5616 return_val_if_nok (error, NULL);
5618 for (i = 1; i < tdef->rows; ++i) {
5619 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5620 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5623 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5624 return_val_if_nok (error, NULL);
5626 mono_array_setref (res, count, rt);
5628 MonoException *ex = mono_error_convert_to_exception (error);
5629 mono_array_setref (*exceptions, count, ex);
5638 ICALL_EXPORT MonoArray*
5639 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5642 MonoArray *res = NULL;
5643 MonoArray *exceptions = NULL;
5644 MonoImage *image = NULL;
5645 MonoTableInfo *table = NULL;
5648 int i, len, ex_count;
5650 domain = mono_object_domain (assembly);
5652 g_assert (!assembly_is_dynamic (assembly->assembly));
5653 image = assembly->assembly->image;
5654 table = &image->tables [MONO_TABLE_FILE];
5655 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5656 if (mono_error_set_pending_exception (&error))
5659 /* Append data from all modules in the assembly */
5660 for (i = 0; i < table->rows; ++i) {
5661 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5662 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5667 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5668 if (mono_error_set_pending_exception (&error))
5672 /* Append the new types to the end of the array */
5673 if (mono_array_length (res2) > 0) {
5675 MonoArray *res3, *ex3;
5677 len1 = mono_array_length (res);
5678 len2 = mono_array_length (res2);
5680 res3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5681 if (mono_error_set_pending_exception (&error))
5683 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5684 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5687 ex3 = mono_array_new_checked (domain, mono_defaults.runtimetype_class, len1 + len2, &error);
5688 if (mono_error_set_pending_exception (&error))
5690 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5691 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5698 /* the ReflectionTypeLoadException must have all the types (Types property),
5699 * NULL replacing types which throws an exception. The LoaderException must
5700 * contain all exceptions for NULL items.
5703 len = mono_array_length (res);
5706 for (i = 0; i < len; i++) {
5707 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5711 klass = mono_type_get_class (t->type);
5712 if ((klass != NULL) && mono_class_has_failure (klass)) {
5713 /* keep the class in the list */
5714 list = g_list_append (list, klass);
5715 /* and replace Type with NULL */
5716 mono_array_setref (res, i, NULL);
5723 if (list || ex_count) {
5725 MonoException *exc = NULL;
5726 MonoArray *exl = NULL;
5727 int j, length = g_list_length (list) + ex_count;
5729 exl = mono_array_new_checked (domain, mono_defaults.exception_class, length, &error);
5730 if (mono_error_set_pending_exception (&error)) {
5734 /* Types for which mono_class_get_checked () succeeded */
5735 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5736 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5737 mono_array_setref (exl, i, exc);
5739 /* Types for which it don't */
5740 for (j = 0; j < mono_array_length (exceptions); ++j) {
5741 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5743 g_assert (i < length);
5744 mono_array_setref (exl, i, exc);
5751 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5752 if (!is_ok (&error)) {
5753 mono_error_set_pending_exception (&error);
5756 mono_set_pending_exception (exc);
5764 ves_icall_Mono_RuntimeMarshal_FreeAssemblyName (MonoAssemblyName *aname)
5766 mono_assembly_name_free (aname);
5769 ICALL_EXPORT gboolean
5770 ves_icall_System_Reflection_AssemblyName_ParseAssemblyName (const char *name, MonoAssemblyName *aname, gboolean *is_version_definited, gboolean *is_token_defined)
5772 *is_version_definited = *is_token_defined = FALSE;
5774 return mono_assembly_name_parse_full (name, aname, TRUE, is_version_definited, is_token_defined);
5777 ICALL_EXPORT MonoReflectionType*
5778 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5781 MonoReflectionType *ret;
5782 MonoDomain *domain = mono_object_domain (module);
5785 g_assert (module->image);
5787 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5788 /* These images do not have a global type */
5791 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5792 if (!mono_error_ok (&error)) {
5793 mono_error_set_pending_exception (&error);
5797 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5798 if (!mono_error_ok (&error)) {
5799 mono_error_set_pending_exception (&error);
5807 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5809 /*if (module->image)
5810 mono_image_close (module->image);*/
5813 ICALL_EXPORT MonoString*
5814 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5816 MonoDomain *domain = mono_object_domain (module);
5818 g_assert (module->image);
5819 return mono_string_new (domain, module->image->guid);
5822 ICALL_EXPORT gpointer
5823 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5826 if (module->image && module->image->is_module_handle)
5827 return module->image->raw_data;
5830 return (gpointer) (-1);
5834 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5836 if (image_is_dynamic (image)) {
5837 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5838 *pe_kind = dyn->pe_kind;
5839 *machine = dyn->machine;
5842 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5843 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5848 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5850 return (image->md_version_major << 16) | (image->md_version_minor);
5853 ICALL_EXPORT MonoArray*
5854 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5857 MonoArray *exceptions;
5860 if (!module->image) {
5861 MonoArray *arr = mono_array_new_checked (mono_object_domain (module), mono_defaults.runtimetype_class, 0, &error);
5862 mono_error_set_pending_exception (&error);
5867 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5868 if (mono_error_set_pending_exception (&error))
5871 for (i = 0; i < mono_array_length (exceptions); ++i) {
5872 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5874 mono_set_pending_exception (ex);
5883 mono_memberref_is_method (MonoImage *image, guint32 token)
5885 if (!image_is_dynamic (image)) {
5886 guint32 cols [MONO_MEMBERREF_SIZE];
5888 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5889 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5890 mono_metadata_decode_blob_size (sig, &sig);
5891 return (*sig != 0x6);
5894 MonoClass *handle_class;
5896 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL, &error)) {
5897 mono_error_cleanup (&error); /* just probing, ignore error */
5901 return mono_defaults.methodhandle_class == handle_class;
5906 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5909 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5910 mono_array_addr (type_args, MonoType*, 0));
5912 context->class_inst = NULL;
5914 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5915 mono_array_addr (method_args, MonoType*, 0));
5917 context->method_inst = NULL;
5920 ICALL_EXPORT MonoType*
5921 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5924 int table = mono_metadata_token_table (token);
5925 int index = mono_metadata_token_index (token);
5926 MonoGenericContext context;
5929 *resolve_error = ResolveTokenError_Other;
5931 /* Validate token */
5932 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5933 (table != MONO_TABLE_TYPESPEC)) {
5934 *resolve_error = ResolveTokenError_BadTable;
5938 if (image_is_dynamic (image)) {
5939 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5940 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5941 mono_error_cleanup (&error);
5942 return klass ? &klass->byval_arg : NULL;
5945 init_generic_context_from_args (&context, type_args, method_args);
5946 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
5947 mono_error_cleanup (&error);
5948 return klass ? &klass->byval_arg : NULL;
5951 if ((index <= 0) || (index > image->tables [table].rows)) {
5952 *resolve_error = ResolveTokenError_OutOfRange;
5956 init_generic_context_from_args (&context, type_args, method_args);
5957 klass = mono_class_get_checked (image, token, &error);
5959 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5960 if (!mono_error_ok (&error)) {
5961 mono_error_set_pending_exception (&error);
5966 return &klass->byval_arg;
5971 ICALL_EXPORT MonoMethod*
5972 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5975 int table = mono_metadata_token_table (token);
5976 int index = mono_metadata_token_index (token);
5977 MonoGenericContext context;
5980 *resolve_error = ResolveTokenError_Other;
5982 /* Validate token */
5983 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5984 (table != MONO_TABLE_MEMBERREF)) {
5985 *resolve_error = ResolveTokenError_BadTable;
5989 if (image_is_dynamic (image)) {
5990 if (table == MONO_TABLE_METHOD) {
5991 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
5992 mono_error_cleanup (&error);
5996 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5997 *resolve_error = ResolveTokenError_BadTable;
6001 init_generic_context_from_args (&context, type_args, method_args);
6002 method = (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6003 mono_error_cleanup (&error);
6007 if ((index <= 0) || (index > image->tables [table].rows)) {
6008 *resolve_error = ResolveTokenError_OutOfRange;
6011 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
6012 *resolve_error = ResolveTokenError_BadTable;
6016 init_generic_context_from_args (&context, type_args, method_args);
6017 method = mono_get_method_checked (image, token, NULL, &context, &error);
6018 mono_error_set_pending_exception (&error);
6023 ICALL_EXPORT MonoString*
6024 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6027 int index = mono_metadata_token_index (token);
6029 *resolve_error = ResolveTokenError_Other;
6031 /* Validate token */
6032 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
6033 *resolve_error = ResolveTokenError_BadTable;
6037 if (image_is_dynamic (image)) {
6038 MonoString * result = (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6039 mono_error_cleanup (&error);
6043 if ((index <= 0) || (index >= image->heap_us.size)) {
6044 *resolve_error = ResolveTokenError_OutOfRange;
6048 /* FIXME: What to do if the index points into the middle of a string ? */
6050 MonoString *result = mono_ldstr_checked (mono_domain_get (), image, index, &error);
6051 mono_error_set_pending_exception (&error);
6055 ICALL_EXPORT MonoClassField*
6056 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
6060 int table = mono_metadata_token_table (token);
6061 int index = mono_metadata_token_index (token);
6062 MonoGenericContext context;
6063 MonoClassField *field;
6065 *resolve_error = ResolveTokenError_Other;
6067 /* Validate token */
6068 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
6069 *resolve_error = ResolveTokenError_BadTable;
6073 if (image_is_dynamic (image)) {
6074 if (table == MONO_TABLE_FIELD) {
6075 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL, &error);
6076 mono_error_cleanup (&error);
6080 if (mono_memberref_is_method (image, token)) {
6081 *resolve_error = ResolveTokenError_BadTable;
6085 init_generic_context_from_args (&context, type_args, method_args);
6086 field = (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context, &error);
6087 mono_error_cleanup (&error);
6091 if ((index <= 0) || (index > image->tables [table].rows)) {
6092 *resolve_error = ResolveTokenError_OutOfRange;
6095 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
6096 *resolve_error = ResolveTokenError_BadTable;
6100 init_generic_context_from_args (&context, type_args, method_args);
6101 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6102 mono_error_set_pending_exception (&error);
6108 ICALL_EXPORT MonoObject*
6109 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6113 int table = mono_metadata_token_table (token);
6115 *error = ResolveTokenError_Other;
6118 case MONO_TABLE_TYPEDEF:
6119 case MONO_TABLE_TYPEREF:
6120 case MONO_TABLE_TYPESPEC: {
6121 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6123 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6124 mono_error_set_pending_exception (&merror);
6131 case MONO_TABLE_METHOD:
6132 case MONO_TABLE_METHODSPEC: {
6133 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6135 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6136 mono_error_set_pending_exception (&merror);
6142 case MONO_TABLE_FIELD: {
6143 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6145 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6146 mono_error_set_pending_exception (&merror);
6152 case MONO_TABLE_MEMBERREF:
6153 if (mono_memberref_is_method (image, token)) {
6154 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6156 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6157 mono_error_set_pending_exception (&merror);
6164 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6166 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6167 mono_error_set_pending_exception (&merror);
6176 *error = ResolveTokenError_BadTable;
6182 ICALL_EXPORT MonoArray*
6183 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *resolve_error)
6186 int table = mono_metadata_token_table (token);
6187 int idx = mono_metadata_token_index (token);
6188 MonoTableInfo *tables = image->tables;
6193 *resolve_error = ResolveTokenError_OutOfRange;
6195 /* FIXME: Support other tables ? */
6196 if (table != MONO_TABLE_STANDALONESIG)
6199 if (image_is_dynamic (image))
6202 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6205 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6207 ptr = mono_metadata_blob_heap (image, sig);
6208 len = mono_metadata_decode_blob_size (ptr, &ptr);
6210 res = mono_array_new_checked (mono_domain_get (), mono_defaults.byte_class, len, &error);
6211 if (mono_error_set_pending_exception (&error))
6213 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6217 ICALL_EXPORT MonoReflectionType*
6218 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6221 MonoReflectionType *ret;
6223 int isbyref = 0, rank;
6225 char *str = mono_string_to_utf8_checked (smodifiers, &error);
6226 if (mono_error_set_pending_exception (&error))
6229 klass = mono_class_from_mono_type (tb->type.type);
6231 /* logic taken from mono_reflection_parse_type(): keep in sync */
6235 if (isbyref) { /* only one level allowed by the spec */
6244 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6245 mono_error_set_pending_exception (&error);
6249 klass = mono_ptr_class_get (&klass->byval_arg);
6250 mono_class_init (klass);
6261 else if (*p != '*') { /* '*' means unknown lower bound */
6272 klass = mono_array_class_get (klass, rank);
6273 mono_class_init (klass);
6282 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6283 mono_error_set_pending_exception (&error);
6288 ICALL_EXPORT MonoBoolean
6289 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6295 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6301 check_for_invalid_type (MonoClass *klass, MonoError *error)
6306 mono_error_init (error);
6308 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6311 name = mono_type_get_full_name (klass);
6312 str = mono_string_new (mono_domain_get (), name);
6314 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6317 ICALL_EXPORT MonoReflectionType *
6318 ves_icall_RuntimeType_make_array_type (MonoReflectionType *type, int rank)
6321 MonoReflectionType *ret;
6322 MonoClass *klass, *aklass;
6324 klass = mono_class_from_mono_type (type->type);
6325 check_for_invalid_type (klass, &error);
6326 mono_error_set_pending_exception (&error);
6328 if (rank == 0) //single dimentional array
6329 aklass = mono_array_class_get (klass, 1);
6331 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6333 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6334 mono_error_set_pending_exception (&error);
6339 ICALL_EXPORT MonoReflectionType *
6340 ves_icall_RuntimeType_make_byref_type (MonoReflectionType *type)
6343 MonoReflectionType *ret;
6346 klass = mono_class_from_mono_type (type->type);
6347 mono_class_init_checked (klass, &error);
6348 if (mono_error_set_pending_exception (&error))
6351 check_for_invalid_type (klass, &error);
6352 if (mono_error_set_pending_exception (&error))
6355 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6356 mono_error_set_pending_exception (&error);
6361 ICALL_EXPORT MonoReflectionType *
6362 ves_icall_RuntimeType_MakePointerType (MonoReflectionType *type)
6365 MonoReflectionType *ret;
6366 MonoClass *klass, *pklass;
6368 klass = mono_class_from_mono_type (type->type);
6369 mono_class_init_checked (klass, &error);
6370 if (mono_error_set_pending_exception (&error))
6372 check_for_invalid_type (klass, &error);
6373 if (mono_error_set_pending_exception (&error))
6376 pklass = mono_ptr_class_get (type->type);
6378 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6379 mono_error_set_pending_exception (&error);
6384 ICALL_EXPORT MonoObject *
6385 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6386 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6389 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6390 MonoObject *delegate;
6392 MonoMethod *method = info->method;
6394 mono_class_init_checked (delegate_class, &error);
6395 if (mono_error_set_pending_exception (&error))
6398 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6399 /* FIXME improve this exception message */
6400 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6402 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6403 mono_error_set_pending_exception (&error);
6407 if (mono_security_core_clr_enabled ()) {
6408 if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
6409 if (throwOnBindFailure)
6410 mono_error_set_pending_exception (&error);
6412 mono_error_cleanup (&error);
6417 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6418 if (mono_error_set_pending_exception (&error))
6421 if (method_is_dynamic (method)) {
6422 /* Creating a trampoline would leak memory */
6423 func = mono_compile_method_checked (method, &error);
6424 if (mono_error_set_pending_exception (&error))
6427 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6428 method = mono_object_get_virtual_method (target, method);
6429 gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
6430 if (mono_error_set_pending_exception (&error))
6432 func = mono_create_ftnptr (mono_domain_get (), trampoline);
6435 mono_delegate_ctor_with_method (delegate, target, func, method, &error);
6436 if (mono_error_set_pending_exception (&error))
6441 ICALL_EXPORT MonoMulticastDelegate *
6442 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6445 MonoMulticastDelegate *ret;
6447 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6449 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6450 if (mono_error_set_pending_exception (&error))
6453 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6458 ICALL_EXPORT MonoReflectionMethod*
6459 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6461 MonoReflectionMethod *ret = NULL;
6463 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6464 mono_error_set_pending_exception (&error);
6470 static inline gint32
6471 mono_array_get_byte_length (MonoArray *array)
6477 klass = array->obj.vtable->klass;
6479 if (array->bounds == NULL)
6480 length = array->max_length;
6483 for (i = 0; i < klass->rank; ++ i)
6484 length *= array->bounds [i].length;
6487 switch (klass->element_class->byval_arg.type) {
6490 case MONO_TYPE_BOOLEAN:
6494 case MONO_TYPE_CHAR:
6502 return length * sizeof (gpointer);
6513 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6515 return mono_array_get_byte_length (array);
6519 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6521 return mono_array_get (array, gint8, idx);
6525 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6527 mono_array_set (array, gint8, idx, value);
6530 ICALL_EXPORT MonoBoolean
6531 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6533 guint8 *src_buf, *dest_buf;
6536 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6540 g_assert (count >= 0);
6542 /* This is called directly from the class libraries without going through the managed wrapper */
6543 MONO_CHECK_ARG_NULL (src, FALSE);
6544 MONO_CHECK_ARG_NULL (dest, FALSE);
6546 /* watch out for integer overflow */
6547 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6550 src_buf = (guint8 *)src->vector + src_offset;
6551 dest_buf = (guint8 *)dest->vector + dest_offset;
6554 memcpy (dest_buf, src_buf, count);
6556 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6561 #ifndef DISABLE_REMOTING
6562 ICALL_EXPORT MonoObject *
6563 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6566 MonoDomain *domain = mono_object_domain (this_obj);
6568 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6569 MonoTransparentProxy *tp;
6573 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6574 if (mono_error_set_pending_exception (&error))
6577 tp = (MonoTransparentProxy*) res;
6579 MONO_OBJECT_SETREF (tp, rp, rp);
6580 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6581 klass = mono_class_from_mono_type (type);
6583 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6584 mono_class_setup_vtable (klass);
6585 if (mono_class_has_failure (klass)) {
6586 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6590 tp->custom_type_info = (mono_object_isinst_checked (this_obj, mono_defaults.iremotingtypeinfo_class, &error) != NULL);
6591 if (mono_error_set_pending_exception (&error))
6593 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6594 if (mono_error_set_pending_exception (&error))
6597 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp, &error);
6598 if (mono_error_set_pending_exception (&error))
6603 ICALL_EXPORT MonoReflectionType *
6604 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6607 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6608 mono_error_set_pending_exception (&error);
6614 /* System.Environment */
6617 ves_icall_System_Environment_get_UserName (void)
6619 /* using glib is more portable */
6620 return mono_string_new (mono_domain_get (), g_get_user_name ());
6624 ICALL_EXPORT MonoString *
6625 ves_icall_System_Environment_get_MachineName (void)
6627 #if defined (HOST_WIN32)
6632 len = MAX_COMPUTERNAME_LENGTH + 1;
6633 buf = g_new (gunichar2, len);
6636 if (GetComputerName (buf, (PDWORD) &len)) {
6638 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6639 mono_error_set_pending_exception (&error);
6644 #elif !defined(DISABLE_SOCKETS)
6648 #if defined _SC_HOST_NAME_MAX
6649 n = sysconf (_SC_HOST_NAME_MAX);
6653 buf = g_malloc (n+1);
6655 if (gethostname (buf, n) == 0){
6657 result = mono_string_new (mono_domain_get (), buf);
6664 return mono_string_new (mono_domain_get (), "mono");
6669 ves_icall_System_Environment_get_Platform (void)
6671 #if defined (TARGET_WIN32)
6674 #elif defined(__MACH__)
6677 // Notice that the value is hidden from user code, and only exposed
6678 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6679 // define and making assumptions based on Unix/128/4 values before there
6680 // was a MacOS define. Lots of code would assume that not-Unix meant
6681 // Windows, but in this case, it would be OSX.
6690 ICALL_EXPORT MonoString *
6691 ves_icall_System_Environment_get_NewLine (void)
6693 #if defined (HOST_WIN32)
6694 return mono_string_new (mono_domain_get (), "\r\n");
6696 return mono_string_new (mono_domain_get (), "\n");
6700 ICALL_EXPORT MonoBoolean
6701 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6703 #if SIZEOF_VOID_P == 8
6707 gboolean isWow64Process = FALSE;
6708 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6709 return (MonoBoolean)isWow64Process;
6711 #elif defined(HAVE_SYS_UTSNAME_H)
6712 struct utsname name;
6714 if (uname (&name) >= 0) {
6715 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6722 ICALL_EXPORT MonoString *
6723 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6732 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6733 if (mono_error_set_pending_exception (&error))
6735 value = g_getenv (utf8_name);
6742 return mono_string_new (mono_domain_get (), value);
6746 * There is no standard way to get at environ.
6749 #ifndef __MINGW32_VERSION
6750 #if defined(__APPLE__)
6751 #if defined (TARGET_OSX)
6752 /* Apple defines this in crt_externs.h but doesn't provide that header for
6753 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6754 * in fact exist on all implementations (so far)
6756 gchar ***_NSGetEnviron(void);
6757 #define environ (*_NSGetEnviron())
6759 static char *mono_environ[1] = { NULL };
6760 #define environ mono_environ
6761 #endif /* defined (TARGET_OSX) */
6769 ICALL_EXPORT MonoArray *
6770 ves_icall_System_Environment_GetCoomandLineArgs (void)
6773 MonoArray *result = mono_runtime_get_main_args_checked (&error);
6774 mono_error_set_pending_exception (&error);
6778 ICALL_EXPORT MonoArray *
6779 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6791 env_strings = GetEnvironmentStrings();
6794 env_string = env_strings;
6795 while (*env_string != '\0') {
6796 /* weird case that MS seems to skip */
6797 if (*env_string != '=')
6799 while (*env_string != '\0')
6805 domain = mono_domain_get ();
6806 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6807 if (mono_error_set_pending_exception (&error))
6812 env_string = env_strings;
6813 while (*env_string != '\0') {
6814 /* weird case that MS seems to skip */
6815 if (*env_string != '=') {
6816 equal_str = wcschr(env_string, '=');
6817 g_assert(equal_str);
6819 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6820 if (mono_error_set_pending_exception (&error))
6823 mono_array_setref (names, n, str);
6826 while (*env_string != '\0')
6831 FreeEnvironmentStrings (env_strings);
6845 for (e = environ; *e != 0; ++ e)
6848 domain = mono_domain_get ();
6849 names = mono_array_new_checked (domain, mono_defaults.string_class, n, &error);
6850 if (mono_error_set_pending_exception (&error))
6854 for (e = environ; *e != 0; ++ e) {
6855 parts = g_strsplit (*e, "=", 2);
6857 str = mono_string_new (domain, *parts);
6858 mono_array_setref (names, n, str);
6871 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6874 gunichar2 *utf16_name, *utf16_value;
6876 gchar *utf8_name, *utf8_value;
6881 utf16_name = mono_string_to_utf16 (name);
6882 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6883 SetEnvironmentVariable (utf16_name, NULL);
6884 g_free (utf16_name);
6888 utf16_value = mono_string_to_utf16 (value);
6890 SetEnvironmentVariable (utf16_name, utf16_value);
6892 g_free (utf16_name);
6893 g_free (utf16_value);
6895 utf8_name = mono_string_to_utf8_checked (name, &error); /* FIXME: this should be ascii */
6896 if (mono_error_set_pending_exception (&error))
6899 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6900 g_unsetenv (utf8_name);
6905 utf8_value = mono_string_to_utf8_checked (value, &error);
6906 if (!mono_error_ok (&error)) {
6908 mono_error_set_pending_exception (&error);
6911 g_setenv (utf8_name, utf8_value, TRUE);
6914 g_free (utf8_value);
6919 ves_icall_System_Environment_Exit (int result)
6921 mono_environment_exitcode_set (result);
6923 /* FIXME: There are some cleanup hangs that should be worked out, but
6924 * if the program is going to exit, everything will be cleaned up when
6925 * NaCl exits anyway.
6927 #ifndef __native_client__
6928 if (!mono_runtime_try_shutdown ())
6929 mono_thread_exit ();
6931 /* Suspend all managed threads since the runtime is going away */
6932 mono_thread_suspend_all_other_threads ();
6934 mono_runtime_quit ();
6937 /* we may need to do some cleanup here... */
6941 ICALL_EXPORT MonoString*
6942 ves_icall_System_Environment_GetGacPath (void)
6944 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6947 ICALL_EXPORT MonoString*
6948 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6950 #if defined (HOST_WIN32)
6951 #ifndef CSIDL_FLAG_CREATE
6952 #define CSIDL_FLAG_CREATE 0x8000
6955 WCHAR path [MAX_PATH];
6956 /* Create directory if no existing */
6957 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6962 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6963 mono_error_set_pending_exception (&error);
6967 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6969 return mono_string_new (mono_domain_get (), "");
6972 ICALL_EXPORT MonoArray *
6973 ves_icall_System_Environment_GetLogicalDrives (void)
6976 gunichar2 buf [256], *ptr, *dname;
6978 guint initial_size = 127, size = 128;
6981 MonoString *drivestr;
6982 MonoDomain *domain = mono_domain_get ();
6988 while (size > initial_size) {
6989 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6990 if (size > initial_size) {
6993 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6994 initial_size = size;
7008 result = mono_array_new_checked (domain, mono_defaults.string_class, ndrives, &error);
7009 if (mono_error_set_pending_exception (&error))
7016 while (*u16) { u16++; len ++; }
7017 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
7018 if (mono_error_set_pending_exception (&error))
7021 mono_array_setref (result, ndrives++, drivestr);
7032 ICALL_EXPORT MonoString *
7033 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
7036 gunichar2 volume_name [MAX_PATH + 1];
7038 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
7040 MonoString *result = mono_string_from_utf16_checked (volume_name, &error);
7041 mono_error_set_pending_exception (&error);
7045 ICALL_EXPORT MonoString *
7046 ves_icall_System_Environment_InternalGetHome (void)
7048 return mono_string_new (mono_domain_get (), g_get_home_dir ());
7051 static const char *encodings [] = {
7053 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
7054 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
7055 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
7057 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
7058 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
7059 "x_unicode_2_0_utf_7",
7061 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
7062 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
7064 "utf_16", "UTF_16LE", "ucs_2", "unicode",
7067 "unicodefffe", "utf_16be",
7074 * Returns the internal codepage, if the value of "int_code_page" is
7075 * 1 at entry, and we can not compute a suitable code page number,
7076 * returns the code page as a string
7078 ICALL_EXPORT MonoString*
7079 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
7084 char *codepage = NULL;
7086 int want_name = *int_code_page;
7089 *int_code_page = -1;
7091 g_get_charset (&cset);
7092 c = codepage = strdup (cset);
7093 for (c = codepage; *c; c++){
7094 if (isascii (*c) && isalpha (*c))
7099 /* g_print ("charset: %s\n", cset); */
7101 /* handle some common aliases */
7104 for (i = 0; p != 0; ){
7107 p = encodings [++i];
7110 if (strcmp (p, codepage) == 0){
7111 *int_code_page = code;
7114 p = encodings [++i];
7117 if (strstr (codepage, "utf_8") != NULL)
7118 *int_code_page |= 0x10000000;
7121 if (want_name && *int_code_page == -1)
7122 return mono_string_new (mono_domain_get (), cset);
7127 ICALL_EXPORT MonoBoolean
7128 ves_icall_System_Environment_get_HasShutdownStarted (void)
7130 if (mono_runtime_is_shutting_down ())
7133 if (mono_domain_is_unloading (mono_domain_get ()))
7140 ves_icall_System_Environment_BroadcastSettingChange (void)
7143 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
7149 ves_icall_System_Environment_get_TickCount (void)
7151 /* this will overflow after ~24 days */
7152 return (gint32) (mono_msec_boottime () & 0xffffffff);
7156 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7161 #ifndef DISABLE_REMOTING
7162 ICALL_EXPORT MonoBoolean
7163 ves_icall_IsTransparentProxy (MonoObject *proxy)
7168 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7174 ICALL_EXPORT MonoReflectionMethod *
7175 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7176 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7178 MonoReflectionMethod *ret = NULL;
7183 MonoMethod **vtable;
7184 MonoMethod *res = NULL;
7186 MONO_CHECK_ARG_NULL (rtype, NULL);
7187 MONO_CHECK_ARG_NULL (rmethod, NULL);
7189 method = rmethod->method;
7190 klass = mono_class_from_mono_type (rtype->type);
7191 mono_class_init_checked (klass, &error);
7192 if (mono_error_set_pending_exception (&error))
7195 if (MONO_CLASS_IS_INTERFACE (klass))
7198 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7201 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7202 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7208 mono_class_setup_vtable (klass);
7209 vtable = klass->vtable;
7211 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7212 gboolean variance_used = FALSE;
7213 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7214 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7216 res = vtable [offs + method->slot];
7218 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7221 if (method->slot != -1)
7222 res = vtable [method->slot];
7228 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7229 mono_error_set_pending_exception (&error);
7234 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7240 klass = mono_class_from_mono_type (type->type);
7241 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7242 if (!is_ok (&error)) {
7243 mono_error_set_pending_exception (&error);
7247 mono_vtable_set_is_remote (vtable, enable);
7250 #else /* DISABLE_REMOTING */
7253 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7255 g_assert_not_reached ();
7260 ICALL_EXPORT MonoObject *
7261 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7268 domain = mono_object_domain (type);
7269 klass = mono_class_from_mono_type (type->type);
7270 mono_class_init_checked (klass, &error);
7271 if (mono_error_set_pending_exception (&error))
7274 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7275 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7279 if (klass->rank >= 1) {
7280 g_assert (klass->rank == 1);
7281 ret = (MonoObject *) mono_array_new_checked (domain, klass->element_class, 0, &error);
7282 mono_error_set_pending_exception (&error);
7285 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7286 if (!is_ok (&error)) {
7287 mono_error_set_pending_exception (&error);
7290 /* Bypass remoting object creation check */
7291 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7292 mono_error_set_pending_exception (&error);
7298 ICALL_EXPORT MonoString *
7299 ves_icall_System_IO_get_temp_path (void)
7301 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7304 #ifndef PLATFORM_NO_DRIVEINFO
7305 ICALL_EXPORT MonoBoolean
7306 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7307 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7311 ULARGE_INTEGER wapi_free_bytes_avail;
7312 ULARGE_INTEGER wapi_total_number_of_bytes;
7313 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7315 *error = ERROR_SUCCESS;
7316 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7317 &wapi_total_number_of_free_bytes);
7320 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7321 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7322 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7324 *free_bytes_avail = 0;
7325 *total_number_of_bytes = 0;
7326 *total_number_of_free_bytes = 0;
7327 *error = GetLastError ();
7333 ICALL_EXPORT guint32
7334 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7336 return GetDriveType (mono_string_chars (root_path_name));
7340 ICALL_EXPORT gpointer
7341 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7344 gpointer result = mono_compile_method_checked (method, &error);
7345 mono_error_set_pending_exception (&error);
7349 ICALL_EXPORT MonoString *
7350 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7355 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7357 #if defined (HOST_WIN32)
7358 /* Avoid mixing '/' and '\\' */
7361 for (i = strlen (path) - 1; i >= 0; i--)
7362 if (path [i] == '/')
7366 mcpath = mono_string_new (mono_domain_get (), path);
7372 /* this is an icall */
7374 get_bundled_app_config (void)
7377 const gchar *app_config;
7380 gchar *config_file_name, *config_file_path;
7381 gsize len, config_file_path_length, config_ext_length;
7384 domain = mono_domain_get ();
7385 file = domain->setup->configuration_file;
7386 if (!file || file->length == 0)
7389 // Retrieve config file and remove the extension
7390 config_file_name = mono_string_to_utf8_checked (file, &error);
7391 if (mono_error_set_pending_exception (&error))
7393 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7394 if (!config_file_path)
7395 config_file_path = config_file_name;
7397 config_file_path_length = strlen (config_file_path);
7398 config_ext_length = strlen (".config");
7399 if (config_file_path_length <= config_ext_length)
7402 len = config_file_path_length - config_ext_length;
7403 module = (gchar *)g_malloc0 (len + 1);
7404 memcpy (module, config_file_path, len);
7405 // Get the config file from the module name
7406 app_config = mono_config_string_for_assembly_file (module);
7409 if (config_file_name != config_file_path)
7410 g_free (config_file_name);
7411 g_free (config_file_path);
7416 return mono_string_new (mono_domain_get (), app_config);
7420 get_bundled_machine_config (void)
7422 const gchar *machine_config;
7424 machine_config = mono_get_machine_config ();
7426 if (!machine_config)
7429 return mono_string_new (mono_domain_get (), machine_config);
7432 ICALL_EXPORT MonoString *
7433 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7438 path = g_path_get_dirname (mono_get_config_dir ());
7440 #if defined (HOST_WIN32)
7441 /* Avoid mixing '/' and '\\' */
7444 for (i = strlen (path) - 1; i >= 0; i--)
7445 if (path [i] == '/')
7449 ipath = mono_string_new (mono_domain_get (), path);
7455 ICALL_EXPORT gboolean
7456 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7458 MonoPEResourceDataEntry *entry;
7461 if (!assembly || !result || !size)
7466 image = assembly->assembly->image;
7467 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7471 *result = mono_image_rva_map (image, entry->rde_data_offset);
7476 *size = entry->rde_size;
7481 ICALL_EXPORT MonoBoolean
7482 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7484 return mono_is_debugger_attached ();
7487 ICALL_EXPORT MonoBoolean
7488 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7490 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7491 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7497 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7499 if (mono_get_runtime_callbacks ()->debug_log)
7500 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7504 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7506 #if defined (HOST_WIN32)
7507 OutputDebugString (mono_string_chars (message));
7509 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7513 /* Only used for value types */
7514 ICALL_EXPORT MonoObject *
7515 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7522 domain = mono_object_domain (type);
7523 klass = mono_class_from_mono_type (type->type);
7524 mono_class_init_checked (klass, &error);
7525 if (mono_error_set_pending_exception (&error))
7528 if (mono_class_is_nullable (klass))
7529 /* No arguments -> null */
7532 result = mono_object_new_checked (domain, klass, &error);
7533 mono_error_set_pending_exception (&error);
7537 ICALL_EXPORT MonoReflectionMethod *
7538 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7540 MonoReflectionMethod *ret = NULL;
7543 MonoClass *klass, *parent;
7544 MonoGenericContext *generic_inst = NULL;
7545 MonoMethod *method = m->method;
7546 MonoMethod *result = NULL;
7549 if (method->klass == NULL)
7552 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7553 MONO_CLASS_IS_INTERFACE (method->klass) ||
7554 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7557 slot = mono_method_get_vtable_slot (method);
7561 klass = method->klass;
7562 if (klass->generic_class) {
7563 generic_inst = mono_class_get_context (klass);
7564 klass = klass->generic_class->container_class;
7568 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7569 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7570 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7571 or klass is the generic container class and generic_inst is the instantiation.
7573 when we go to the parent, if the parent is an open constructed type, we need to
7574 replace the type parameters by the definitions from the generic_inst, and then take it
7575 apart again into the klass and the generic_inst.
7577 For cases like this:
7578 class C<T> : B<T, int> {
7579 public override void Foo () { ... }
7581 class B<U,V> : A<HashMap<U,V>> {
7582 public override void Foo () { ... }
7585 public virtual void Foo () { ... }
7588 if at each iteration the parent isn't open, we can skip inflating it. if at some
7589 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7592 MonoGenericContext *parent_inst = NULL;
7593 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7594 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7595 if (!mono_error_ok (&error)) {
7596 mono_error_set_pending_exception (&error);
7600 if (parent->generic_class) {
7601 parent_inst = mono_class_get_context (parent);
7602 parent = parent->generic_class->container_class;
7605 mono_class_setup_vtable (parent);
7606 if (parent->vtable_size <= slot)
7609 generic_inst = parent_inst;
7612 klass = klass->parent;
7615 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7616 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7617 if (!mono_error_ok (&error)) {
7618 mono_error_set_pending_exception (&error);
7622 generic_inst = NULL;
7624 if (klass->generic_class) {
7625 generic_inst = mono_class_get_context (klass);
7626 klass = klass->generic_class->container_class;
7632 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7633 if (!mono_error_ok (&error)) {
7634 mono_error_set_pending_exception (&error);
7639 if (klass == method->klass)
7642 /*This is possible if definition == FALSE.
7643 * Do it here to be really sure we don't read invalid memory.
7645 if (slot >= klass->vtable_size)
7648 mono_class_setup_vtable (klass);
7650 result = klass->vtable [slot];
7651 if (result == NULL) {
7652 /* It is an abstract method */
7653 gpointer iter = NULL;
7654 while ((result = mono_class_get_methods (klass, &iter)))
7655 if (result->slot == slot)
7662 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7663 mono_error_set_pending_exception (&error);
7667 ICALL_EXPORT MonoString*
7668 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7670 MonoMethod *method = m->method;
7672 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7677 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7679 iter->sig = *(MonoMethodSignature**)argsp;
7681 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7682 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7685 /* FIXME: it's not documented what start is exactly... */
7689 iter->args = argsp + sizeof (gpointer);
7691 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7693 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7696 ICALL_EXPORT MonoTypedRef
7697 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7699 guint32 i, arg_size;
7703 i = iter->sig->sentinelpos + iter->next_arg;
7705 g_assert (i < iter->sig->param_count);
7707 res.type = iter->sig->params [i];
7708 res.klass = mono_class_from_mono_type (res.type);
7709 arg_size = mono_type_stack_size (res.type, &align);
7710 #if defined(__arm__) || defined(__mips__)
7711 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7713 res.value = iter->args;
7714 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7715 /* Values are stored as 8 byte register sized objects, but 'value'
7716 * is dereferenced as a pointer in other routines.
7718 res.value = (char*)res.value + 4;
7720 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7721 if (arg_size <= sizeof (gpointer)) {
7723 int padding = arg_size - mono_type_size (res.type, &dummy);
7724 res.value = (guint8*)res.value + padding;
7727 iter->args = (char*)iter->args + arg_size;
7730 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7735 ICALL_EXPORT MonoTypedRef
7736 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7738 guint32 i, arg_size;
7742 i = iter->sig->sentinelpos + iter->next_arg;
7744 g_assert (i < iter->sig->param_count);
7746 while (i < iter->sig->param_count) {
7747 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7749 res.type = iter->sig->params [i];
7750 res.klass = mono_class_from_mono_type (res.type);
7751 /* FIXME: endianess issue... */
7752 arg_size = mono_type_stack_size (res.type, &align);
7753 #if defined(__arm__) || defined(__mips__)
7754 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7756 res.value = iter->args;
7757 iter->args = (char*)iter->args + arg_size;
7759 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7762 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7770 ICALL_EXPORT MonoType*
7771 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7775 i = iter->sig->sentinelpos + iter->next_arg;
7777 g_assert (i < iter->sig->param_count);
7779 return iter->sig->params [i];
7782 ICALL_EXPORT MonoObject*
7783 mono_TypedReference_ToObject (MonoTypedRef* tref)
7786 MonoObject *result = NULL;
7787 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7788 MonoObject** objp = (MonoObject **)tref->value;
7792 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7793 mono_error_set_pending_exception (&error);
7797 ICALL_EXPORT MonoTypedRef
7798 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7801 MonoReflectionField *f;
7803 MonoType *ftype = NULL;
7807 memset (&res, 0, sizeof (res));
7810 g_assert (mono_array_length (fields) > 0);
7812 klass = target->vtable->klass;
7814 for (i = 0; i < mono_array_length (fields); ++i) {
7815 f = mono_array_get (fields, MonoReflectionField*, i);
7817 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7820 if (f->field->parent != klass) {
7821 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7825 p = (guint8*)target + f->field->offset;
7827 p += f->field->offset - sizeof (MonoObject);
7828 klass = mono_class_from_mono_type (f->field->type);
7829 ftype = f->field->type;
7833 res.klass = mono_class_from_mono_type (ftype);
7840 prelink_method (MonoMethod *method, MonoError *error)
7842 const char *exc_class, *exc_arg;
7844 mono_error_init (error);
7845 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7847 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7849 mono_error_set_exception_instance (error,
7850 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7853 /* create the wrapper, too? */
7857 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7861 prelink_method (method->method, &error);
7862 mono_error_set_pending_exception (&error);
7866 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7869 MonoClass *klass = mono_class_from_mono_type (type->type);
7871 gpointer iter = NULL;
7873 mono_class_init_checked (klass, &error);
7874 if (mono_error_set_pending_exception (&error))
7877 while ((m = mono_class_get_methods (klass, &iter))) {
7878 prelink_method (m, &error);
7879 if (mono_error_set_pending_exception (&error))
7884 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7886 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7887 gint32 const **exponents,
7888 gunichar2 const **digitLowerTable,
7889 gunichar2 const **digitUpperTable,
7890 gint64 const **tenPowersList,
7891 gint32 const **decHexDigits)
7893 *mantissas = Formatter_MantissaBitsTable;
7894 *exponents = Formatter_TensExponentTable;
7895 *digitLowerTable = Formatter_DigitLowerTable;
7896 *digitUpperTable = Formatter_DigitUpperTable;
7897 *tenPowersList = Formatter_TenPowersList;
7898 *decHexDigits = Formatter_DecHexDigits;
7902 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7903 * and avoid useless allocations.
7906 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7908 MonoReflectionType *rt;
7912 mono_error_init (error);
7913 for (i = 0; i < type->num_mods; ++i) {
7914 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7919 res = mono_array_new_checked (mono_domain_get (), mono_defaults.systemtype_class, count, error);
7920 return_val_if_nok (error, NULL);
7922 for (i = 0; i < type->num_mods; ++i) {
7923 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7924 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7925 return_val_if_nok (error, NULL);
7927 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7928 return_val_if_nok (error, NULL);
7930 mono_array_setref (res, count, rt);
7937 ICALL_EXPORT MonoArray*
7938 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7941 MonoType *type = param->ClassImpl->type;
7942 MonoClass *member_class = mono_object_class (param->MemberImpl);
7943 MonoMethod *method = NULL;
7946 MonoMethodSignature *sig;
7949 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7950 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7951 method = rmethod->method;
7952 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7953 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7954 if (!(method = prop->property->get))
7955 method = prop->property->set;
7958 char *type_name = mono_type_get_full_name (member_class);
7959 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7960 MonoException *ex = mono_get_exception_not_supported (msg);
7963 mono_set_pending_exception (ex);
7967 image = method->klass->image;
7968 pos = param->PositionImpl;
7969 sig = mono_method_signature (method);
7973 type = sig->params [pos];
7975 res = type_array_from_modifiers (image, type, optional, &error);
7976 mono_error_set_pending_exception (&error);
7981 get_property_type (MonoProperty *prop)
7983 MonoMethodSignature *sig;
7985 sig = mono_method_signature (prop->get);
7987 } else if (prop->set) {
7988 sig = mono_method_signature (prop->set);
7989 return sig->params [sig->param_count - 1];
7994 ICALL_EXPORT MonoArray*
7995 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7998 MonoType *type = get_property_type (property->property);
7999 MonoImage *image = property->klass->image;
8004 res = type_array_from_modifiers (image, type, optional, &error);
8005 mono_error_set_pending_exception (&error);
8010 *Construct a MonoType suited to be used to decode a constant blob object.
8012 * @type is the target type which will be constructed
8013 * @blob_type is the blob type, for example, that comes from the constant table
8014 * @real_type is the expected constructed type.
8017 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
8019 type->type = blob_type;
8020 type->data.klass = NULL;
8021 if (blob_type == MONO_TYPE_CLASS)
8022 type->data.klass = mono_defaults.object_class;
8023 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
8024 /* For enums, we need to use the base type */
8025 type->type = MONO_TYPE_VALUETYPE;
8026 type->data.klass = mono_class_from_mono_type (real_type);
8028 type->data.klass = mono_class_from_mono_type (real_type);
8031 ICALL_EXPORT MonoObject*
8032 property_info_get_default_value (MonoReflectionProperty *property)
8036 MonoProperty *prop = property->property;
8037 MonoType *type = get_property_type (prop);
8038 MonoDomain *domain = mono_object_domain (property);
8039 MonoTypeEnum def_type;
8040 const char *def_value;
8043 mono_class_init (prop->parent);
8045 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
8046 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
8050 def_value = mono_class_get_property_default_value (prop, &def_type);
8052 mono_type_from_blob_type (&blob_type, def_type, type);
8053 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
8055 mono_error_set_pending_exception (&error);
8059 ICALL_EXPORT MonoBoolean
8060 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
8063 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
8064 MonoCustomAttrInfo *cinfo;
8067 mono_class_init_checked (attr_class, &error);
8068 if (mono_error_set_pending_exception (&error))
8071 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
8072 if (!is_ok (&error)) {
8073 mono_error_set_pending_exception (&error);
8078 found = mono_custom_attrs_has_attr (cinfo, attr_class);
8080 mono_custom_attrs_free (cinfo);
8084 ICALL_EXPORT MonoArray*
8085 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
8087 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
8092 mono_class_init_checked (attr_class, &error);
8093 if (mono_error_set_pending_exception (&error))
8097 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
8098 if (!mono_error_ok (&error)) {
8099 mono_error_set_pending_exception (&error);
8106 ICALL_EXPORT MonoArray*
8107 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
8111 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
8112 mono_error_set_pending_exception (&error);
8117 ICALL_EXPORT MonoString*
8118 ves_icall_Mono_Runtime_GetDisplayName (void)
8121 MonoString *display_name;
8123 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
8124 display_name = mono_string_new (mono_domain_get (), info);
8126 return display_name;
8129 ICALL_EXPORT MonoString*
8130 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
8133 MonoString *message;
8137 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
8138 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
8141 message = mono_string_new (mono_domain_get (), "Error looking up error string");
8143 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
8144 if (mono_error_set_pending_exception (&error))
8151 ICALL_EXPORT gpointer
8152 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8154 return GetCurrentProcess ();
8157 ICALL_EXPORT MonoBoolean
8158 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8160 return GetExitCodeProcess (handle, (guint32*) exitcode);
8163 ICALL_EXPORT MonoBoolean
8164 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8166 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8167 return CloseHandle (handle);
8169 return CloseProcess (handle);
8173 ICALL_EXPORT MonoBoolean
8174 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8176 return TerminateProcess (handle, exitcode);
8180 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8182 return WaitForInputIdle (handle, milliseconds);
8185 ICALL_EXPORT MonoBoolean
8186 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8188 return GetProcessWorkingSetSize (handle, min, max);
8191 ICALL_EXPORT MonoBoolean
8192 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8194 return SetProcessWorkingSetSize (handle, min, max);
8197 ICALL_EXPORT MonoBoolean
8198 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8200 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8204 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8206 return mono_process_current_pid ();
8210 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8212 return GetPriorityClass (handle);
8215 ICALL_EXPORT MonoBoolean
8216 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8218 return SetPriorityClass (handle, priorityClass);
8221 #ifndef DISABLE_ICALL_TABLES
8223 #define ICALL_TYPE(id,name,first)
8224 #define ICALL(id,name,func) Icall_ ## id,
8225 #define HANDLES(inner) inner
8228 #include "metadata/icall-def.h"
8234 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8235 #define ICALL(id,name,func)
8237 #define HANDLES(inner) inner
8239 #include "metadata/icall-def.h"
8245 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8246 #define ICALL(id,name,func)
8248 #define HANDLES(inner) inner
8250 guint16 first_icall;
8253 static const IcallTypeDesc
8254 icall_type_descs [] = {
8255 #include "metadata/icall-def.h"
8259 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8262 #define HANDLES(inner) inner
8264 #define ICALL_TYPE(id,name,first)
8267 #ifdef HAVE_ARRAY_ELEM_INIT
8268 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8269 #define MSGSTRFIELD1(line) str##line
8271 static const struct msgstrtn_t {
8272 #define ICALL(id,name,func)
8274 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8275 #include "metadata/icall-def.h"
8277 } icall_type_names_str = {
8278 #define ICALL_TYPE(id,name,first) (name),
8279 #include "metadata/icall-def.h"
8282 static const guint16 icall_type_names_idx [] = {
8283 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8284 #include "metadata/icall-def.h"
8287 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8289 static const struct msgstr_t {
8291 #define ICALL_TYPE(id,name,first)
8292 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8293 #include "metadata/icall-def.h"
8295 } icall_names_str = {
8296 #define ICALL(id,name,func) (name),
8297 #include "metadata/icall-def.h"
8300 static const guint16 icall_names_idx [] = {
8301 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8302 #include "metadata/icall-def.h"
8305 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8311 #define ICALL_TYPE(id,name,first) name,
8312 #define ICALL(id,name,func)
8313 static const char* const
8314 icall_type_names [] = {
8315 #include "metadata/icall-def.h"
8319 #define icall_type_name_get(id) (icall_type_names [(id)])
8323 #define ICALL_TYPE(id,name,first)
8324 #define ICALL(id,name,func) name,
8325 static const char* const
8327 #include "metadata/icall-def.h"
8330 #define icall_name_get(id) icall_names [(id)]
8332 #endif /* !HAVE_ARRAY_ELEM_INIT */
8335 #define HANDLES(inner) inner
8338 #define ICALL_TYPE(id,name,first)
8339 #define ICALL(id,name,func) func,
8340 static const gconstpointer
8341 icall_functions [] = {
8342 #include "metadata/icall-def.h"
8346 #ifdef ENABLE_ICALL_SYMBOL_MAP
8348 #define HANDLES(inner) inner
8351 #define ICALL_TYPE(id,name,first)
8352 #define ICALL(id,name,func) #func,
8353 static const gconstpointer
8354 icall_symbols [] = {
8355 #include "metadata/icall-def.h"
8362 #define ICALL_TYPE(id,name,first)
8363 #define ICALL(id,name,func) 0,
8365 #define HANDLES(inner) 1,
8367 icall_uses_handles [] = {
8368 #include "metadata/icall-def.h"
8373 #endif /* DISABLE_ICALL_TABLES */
8375 static mono_mutex_t icall_mutex;
8376 static GHashTable *icall_hash = NULL;
8377 static GHashTable *jit_icall_hash_name = NULL;
8378 static GHashTable *jit_icall_hash_addr = NULL;
8381 mono_icall_init (void)
8383 #ifndef DISABLE_ICALL_TABLES
8386 /* check that tables are sorted: disable in release */
8389 const char *prev_class = NULL;
8390 const char *prev_method;
8392 for (i = 0; i < Icall_type_num; ++i) {
8393 const IcallTypeDesc *desc;
8396 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8397 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8398 prev_class = icall_type_name_get (i);
8399 desc = &icall_type_descs [i];
8400 num_icalls = icall_desc_num_icalls (desc);
8401 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8402 for (j = 0; j < num_icalls; ++j) {
8403 const char *methodn = icall_name_get (desc->first_icall + j);
8404 if (prev_method && strcmp (prev_method, methodn) >= 0)
8405 g_print ("method %s should come before method %s\n", methodn, prev_method);
8406 prev_method = methodn;
8412 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8413 mono_os_mutex_init (&icall_mutex);
8417 mono_icall_lock (void)
8419 mono_locks_os_acquire (&icall_mutex, IcallLock);
8423 mono_icall_unlock (void)
8425 mono_locks_os_release (&icall_mutex, IcallLock);
8429 mono_icall_cleanup (void)
8431 g_hash_table_destroy (icall_hash);
8432 g_hash_table_destroy (jit_icall_hash_name);
8433 g_hash_table_destroy (jit_icall_hash_addr);
8434 mono_os_mutex_destroy (&icall_mutex);
8438 * mono_add_internal_call:
8439 * @name: method specification to surface to the managed world
8440 * @method: pointer to a C method to invoke when the method is called
8442 * This method surfaces the C function pointed by @method as a method
8443 * that has been surfaced in managed code with the method specified in
8444 * @name as an internal call.
8446 * Internal calls are surfaced to all app domains loaded and they are
8447 * accessibly by a type with the specified name.
8449 * You must provide a fully qualified type name, that is namespaces
8450 * and type name, followed by a colon and the method name, with an
8451 * optional signature to bind.
8453 * For example, the following are all valid declarations:
8455 * "MyApp.Services.ScriptService:Accelerate"
8456 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8458 * You use method parameters in cases where there might be more than
8459 * one surface method to managed code. That way you can register different
8460 * internal calls for different method overloads.
8462 * The internal calls are invoked with no marshalling. This means that .NET
8463 * types like System.String are exposed as `MonoString *` parameters. This is
8464 * different than the way that strings are surfaced in P/Invoke.
8466 * For more information on how the parameters are marshalled, see the
8467 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8470 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8471 * reference for more information on the format of method descriptions.
8474 mono_add_internal_call (const char *name, gconstpointer method)
8478 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8480 mono_icall_unlock ();
8483 #ifndef DISABLE_ICALL_TABLES
8485 #ifdef HAVE_ARRAY_ELEM_INIT
8487 compare_method_imap (const void *key, const void *elem)
8489 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8490 return strcmp (key, method_name);
8494 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8496 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);
8499 return (nameslot - &icall_names_idx [0]);
8503 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8505 gsize slotnum = find_slot_icall (imap, name);
8508 return (gboolean)icall_uses_handles [slotnum];
8512 find_method_icall (const IcallTypeDesc *imap, const char *name)
8514 gsize slotnum = find_slot_icall (imap, name);
8517 return (gpointer)icall_functions [slotnum];
8521 compare_class_imap (const void *key, const void *elem)
8523 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8524 return strcmp (key, class_name);
8527 static const IcallTypeDesc*
8528 find_class_icalls (const char *name)
8530 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);
8533 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8536 #else /* HAVE_ARRAY_ELEM_INIT */
8539 compare_method_imap (const void *key, const void *elem)
8541 const char** method_name = (const char**)elem;
8542 return strcmp (key, *method_name);
8546 find_slot_icall (const IcallTypeDesc *imap, const char *name)
8548 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8551 return nameslot - icall_names;
8555 find_method_icall (const IcallTypeDesc *imap, const char *name)
8557 gsize slotnum = find_slot_icall (imap, name);
8560 return (gpointer)icall_functions [slotnum];
8564 find_uses_handles_icall (const IcallTypeDesc *imap, const char *name)
8566 gsize slotnum = find_slot_icall (imap, name);
8569 return (gboolean)icall_uses_handles [slotnum];
8573 compare_class_imap (const void *key, const void *elem)
8575 const char** class_name = (const char**)elem;
8576 return strcmp (key, *class_name);
8579 static const IcallTypeDesc*
8580 find_class_icalls (const char *name)
8582 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8585 return &icall_type_descs [nameslot - icall_type_names];
8588 #endif /* HAVE_ARRAY_ELEM_INIT */
8590 #endif /* DISABLE_ICALL_TABLES */
8593 * we should probably export this as an helper (handle nested types).
8594 * Returns the number of chars written in buf.
8597 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8599 int nspacelen, cnamelen;
8600 nspacelen = strlen (klass->name_space);
8601 cnamelen = strlen (klass->name);
8602 if (nspacelen + cnamelen + 2 > bufsize)
8605 memcpy (buf, klass->name_space, nspacelen);
8606 buf [nspacelen ++] = '.';
8608 memcpy (buf + nspacelen, klass->name, cnamelen);
8609 buf [nspacelen + cnamelen] = 0;
8610 return nspacelen + cnamelen;
8613 #ifdef DISABLE_ICALL_TABLES
8615 no_icall_table (void)
8617 g_assert_not_reached ();
8622 * mono_lookup_internal_call_full:
8623 * @method: the method to look up
8624 * @uses_handles: out argument if method needs handles around managed objects.
8626 * Returns a pointer to the icall code for the given method. If
8627 * uses_handles is not NULL, it will be set to TRUE if the method
8628 * needs managed objects wrapped using the infrastructure in handle.h
8630 * If the method is not found, warns and returns NULL.
8633 mono_lookup_internal_call_full (MonoMethod *method, mono_bool *uses_handles)
8638 int typelen = 0, mlen, siglen;
8640 #ifndef DISABLE_ICALL_TABLES
8641 const IcallTypeDesc *imap = NULL;
8644 g_assert (method != NULL);
8646 if (method->is_inflated)
8647 method = ((MonoMethodInflated *) method)->declaring;
8649 if (method->klass->nested_in) {
8650 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8654 mname [pos++] = '/';
8657 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8663 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8668 #ifndef DISABLE_ICALL_TABLES
8669 imap = find_class_icalls (mname);
8672 mname [typelen] = ':';
8673 mname [typelen + 1] = ':';
8675 mlen = strlen (method->name);
8676 memcpy (mname + typelen + 2, method->name, mlen);
8677 sigstart = mname + typelen + 2 + mlen;
8680 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8681 siglen = strlen (tmpsig);
8682 if (typelen + mlen + siglen + 6 > sizeof (mname))
8685 memcpy (sigstart + 1, tmpsig, siglen);
8686 sigstart [siglen + 1] = ')';
8687 sigstart [siglen + 2] = 0;
8692 res = g_hash_table_lookup (icall_hash, mname);
8695 *uses_handles = FALSE;
8696 mono_icall_unlock ();;
8699 /* try without signature */
8701 res = g_hash_table_lookup (icall_hash, mname);
8704 *uses_handles = FALSE;
8705 mono_icall_unlock ();
8709 #ifdef DISABLE_ICALL_TABLES
8710 mono_icall_unlock ();
8711 /* Fail only when the result is actually used */
8712 /* mono_marshal_get_native_wrapper () depends on this */
8713 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8714 return ves_icall_System_String_ctor_RedirectToCreateString;
8716 return no_icall_table;
8718 /* it wasn't found in the static call tables */
8720 mono_icall_unlock ();
8723 res = find_method_icall (imap, sigstart - mlen);
8726 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8727 mono_icall_unlock ();
8730 /* try _with_ signature */
8732 res = find_method_icall (imap, sigstart - mlen);
8735 *uses_handles = find_uses_handles_icall (imap, sigstart - mlen);
8736 mono_icall_unlock ();
8740 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8741 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8742 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8743 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8744 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");
8745 g_print ("If you see other errors or faults after this message they are probably related\n");
8746 g_print ("and you need to fix your mono install first.\n");
8748 mono_icall_unlock ();
8755 mono_lookup_internal_call (MonoMethod *method)
8757 return mono_lookup_internal_call_full (method, NULL);
8760 #ifdef ENABLE_ICALL_SYMBOL_MAP
8762 func_cmp (gconstpointer key, gconstpointer p)
8764 return (gsize)key - (gsize)*(gsize*)p;
8769 * mono_lookup_icall_symbol:
8771 * Given the icall METHOD, returns its C symbol.
8774 mono_lookup_icall_symbol (MonoMethod *m)
8776 #ifdef DISABLE_ICALL_TABLES
8777 g_assert_not_reached ();
8780 #ifdef ENABLE_ICALL_SYMBOL_MAP
8784 static gconstpointer *functions_sorted;
8785 static const char**symbols_sorted;
8786 static gboolean inited;
8791 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8792 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8793 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8794 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8795 /* Bubble sort the two arrays */
8799 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8800 if (functions_sorted [i] > functions_sorted [i + 1]) {
8803 tmp = functions_sorted [i];
8804 functions_sorted [i] = functions_sorted [i + 1];
8805 functions_sorted [i + 1] = tmp;
8806 tmp = symbols_sorted [i];
8807 symbols_sorted [i] = symbols_sorted [i + 1];
8808 symbols_sorted [i + 1] = tmp;
8815 func = mono_lookup_internal_call (m);
8818 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8822 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8824 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8825 g_assert_not_reached ();
8832 type_from_typename (char *type_name)
8834 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8836 if (!strcmp (type_name, "int"))
8837 klass = mono_defaults.int_class;
8838 else if (!strcmp (type_name, "ptr"))
8839 klass = mono_defaults.int_class;
8840 else if (!strcmp (type_name, "void"))
8841 klass = mono_defaults.void_class;
8842 else if (!strcmp (type_name, "int32"))
8843 klass = mono_defaults.int32_class;
8844 else if (!strcmp (type_name, "uint32"))
8845 klass = mono_defaults.uint32_class;
8846 else if (!strcmp (type_name, "int8"))
8847 klass = mono_defaults.sbyte_class;
8848 else if (!strcmp (type_name, "uint8"))
8849 klass = mono_defaults.byte_class;
8850 else if (!strcmp (type_name, "int16"))
8851 klass = mono_defaults.int16_class;
8852 else if (!strcmp (type_name, "uint16"))
8853 klass = mono_defaults.uint16_class;
8854 else if (!strcmp (type_name, "long"))
8855 klass = mono_defaults.int64_class;
8856 else if (!strcmp (type_name, "ulong"))
8857 klass = mono_defaults.uint64_class;
8858 else if (!strcmp (type_name, "float"))
8859 klass = mono_defaults.single_class;
8860 else if (!strcmp (type_name, "double"))
8861 klass = mono_defaults.double_class;
8862 else if (!strcmp (type_name, "object"))
8863 klass = mono_defaults.object_class;
8864 else if (!strcmp (type_name, "obj"))
8865 klass = mono_defaults.object_class;
8866 else if (!strcmp (type_name, "string"))
8867 klass = mono_defaults.string_class;
8868 else if (!strcmp (type_name, "bool"))
8869 klass = mono_defaults.boolean_class;
8870 else if (!strcmp (type_name, "boolean"))
8871 klass = mono_defaults.boolean_class;
8873 g_error ("%s", type_name);
8874 g_assert_not_reached ();
8876 return &klass->byval_arg;
8880 * LOCKING: Take the corlib image lock.
8882 MonoMethodSignature*
8883 mono_create_icall_signature (const char *sigstr)
8888 MonoMethodSignature *res, *res2;
8889 MonoImage *corlib = mono_defaults.corlib;
8891 mono_image_lock (corlib);
8892 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8893 mono_image_unlock (corlib);
8898 parts = g_strsplit (sigstr, " ", 256);
8907 res = mono_metadata_signature_alloc (corlib, len - 1);
8912 * Under windows, the default pinvoke calling convention is STDCALL but
8915 res->call_convention = MONO_CALL_C;
8918 res->ret = type_from_typename (parts [0]);
8919 for (i = 1; i < len; ++i) {
8920 res->params [i - 1] = type_from_typename (parts [i]);
8925 mono_image_lock (corlib);
8926 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8928 res = res2; /*Value is allocated in the image pool*/
8930 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8931 mono_image_unlock (corlib);
8937 mono_find_jit_icall_by_name (const char *name)
8939 MonoJitICallInfo *info;
8940 g_assert (jit_icall_hash_name);
8943 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8944 mono_icall_unlock ();
8949 mono_find_jit_icall_by_addr (gconstpointer addr)
8951 MonoJitICallInfo *info;
8952 g_assert (jit_icall_hash_addr);
8955 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8956 mono_icall_unlock ();
8962 * mono_get_jit_icall_info:
8964 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8965 * caller should access it while holding the icall lock.
8968 mono_get_jit_icall_info (void)
8970 return jit_icall_hash_name;
8974 * mono_lookup_jit_icall_symbol:
8976 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8979 mono_lookup_jit_icall_symbol (const char *name)
8981 MonoJitICallInfo *info;
8982 const char *res = NULL;
8985 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8987 res = info->c_symbol;
8988 mono_icall_unlock ();
8993 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8996 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8997 mono_icall_unlock ();
9001 * 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
9002 * icalls without wrappers in some cases.
9005 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
9007 MonoJitICallInfo *info;
9014 if (!jit_icall_hash_name) {
9015 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
9016 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
9019 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
9020 g_warning ("jit icall already defined \"%s\"\n", name);
9021 g_assert_not_reached ();
9024 info = g_new0 (MonoJitICallInfo, 1);
9029 info->c_symbol = c_symbol;
9030 info->no_raise = no_raise;
9033 info->wrapper = func;
9035 info->wrapper = NULL;
9038 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
9039 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
9041 mono_icall_unlock ();
9046 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
9048 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);